Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK!ECispmanager/httpd_config.xmlnu[ $HOSTNAME apache apache 0 / 0 60M /tmp/lshttpd/swap 1 0 1 1 /usr/sbin/httpd /etc/httpd/conf/httpd.conf %AP_PORT_OFFSET% /manager/,/mancgi/ %PHP_SUEXEC% 10 $SERVER_ROOT/conf/mime.properties 0 2 86400 1 %ADMIN_EMAIL% $SERVER_ROOT/admin/ $SERVER_ROOT/logs/error.log DEBUG 0 2000M 1 $SERVER_ROOT/logs/access.log 10M 30 0 index.html, index.php, index.htm 31 .htaccess 1 image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800 10000 10000 120 10000 0 10 0 0 best 4096 20M 256K 40M 1 1 4 1 null 8192 16380 500M 4K 500M 1 1 default 1 1 0 1 000 000 002 002 0 0 0 0 10000 10000 15 300 20 11 10 0 60 120 1250M 1300M 400 450 0 0 deny,log,status:403 1 / /etc/* /dev/* $SERVER_ROOT/conf/* $SERVER_ROOT/admin/conf/* ALL 35 PHP_LSAPI_CHILDREN=35 60 0 1 0 60 1400 1500 1 5 LSAPI_MAX_IDLE=60 60 0 60 0 50 1 300 3 400 500 PK!frontpage/conf/srm.confnu[PK!frontpage/conf/access.confnu[PK!frontpage/conf/httpd.confnu[PK!QOhsphere/httpd_config.xmlnu[ $HOSTNAME httpd httpd 0 / 0 60M /tmp/lshttpd/swap 1 0 1 1 /hsphere/local/config/httpd/httpd.conf %AP_PORT_OFFSET% 0 %PHP_SUEXEC% 10 $SERVER_ROOT/conf/mime.properties 0 2 86400 1 %ADMIN_EMAIL% $SERVER_ROOT/admin/ $SERVER_ROOT/logs/error.log DEBUG 0 10M 1 $SERVER_ROOT/logs/access.log 10M 30 0 index.html, index.php, index.htm 31 .htaccess 1 image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800 10000 10000 120 10000 0 10 0 0 best 4096 20M 256K 40M 1 1 4 1 null 8192 16380 500M 4K 500M 1 1 default 1 1 0 000 000 0 0 0 0 10000 10000 15 300 20 11 10 0 60 120 1250M 1300M 400 450 0 0 deny,log,status:403 1 / /etc/* /dev/* $SERVER_ROOT/conf/* $SERVER_ROOT/admin/conf/* ALL 35 PHP_LSAPI_CHILDREN=35 60 0 1 0 60 1400 1500 1 5 LSAPI_MAX_IDLE=60 60 0 60 0 50 1 300 3 200 300 PK!os4^{{cwp/httpd_config.xmlnu[ $HOSTNAME nobody nobody 0 / 0 60M /tmp/lshttpd/swap 1 0 1 2 /usr/local/apache/bin/httpd /usr/local/apache/conf/httpd.conf 0 0 %PHP_SUEXEC% 10 $SERVER_ROOT/conf/mime.properties 1 0 2 86400 1 %ADMIN_EMAIL% $SERVER_ROOT/admin/ /usr/local/apache/logs/error_log DEBUG 0 2000M 1 $SERVER_ROOT/logs/access.log 2000M 30 0 index.html, index.php, index.htm 31 .htaccess 1 image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800 10000 10000 120 10000 0 10 0 0 best 4096 20M 256K 40M 1 1 4 1 null 8192 16380 500M 8K 500M 1 1 default 1 1 0 1 000 000 000 000 0 0 0 0 10000 10000 15 300 200 11 10 0 60 120 1450M 1500M 400 450 0 0 deny,log,status:403 1 / /etc/* /dev/* $SERVER_ROOT/conf/* $SERVER_ROOT/admin/conf/* ALL 35 PHP_LSAPI_CHILDREN=35 60 0 1 0 60 1400 1500 1 5 LSAPI_MAX_IDLE=60 60 0 60 0 50 1 300 3 400 500 PK!Kڕmodsec/inspectmulti.shnu7m#!/bin/sh if [ $# -lt 2 ] ; then echo "miss parameter." else RUNAVCMD=$1 shift for var in "$@" do $RUNAVCMD $var done fi PK!阼O webcachemgr/MIN_VERnu[1.17.10.1 PK!4yTuuwebcachemgr/autoloader.phpnuIw8{webcachemgr/src/LogEntry.phpnuIwmsg = $msg; $this->lvl = $lvl; $this->timestamp = time(); } /** * * @param string $msg */ public function append( $msg ) { $this->msg .= $msg; } /** * * @return int */ public function getLvl() { return $this->lvl; } /** * * @return string */ public function getMsg() { $msg = ($this->prefix == null) ? '' : "{$this->prefix} "; if ( $this->msg ) { $msg .= $this->msg; } return $msg; } /** * * @param int $logLvl * @return string * @throws LSCMException Thrown indirectly. */ public function getOutput( $logLvl ) { if ( $this->lvl > $logLvl ) { return ''; } $timestamp = date('Y-m-d H:i:s', $this->timestamp); $addTagInfo = Logger::getAdditionalTagInfo(); $lvl = '[' . Logger::getLvlDescr($this->lvl) . ']'; $msg = $this->getMsg(); return "{$timestamp} {$addTagInfo} {$lvl} {$msg}\n"; } } PK!g!,webcachemgr/src/Panel/CustomPanelExample.phpnuIwpanelName = 'customPanel'; /** * Optionally set a default server-level cache root directory. * This is used when no explicit cache root has been configured. * Example: $this->defaultSvrCacheRoot = '/var/lscache/'; */ /** @noinspection PhpUnhandledExceptionInspection */ parent::init2(); } /** * Gets a list of found docroots and associated server names. * Only needed for lscmctl 'scan' command. * * @since 1.17.8 */ protected function prepareDocrootMap() { /** * This function can be left as is if you do not intend to use * the lscmctl 'scan' command. In this case lscmctl command * 'addinstalls' can be used to add WordPress installations to the * custom data file instead. * * If you would like to add support for the lscmctl 'scan' command, * implement this function so that it searches for all document root, * server name, and server alias groups and uses this information to * populate $this->docRootMap as follows: * * array( * 'docroots' => array(index => docroot), * 'names' => array("server name/alias" => index) * ); * * Where the value of each discovered servername/alias in the 'names' * array matches the index of the related document root in the * 'docroots' array. */ $this->docRootMap = array('docroots' => array(), 'names' => array()); } /** * Returns the PHP binary split into a path token and an options string. * * Override this method to detect the correct PHP binary for the given * WordPress installation. The $wpInstall object provides context such as * the install's document root and owner information, e.g.: * $ownerInfo = $wpInstall->getOwnerInfo(); * $user = $ownerInfo['user_name']; * * SECURITY NOTE * ----------------------------------------------------------------- * The framework will escapeshellarg() the binPath token but will * interpolate the optionsString RAW into the inner shell command. * Treat optionsString as a shell-active string: * - Only include flags you have composed in source code, or that * come from $this->phpOptions (library-controlled). * - If any options-fragment value originates from configuration or * external data, escapeshellarg() that value before appending it. * * @since 1.17.10 * * @param WPInstall $wpInstall * * @return PhpBinaryParts */ public function getPhpBinaryParts( WPInstall $wpInstall ) { $phpBin = 'php'; return new PhpBinaryParts($phpBin, $this->phpOptions); } /** * @deprecated since 1.17.10 Override getPhpBinaryParts() instead. * * @since 1.17.8 * * @param WPInstall $wpInstall * * @return string */ public function getPhpBinary( WPInstall $wpInstall ) { $parts = $this->getPhpBinaryParts($wpInstall); $options = $parts->getOptionsString(); return $options === '' ? $parts->getBinPath() : $parts->getBinPath() . ' ' . $options; } } PK!a((&webcachemgr/src/Panel/ControlPanel.phpnuIw (index => docroots), * 'names' => (servername => index) */ protected $docRootMap = null; /** * @since 1.9.7 * @var string */ protected static $minAPIFilePath = ''; /** * @var null|ControlPanel Object that extends ControlPanel abstract class. */ protected static $instance; /** * * @throws LSCMException Thrown indirectly by $this->init2() call. */ protected function __construct() { $this->init2(); } /** * Temporary function name until existing deprecated public static init() * function is removed. * * @since 1.13.2 * * @throws LSCMException Thrown indirectly by $this->initConfPaths() call. */ protected function init2() { /** * output_handler value cleared to avoid compressed output through * 'ob_gzhandler' etc. */ $this->phpOptions = '-d disable_functions=ini_set -d opcache.enable=0 ' . '-d max_execution_time=' . static::PHP_TIMEOUT . ' -d memory_limit=512M -d register_argc_argv=1 ' . '-d zlib.output_compression=0 -d output_handler= ' . '-d safe_mode=0 -d open_basedir='; $this->initConfPaths(); } /** * Deprecated 02/04/19 as this function will be made private. * Use getClassInstance() with a fully qualified class name as a parameter * instead. * * Sets static::$instance with a new $className instance if it has not been * set already. An exception will be thrown if static::$instance has already * been set to a different class name than the one provided. * * @deprecated * * @param string $className A fully qualified control panel class name. * * @return ControlPanel|null Object that extends ControlPanel abstract * class. * * @throws LSCMException Thrown when unable to include custom panel file. * @throws LSCMException Thrown when class 'CustomPanel' does not extend * class '\Lsc\Wp\Panel\CustomPanelBase'. * @throws LSCMException Re-thrown when "new $className()" call throws an * exception. * @throws LSCMException Thrown when an instance of a different * ControlPanel/CustomPanel extending class has already been created. */ public static function initByClassName( $className ) { if ( static::$instance == null ) { if ( $className == 'custom' ) { $lsws_home = realpath(__DIR__ . '/../../../../'); $customPanelFile = "$lsws_home/admin/lscdata/custom/CustomPanel.php"; if ( ! file_exists($customPanelFile) || ! include_once $customPanelFile ) { throw new LSCMException( "Unable to include file $customPanelFile" ); } $className = '\Lsc\Wp\Panel\CustomPanel'; $isSubClass = is_subclass_of( $className, '\Lsc\Wp\Panel\CustomPanelBase' ); if ( ! $isSubClass ) { throw new LSCMException( 'Class CustomPanel must extend class ' . '\Lsc\Wp\Panel\CustomPanelBase' ); } } try{ static::$instance = new $className(); } catch ( Exception $e ){ throw new LSCMException( "Could not create object with class name $className. " . "Error: {$e->getMessage()}" ); } } else { $instanceClassName = '\\' . get_class(static::$instance); if ( $instanceClassName != $className ) { throw new LSCMException( "Could not initialize $className instance as an instance " . "of another class ($instanceClassName) has already " . 'been created.' ); } } return static::$instance; } /** * Deprecated 01/14/19. Use initByClassName() instead. * * @deprecated * * @param string $name * * @return ControlPanel Object that extends ControlPanel abstract class. * * @throws LSCMException Thrown when static::$instance is not null. * @throws LSCMException Thrown when provided $name is not recognized. * @throws LSCMException Thrown indirectly by static::initByClassName() * call. */ public static function init( $name ) { if ( static::$instance != null ) { throw new LSCMException( 'ControlPanel cannot be initialized twice.' ); } switch ($name) { case static::PANEL_CPANEL: $className = 'CPanel'; break; case static::PANEL_PLESK: $className = 'Plesk'; break; default: throw new LSCMException( "Control panel '$name' is not supported." ); } return static::initByClassName("\Lsc\Wp\Panel\\$className"); } /** * Returns current ControlPanel instance when no $className is given. When * $className is provided, an instance of $className will also be * initialized if it has not yet been initialized already. * * @param string $className Fully qualified class name. * * @return ControlPanel Object that extends ControlPanel abstract class. * * @throws LSCMException Thrown when static::$instance is null. * @throws LSCMException Thrown indirectly by static::initByClassName() * call. */ public static function getClassInstance( $className = '' ) { if ( $className != '' ) { static::initByClassName($className); } elseif ( static::$instance == null ) { throw new LSCMException( 'Could not get instance, ControlPanel not initialized. ' ); } return static::$instance; } /** * Deprecated on 02/06/19. Use getClassInstance() instead. * * @deprecated * * @return ControlPanel Object that extends ControlPanel abstract class. * * @throws LSCMException Thrown indirectly by static::getClassInstance() * call. */ public static function getInstance() { return static::getClassInstance(); } /** * * @param string $serverName * * @return string|null * * @throws LSCMException Thrown indirectly by $this->prepareDocrootMap() * call. */ public function mapDocRoot( $serverName ) { if ( $this->docRootMap == null ) { $this->prepareDocrootMap(); } if ( isset($this->docRootMap['names'][$serverName]) ) { $index = $this->docRootMap['names'][$serverName]; return $this->docRootMap['docroots'][$index]; } // error out return null; } /** * * @return bool * * @throws LSCMException Thrown indirectly by $this->getServerCacheRoot() * call. * @throws LSCMException Thrown indirectly by $this->getVHCacheRoot() call. */ public function areCacheRootsSet() { $ret = true; if ( static::NOT_SET == $this->getServerCacheRoot() ) { $ret = false; } if ( static::NOT_SET == $this->getVHCacheRoot() ) { $ret = false; } return $ret; } /** * * @throws LSCMException Thrown when cache is not enabled for the current * LiteSpeed license. * @throws LSCMException Thrown indirectly by $this->getServerCacheRoot() * call. * @throws LSCMException Thrown indirectly by $this->setServerCacheRoot() * call. * @throws LSCMException Thrown indirectly by $this->getVHCacheRoot() call. * @throws LSCMException Thrown indirectly by $this->setVHCacheRoot() call. */ public function verifyCacheSetup() { if ( !$this->isCacheEnabled() ) { throw new LSCMException( 'LSCache is not included in the current LiteSpeed license. ' . 'Please purchase the LSCache add-on or upgrade to a ' . 'license type that includes LSCache and try again.', LSCMException::E_PERMISSION ); } $restartRequired = false; if ( static::NOT_SET == $this->getServerCacheRoot() ) { $this->setServerCacheRoot(); $restartRequired = true; } if ( static::NOT_SET == $this->getVHCacheRoot() ) { $this->setVHCacheRoot(); $restartRequired = true; } if ( $restartRequired ) { Util::restartLsws(); } } /** * * @param string $vhCacheRoot * * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->writeVHCacheRoot() * call. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->applyVHConfChanges() * call. */ public function setVHCacheRoot( $vhCacheRoot = 'lscache' ) { $this->log('Attempting to set VH cache root...', Logger::L_VERBOSE); if ( $vhCacheRoot !== '' && $vhCacheRoot[0] === '/' ) { $basePath = preg_replace('#/\$vh_user$#', '', $vhCacheRoot); if ( !Util::isSafeAbsPath($basePath) ) { throw new LSCMException( 'Refusing to write unsafe absolute VH cache root path.' ); } } elseif ( !preg_match('#^[A-Za-z0-9_\-]+$#', $vhCacheRoot) ) { throw new LSCMException( 'Refusing to write unsafe VH cache root: non-absolute values ' . 'must contain only [A-Za-z0-9_-] characters.' ); } if ( !file_exists($this->apacheVHConf) ) { $this->createVHConfAndSetCacheRoot( $this->apacheVHConf, $vhCacheRoot ); } else { $this->writeVHCacheRoot($this->apacheVHConf, $vhCacheRoot); } $this->vhCacheRoot = $vhCacheRoot; $this->log( "Virtual Host cache root set to $vhCacheRoot", Logger::L_INFO ); if ( $this->vhCacheRoot[0] == '/' && !file_exists($this->vhCacheRoot) ) { /** * 01/29/19: Temporarily create top virtual host cache root * directory to avoid LSWS setting incorrect owner/group and * permissions for the directory outside the cage. */ mkdir(str_replace('/$vh_user', '', $vhCacheRoot), 0755, true); } $this->applyVHConfChanges(); } /** * * @return bool * * @throws LSCMException Thrown when status file is not found. * @throws LSCMException Thrown when status file cannot be read. * */ public function isCacheEnabled() { $statusFile = '/tmp/lshttpd/.status'; /** * V7 (CWE-59 symlink-following / CWE-367 TOCTOU) — /tmp/lshttpd/.status * is a fixed path in a sticky, world-writable directory and is read * here in an elevated context. Refuse to follow a symlink and require * the opened descriptor to be a regular file owned by a trusted system * account whose dev/inode matches the pre-open lstat (so a symlink * swapped in during the open window is detected rather than followed). * * LiteSpeed writes this file as its admin user (lsadm), not root, so * accept root OR lsadm as the owner. The containing directory * (/tmp/lshttpd) is not tenant-writable, so an unprivileged user cannot * pre-create or symlink the file regardless. */ if ( is_link($statusFile) || !file_exists($statusFile) ) { throw new LSCMException( 'Cannot determine LSCache availability. Please start/switch to ' . 'LiteSpeed Web Server before trying again.', LSCMException::E_PERMISSION ); } $pre = @lstat($statusFile); if ( $pre === false || ($f = @fopen($statusFile, 'rb')) === false ) { throw new LSCMException( 'Cannot determine LSCache availability.', LSCMException::E_PERMISSION ); } $st = fstat($f); $allowedUids = [ 0 ]; if ( function_exists('posix_getpwnam') && ($pw = @posix_getpwnam('lsadm')) !== false && isset($pw['uid']) ) { $allowedUids[] = (int)$pw['uid']; } if ( $st === false || ($st['mode'] & 0170000) !== 0100000 || !in_array($st['uid'], $allowedUids, true) || $st['ino'] !== $pre['ino'] || $st['dev'] !== $pre['dev'] ) { fclose($f); throw new LSCMException( 'Cannot determine LSCache availability.', LSCMException::E_PERMISSION ); } fseek($f, -128, SEEK_END); $line = fread($f, 128); fclose($f); if ( preg_match('/FEATURES: ([0-9.]+)/', $line, $m) && ($m[1] & 1) == 1 ) { return true; } return false; } /** * return array of docroots, can set index from and batch * * @param int $offset * @param null|int $length * * @return string[] * * @throws LSCMException Thrown indirectly by $this->prepareDocrootMap() * call. */ public function getDocRoots( $offset = 0, $length = null ) { if ( $this->docRootMap == null ) { $this->prepareDocrootMap(); } return array_slice($this->docRootMap['docroots'], $offset, $length); } /** * Used in PleskEscalate. * * @return array[] * * @noinspection PhpUnused * @noinspection PhpDocMissingThrowsInspection */ public function getDocrootMap() { if ( $this->docRootMap == null ) { /** * LSCMException not thrown in Plesk implementation. * @noinspection PhpUnhandledExceptionInspection */ $this->prepareDocrootMap(); } return $this->docRootMap; } /** * * @return string */ public function getDefaultSvrCacheRoot() { return $this->defaultSvrCacheRoot; } /** * * @return string * * @throws LSCMException Thrown indirectly by $this->initCacheRoots() call. */ public function getServerCacheRoot() { if ( $this->serverCacheRoot == null ) { $this->initCacheRoots(); } return $this->serverCacheRoot; } /** * * @return string * * @throws LSCMException Thrown indirectly by $this->initCacheRoots() call. */ public function getVHCacheRoot() { if ( $this->vhCacheRoot == null ) { $this->initCacheRoots(); } return $this->vhCacheRoot; } /** * * @return void * * @throws LSCMException Thrown in some existing implementations. */ abstract protected function initConfPaths(); /** * * @throws LSCMException Thrown in some existing implementations. */ abstract protected function prepareDocrootMap(); /** * Returns the PHP binary split into a path token and an options string. * * Override this in panel subclasses instead of getPhpBinary(). The * default implementation wraps the legacy getPhpBinary() string for * backward compatibility with older CustomPanel implementations that * only override that method. * * @since 1.17.10 * * @param WPInstall $wpInstall * * @return PhpBinaryParts * * @throws LSCMException Thrown indirectly by $this->getPhpBinary(). */ public function getPhpBinaryParts( WPInstall $wpInstall ) { $legacy = trim($this->getPhpBinary($wpInstall)); $parts = preg_split('/\s+/', $legacy, 2); return new PhpBinaryParts( $parts[0], isset($parts[1]) ? $parts[1] : '' ); } /** * @deprecated since 1.17.10 Override getPhpBinaryParts() instead. * * @param WPInstall $wpInstall * * @return string * * @throws LSCMException Thrown in some existing implementations. */ abstract public function getPhpBinary( WPInstall $wpInstall ); /** * Searches the given directories '.conf' files for CacheRoot setting. * * Note: Visibility is public to better accommodate escalation functions. * * @param string $confDir Directory to be searched. * * @return string */ public function cacheRootSearch( $confDir ) { $files = new DirectoryIterator($confDir); foreach ( $files as $file ) { $filename = $file->getFilename(); if ( strlen($filename) > 5 && substr_compare($filename, '.conf', -5) === 0 ) { $cacheRoot = $this->getCacheRootSetting($file->getPathname()); if ( $cacheRoot != '' ) { return $cacheRoot; } } } return ''; } /** * Note: Visibility is public to better accommodate escalation functions. * * @param string $file * * @return string */ public function getCacheRootSetting( $file ) { if ( file_exists($file) ) { $matchFound = preg_match( '/^\s*CacheRoot (.+)/im', file_get_contents($file), $matches ); if ( $matchFound ) { return trim($matches[1]); } } return ''; } /** * Note: Visibility is public to better accommodate escalation functions. * * @return string */ public function getLSWSCacheRootSetting() { $serverConf = __DIR__ . '/../../../../conf/httpd_config.xml'; if ( file_exists($serverConf) ) { $matchFound = preg_match( '!(.+)!i', file_get_contents($serverConf), $matches ); if ( $matchFound ) { return trim($matches[1]); } } return ''; } abstract protected function serverCacheRootSearch(); abstract protected function vhCacheRootSearch(); /** * Checks server and VH conf files for cacheroot settings and populates in * object if found. * * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->log() call. */ protected function initCacheRoots() { $svrCacheRoot = $this->serverCacheRootSearch(); if ( $svrCacheRoot == '' ) { $svrCacheRoot = $this->getLSWSCacheRootSetting(); } $vhCacheRoot = $this->vhCacheRootSearch(); if ( $svrCacheRoot ) { $this->serverCacheRoot = $svrCacheRoot; $this->log( "Server level cache root is $svrCacheRoot.", Logger::L_DEBUG ); } else { $this->serverCacheRoot = static::NOT_SET; $this->log('Server level cache root is not set.', Logger::L_NOTICE); } if ( $vhCacheRoot ) { $this->vhCacheRoot = $vhCacheRoot; $this->log( "Virtual Host level cache root is $vhCacheRoot.", Logger::L_DEBUG ); } else { $this->vhCacheRoot = static::NOT_SET; $this->log( 'Virtual Host level cache root is not set.', Logger::L_INFO ); } } /** * * @param string $msg * @param int $level * * @throws LSCMException Thrown indirectly by Logger::error() call. * @throws LSCMException Thrown indirectly by Logger::warn() call. * @throws LSCMException Thrown indirectly by Logger::notice() call. * @throws LSCMException Thrown indirectly by Logger::info() call. * @throws LSCMException Thrown indirectly by Logger::verbose() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. */ protected function log( $msg, $level ) { $msg = "$this->panelName - $msg"; switch ($level) { case Logger::L_ERROR: Logger::error($msg); break; case Logger::L_WARN: Logger::warn($msg); break; case Logger::L_NOTICE: Logger::notice($msg); break; case Logger::L_INFO: Logger::info($msg); break; case Logger::L_VERBOSE: Logger::verbose($msg); break; case Logger::L_DEBUG: Logger::debug($msg); break; //no default } } /** * * @param string $svrCacheRoot * * @throws LSCMException Thrown directly and indirectly. */ public function setServerCacheRoot( $svrCacheRoot = '' ) { $this->log('Attempting to set server cache root...', Logger::L_VERBOSE); if ( $svrCacheRoot != '' ) { $cacheroot = $svrCacheRoot; } else { $cacheroot = $this->defaultSvrCacheRoot; } if ( !Util::isSafeAbsPath($cacheroot) ) { throw new LSCMException( 'Refusing to write unsafe server cache root path.' ); } $cacheRootLine = "\nCacheRoot $cacheroot\n\n\n"; if ( !file_exists($this->apacheConf) ) { file_put_contents($this->apacheConf, $cacheRootLine); chmod($this->apacheConf, 0644); $this->log("Created file $this->apacheConf", Logger::L_VERBOSE); } else { if ( !is_writable($this->apacheConf) ) { throw new LSCMException( 'Apache Config is not writeable. No changes made.' ); } if ( !Util::createBackup($this->apacheConf) ) { throw new LSCMException( 'Could not backup Apache config. No changes made.' ); } else { $file_contents = file($this->apacheConf); $pattern = '/^\s*/im'; if ( preg_grep($pattern, $file_contents) ) { if ( preg_grep('/^\s*CacheRoot +/im', $file_contents) ) { $file_contents = preg_replace( '/^\s*CacheRoot +.+/im', "CacheRoot $cacheroot", $file_contents ); } else { $file_contents = preg_replace( '/^\s*/im', "\nCacheRoot $cacheroot", $file_contents ); } } else { array_unshift($file_contents, $cacheRootLine); } file_put_contents($this->apacheConf, $file_contents); } } $this->serverCacheRoot = $cacheroot; $this->log("Server level cache root set to $cacheroot", Logger::L_INFO); if ( file_exists($cacheroot) ) { exec('/bin/rm -rf ' . escapeshellarg($cacheroot)); $this->log( 'Server level cache root directory removed for proper ' . 'permission.', Logger::L_DEBUG ); } } /** * * @param array $file_contents * @param string $vhCacheRoot * * @return array */ abstract protected function addVHCacheRootSection( array $file_contents, $vhCacheRoot = 'lscache' ); /** * * @param string $vhConf * * @throws LSCMException Thrown when virtual host conf file is not * writeable. * @throws LSCMException Thrown when a backup of the virtual host conf file * could not be made. * @throws LSCMException Thrown when "write to virtual host conf file" call * fails. * @throws LSCMException Thrown indirectly by $this->log() call. */ public function writeVHCacheRoot( $vhConf, $vhCacheRoot = 'lscache' ) { if ( !is_writable($vhConf) ) { throw new LSCMException( "Could not write to VH config $vhConf. No changes made.", LSCMException::E_PERMISSION ); } if ( !Util::createBackup($vhConf) ) { throw new LSCMException( "Could not backup Virtual Host config file $vhConf. No " . 'changes made.', LSCMException::E_PERMISSION ); } $file_contents = file($vhConf); if ( preg_grep('/^\s*/im', $file_contents) ) { if ( preg_grep('/^\s*CacheRoot +/im', $file_contents) ) { $modified_contents = preg_replace( '/^\s*CacheRoot +.+/im', "CacheRoot $vhCacheRoot", $file_contents ); } else { $modified_contents = preg_replace( '/^\s*/im', "\nCacheRoot $vhCacheRoot", $file_contents ); } } else { $modified_contents = $this->addVHCacheRootSection($file_contents, $vhCacheRoot); } if ( file_put_contents($vhConf, $modified_contents) === false ) { throw new LSCMException( "Failed to write to file $vhConf.", LSCMException::E_PERMISSION ); } $this->log("Updated file $vhConf.", Logger::L_DEBUG); } /** * Note: Visibility is public to better accommodate escalation functions. * * @param string $vhConf * @param string $vhCacheRoot */ abstract public function createVHConfAndSetCacheRoot( $vhConf, $vhCacheRoot = 'lscache' ); /** * Note: Visibility is public to better accommodate escalation functions. * * @throws LSCMException Thrown by some implementations. */ abstract public function applyVHConfChanges(); /** * * @since 1.9.7 */ protected static function setMinAPIFilePath() { static::$minAPIFilePath = realpath(__DIR__ . '/../..') . '/MIN_VER'; } /** * * @since 1.9.7 * * @return string */ protected static function getMinAPIFilePath() { if ( static::$minAPIFilePath == '' ) { static::setMinAPIFilePath(); } return static::$minAPIFilePath; } /** * * @since 1.9.7 * @since 1.12 Changed visibility from protected to public. */ public static function populateMinAPIVerFile() { $minVerFile = static::getMinAPIFilePath(); $content = Util::get_url_contents( 'https://www.litespeed.sh/sub/shared/MIN_VER' ); if ( !empty($content) ) { file_put_contents($minVerFile, $content); } else { touch($minVerFile); } } /** * * @since 1.9.7 * * @return string */ protected static function getMinAPIVer() { $minVerFile = static::getMinAPIFilePath(); clearstatcache(); if ( !file_exists($minVerFile) || (time() - filemtime($minVerFile)) > 86400 ) { static::populateMinAPIVerFile(); } if ( ($content = file_get_contents($minVerFile)) !== false ) { return trim($content); } return ''; } /** * * @since 1.9.7 * * @return bool */ public static function meetsMinAPIVerRequirement() { $minAPIVer = static::getMinAPIVer(); if ( $minAPIVer == '' || Util::betterVersionCompare(static::PANEL_API_VERSION, $minAPIVer, '<') ) { return false; } return true; } /** * * @since 1.9 * * @param string $panelAPIVer Shared code API version used by the panel * plugin. * * @return int */ public static function checkPanelAPICompatibility( $panelAPIVer ) { $supportedAPIVers = array( '1.17.10.1', '1.17.10', '1.17.9', '1.17.8', '1.17.7', '1.17.6', '1.17.5', '1.17.4.2', '1.17.4.1', '1.17.4', '1.17.3', '1.17.2', '1.17.1.1', '1.17.1', '1.17.0.5', '1.17.0.4', '1.17.0.3', '1.17.0.2', '1.17.0.1', '1.17', '1.16.1', '1.16.0.2', '1.16.0.1', '1.16', '1.15.0.1', '1.15', '1.14.5', '1.14.4.1', '1.14.4', '1.14.3.2', '1.14.3.1', '1.14.3', '1.14.2', '1.14.1.2', '1.14.1.1', '1.14.1', '1.14.0.3', '1.14.0.2', '1.14.0.1', '1.14', '1.13.13.1', '1.13.13', '1.13.12', '1.13.11.1', '1.13.11', '1.13.10.2', '1.13.10.1', '1.13.10', '1.13.9', '1.13.8', '1.13.7.1', '1.13.7', '1.13.6', '1.13.5.2', '1.13.5.1', '1.13.5', '1.13.4.4', '1.13.4.3', '1.13.4.2', '1.13.4.1', '1.13.4', '1.13.3.1', '1.13.3', '1.13.2.2', '1.13.2.1', '1.13.2', '1.13.1', '1.13.0.3', '1.13.0.2', '1.13.0.1', '1.13', '1.12', '1.11', '1.10', '1.9.8', '1.9.7', '1.9.6.1', '1.9.6', '1.9.5', '1.9.4', '1.9.3', '1.9.2', '1.9.1', '1.9', '1.8', '1.7', '1.6.1', '1.6', '1.5', '1.4', '1.3', '1.2', '1.1', '1.0' ); if ( Util::betterVersionCompare($panelAPIVer, $supportedAPIVers[0], '>') ) { return static::PANEL_API_VERSION_TOO_HIGH; } elseif ( Util::betterVersionCompare($panelAPIVer, end($supportedAPIVers), '<') ) { return static::PANEL_API_VERSION_TOO_LOW; } elseif ( ! in_array($panelAPIVer, $supportedAPIVers) ) { return static::PANEL_API_VERSION_UNKNOWN; } else { return static::PANEL_API_VERSION_SUPPORTED; } } /** * * @deprecated 1.9 Use checkPanelAPICompatibility() instead. * * @param string $panelAPIVer Shared code API version used by the panel * plugin. * * @return bool */ public static function isPanelAPICompatible( $panelAPIVer ) { $apiCompatStatus = static::checkPanelAPICompatibility($panelAPIVer); if ( $apiCompatStatus != static::PANEL_API_VERSION_SUPPORTED ) { return false; } return true; } } PK!ܐ} 4 4webcachemgr/src/Panel/Plesk.phpnuIwpanelName = 'Plesk'; $this->defaultSvrCacheRoot = '/var/www/vhosts/lscache/'; parent::init2(); } /** * More reliable than php_uname('s') * * @return string * * @throws LSCMException Thrown when supported Plesk OS detection command * fails. * @throws LSCMException Thrown when supported OS is not detected. */ public function getPleskOS() { $supportedOsList = array( 'centos', 'virtuozzo', 'cloudlinux', 'redhat', 'rhel', 'ubuntu', 'debian', 'almalinux', 'rocky' ); $cmds = array(); if ( file_exists('/etc/debian_version') ) { return 'debian'; } if ( is_readable('/etc/os-release') ) { $cmds[] = 'grep ^ID= /etc/os-release | cut -d "=" -f2 | xargs'; } if ( is_readable('/etc/lsb-release') ) { $cmds[] = 'grep ^DISTRIB_ID= /etc/lsb-release | cut -d "=" -f2 | xargs'; } if ( is_readable('/etc/redhat-release') ) { $cmds[] = 'cat /etc/redhat-release | awk \'{print $1}\''; } foreach ( $cmds as $cmd ) { if ( !($output = shell_exec($cmd)) ) { throw new LSCMException( 'Supported Plesk OS detection command failed.', LSCMException::E_UNSUPPORTED ); } $OS = trim($output); foreach ( $supportedOsList as $supportedOs ) { if ( stripos($OS, $supportedOs) !== false ) { return $supportedOs; } } } throw new LSCMException( 'Plesk detected with unsupported OS. ' . '(Not CentOS/Virtuozzo/Cloudlinux/RedHat/Ubuntu/Debian/' . 'AlmaLinux/Rocky)', LSCMException::E_UNSUPPORTED ); } /** * * @since 1.13.3 * * @return string */ protected function getVhDir() { $vhDir = '/var/www/vhosts'; $psaConfFile = '/etc/psa/psa.conf'; if ( file_exists($psaConfFile) ) { $ret = preg_match( '/HTTPD_VHOSTS_D\s+(\S+)/', file_get_contents($psaConfFile), $m ); if ( $ret == 1 ) { $vhDir = $m[1]; } } return $vhDir; } /** * * @throws LSCMException Thrown indirectly by $this->getPleskOS() call. */ protected function initConfPaths() { $OS = $this->getPleskOS(); switch ( $OS ) { case 'centos': case 'virtuozzo': case 'cloudlinux': case 'redhat': case 'rhel': case 'almalinux': case 'rocky': $this->apacheConf = '/etc/httpd/conf.d/lscache.conf'; break; case 'ubuntu': $this->apacheConf = '/etc/apache2/conf-enabled/lscache.conf'; break; case 'debian': if ( is_dir('/etc/apache2/conf-enabled') ) { $this->apacheConf = '/etc/apache2/conf-enabled/lscache.conf'; } else { /** * Old location. */ $this->apacheConf = '/etc/apache2/conf.d/lscache.conf'; } break; //no default case } $this->apacheVHConf = '/usr/local/psa/admin/conf/templates' . '/custom/domain/domainVirtualHost.php'; } /** * * @return string */ protected function serverCacheRootSearch() { $apacheConfDir = dirname($this->apacheConf); if ( file_exists($apacheConfDir) ) { return $this->cacheRootSearch($apacheConfDir); } return ''; } /** * * @return string */ protected function vhCacheRootSearch() { if ( file_exists($this->apacheVHConf) ) { return $this->getCacheRootSetting($this->apacheVHConf); } return ''; } /** * * @param array $file_contents * @param string $vhCacheRoot * * @return array */ protected function addVHCacheRootSection( array $file_contents, $vhCacheRoot = 'lscache' ) { return preg_replace( '!^\s*!im', "\nCacheRoot $vhCacheRoot\n\n" . '', $file_contents ); } /** * * @param string $vhConf * @param string $vhCacheRoot * * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->log() call. */ public function createVHConfAndSetCacheRoot( $vhConf, $vhCacheRoot = 'lscache' ) { $vhConfTmpl = '/usr/local/psa/admin/conf/templates/default/domain/' . 'domainVirtualHost.php'; $vhConfDir = dirname($vhConf); if ( !file_exists($vhConfDir) ) { mkdir($vhConfDir, 0755, true); $this->log("Created directory $vhConfDir", Logger::L_DEBUG); } copy($vhConfTmpl, $vhConf); Util::matchPermissions($vhConfTmpl, $vhConf); $this->log( "Copied Virtual Host conf template file $vhConfTmpl to $vhConf", Logger::L_DEBUG ); file_put_contents( $vhConf, preg_replace( '!^\s*!im', "\nCacheRoot $vhCacheRoot\n" . "\n", file($vhConf) ) ); $this->log( "Virtual Host cache root set to $vhCacheRoot", Logger::L_INFO ); } public function applyVHConfChanges() { exec('/usr/local/psa/admin/bin/httpdmng --reconfigure-all'); } /** * Gets a list of found docroots and associated server names. * * Note: This function is repeated in Plesk plugin files to avoid extra * serialize ops etc. This copy is for cli only. */ protected function prepareDocrootMap() { exec( 'grep -hro --exclude="stat_ttl.conf" --exclude="*.bak" ' . '--exclude="last_httpd.conf" ' . '"DocumentRoot.*\|ServerName.*\|ServerAlias.*" ' . "{$this->getVhDir()}/system/*/conf/*", $lines ); /** * [0]=servername, [1]=serveralias, [2]=serveralias, [3]=docroot, etc. * Not unique & not sorted. * * Example: * ServerName "pltest1.com:443" * ServerAlias "www.pltest1.com" * ServerAlias "ipv4.pltest1.com" * DocumentRoot "/var/www/vhosts/pltest1.com/httpdocs" * ServerName "pltest1.com:80" * ServerAlias "www.pltest1.com" * ServerAlias "ipv4.pltest1.com" * DocumentRoot "/var/www/vhosts/pltest1.com/httpdocs" * ServerName "pltest2.com:443" * ServerAlias "www.pltest2.com" * ServerAlias "ipv4.pltest2.com" * DocumentRoot "/var/www/vhosts/pltest2.com/httpdocs" * ServerName "pltest2.com:80" * ServerAlias "www.pltest2.com" * ServerAlias "ipv4.pltest2.com" * DocumentRoot "/var/www/vhosts/pltest2.com/httpdocs" * * @noinspection SpellCheckingInspection */ $x = 0; $names = $tmpDocrootMap = array(); $lineCount = count($lines); while ( $x < $lineCount ) { $matchFound = preg_match('/ServerName\s+"([^"]+)"/', $lines[$x], $m1); if ( !$matchFound ) { /** * Invalid start of group, skip. */ $x++; continue; } $UrlInfo = parse_url( (preg_match('#^https?://#', $m1[1])) ? $m1[1] : "http://$m1[1]" ); $names[] = $UrlInfo['host']; $x++; $pattern = '/ServerAlias\s+"([^"]+)"/'; while ( isset($lines[$x]) && preg_match($pattern, $lines[$x], $m2) ) { $names[] = $m2[1]; $x++; } $pattern = '/DocumentRoot\s+"([^"]+)"/'; if ( isset($lines[$x]) && preg_match($pattern, $lines[$x], $m3) == 1 && is_dir($m3[1]) ) { $docroot = $m3[1]; if ( !isset($tmpDocrootMap[$docroot]) ) { $tmpDocrootMap[$docroot] = $names; } else { $tmpDocrootMap[$docroot] = array_merge($tmpDocrootMap[$docroot], $names); } $x++; } $names = array(); } $index = 0; $roots = $serverNames = array(); foreach ( $tmpDocrootMap as $docroot => $names ) { $roots[$index] = $docroot; $names = array_unique($names); foreach ( $names as $n ) { $serverNames[$n] = $index; } $index++; } $this->docRootMap = array( 'docroots' => $roots, 'names' => $serverNames ); } /** * Check for known Plesk PHP binaries and return the newest available * version among them. * * @since 1.9.6 * @since 1.17.6 Added PHP versions 8.3 & 8.4. * * @return string */ protected function getDefaultPhpBinary() { foreach ( [ '8.4', '8.3', '8.2', '8.1', '8.0', '7.4', '7.3', '7.2', '7.1', '7.0', '5.6' ] as $phpVer ) { if ( file_exists(($bin = "/opt/plesk/php/$phpVer/bin/php")) ) { return $bin; } } return ''; } /** * * @since 1.17.10 * * @param WPInstall $wpInstall * * @return PhpBinaryParts */ public function getPhpBinaryParts( WPInstall $wpInstall ) { $binPath = ''; $serverName = $wpInstall->getData(WPInstall::FLD_SERVERNAME); if ( $serverName != null ) { $output = shell_exec( 'plesk db -Ne "SELECT s.value ' . 'FROM ((domains d INNER JOIN hosting h ON h.dom_id=d.id) ' . 'INNER JOIN ServiceNodeEnvironment s ' . 'ON h.php_handler_id=s.name) ' . 'WHERE d.name=' . escapeshellarg($serverName) . ' AND s.section=\'phphandlers\'" ' . '| sed -n \'s:.*\(.*\).*:\1:p\'' ); if ( $output !== null ) { $candidate = trim($output); if ( $candidate !== '' && preg_match('#^/[A-Za-z0-9_./\-]+$#', $candidate) && is_file($candidate) && is_executable($candidate) ) { $binPath = $candidate; } elseif ( $candidate !== '' ) { Logger::debug( 'Plesk handler rejected as unsafe or ' . "non-executable: $candidate. Falling back " . 'to default PHP binary.' ); } } } if ( $binPath === '' ) { $defaultBinary = $this->getDefaultPhpBinary(); $binPath = $defaultBinary !== '' ? $defaultBinary : 'php'; } return new PhpBinaryParts($binPath, $this->phpOptions); } /** * @deprecated since 1.17.10 Override getPhpBinaryParts() instead. * * @param WPInstall $wpInstall * * @return string */ public function getPhpBinary( WPInstall $wpInstall ) { $parts = $this->getPhpBinaryParts($wpInstall); $options = $parts->getOptionsString(); return $options === '' ? $parts->getBinPath() : $parts->getBinPath() . ' ' . $options; } } PK!*??%webcachemgr/src/Panel/DirectAdmin.phpnuIwpanelName = 'DirectAdmin'; $this->defaultSvrCacheRoot = '/home/lscache/'; /** @noinspection PhpUnhandledExceptionInspection */ parent::init2(); } protected function initConfPaths() { $this->apacheConf = '/etc/httpd/conf/extra/httpd-includes.conf'; $this->apacheVHConf = '/usr/local/directadmin/data/templates/custom/' . 'cust_httpd.CUSTOM.2.pre'; } /** * * @return string */ protected function serverCacheRootSearch() { if ( !file_exists($this->apacheConf) ) { return ''; } return $this->getCacheRootSetting($this->apacheConf); } /** * * @return string */ protected function vhCacheRootSearch() { $apacheUserdataDir = dirname($this->apacheVHConf); if ( !file_exists($apacheUserdataDir) ) { return ''; } return $this->daVhCacheRootSearch($apacheUserdataDir); } /** * Searches the given directories '.pre' and '.post' files for CacheRoot * setting. * * @param string $confDir Directory to be searched. * * @return string */ public function daVhCacheRootSearch( $confDir ) { if ( !is_dir($confDir) ) { return ''; } $files = new DirectoryIterator($confDir); foreach ( $files as $file ) { $filename = $file->getFilename(); $isPreOrPostFile = ( strlen($filename) > 4 && ( substr_compare($filename, '.pre', -4) === 0 || substr_compare($filename, '.post', -5) === 0 ) ); if ( $isPreOrPostFile ) { $cacheRoot = $this->getCacheRootSetting($file->getPathname()); if ( $cacheRoot != '' ) { return $cacheRoot; } } } return ''; } /** * * @param array $file_contents * @param string $vhCacheRoot * * @return array */ protected function addVHCacheRootSection( array $file_contents, $vhCacheRoot = 'lscache' ) { array_unshift( $file_contents, "\nCacheRoot $vhCacheRoot\n\n\n" ); return $file_contents; } /** * * @param string $vhConf * @param string $vhCacheRoot * * @throws LSCMException Thrown when mkdir() call fails to create virtual * host conf directory. * @throws LSCMException Thrown when file_put_contents() call fails to * create virtual host conf file. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->log() call. */ public function createVHConfAndSetCacheRoot( $vhConf, $vhCacheRoot = 'lscache' ) { $vhConfDir = dirname($vhConf); if ( !file_exists($vhConfDir) ) { if ( !mkdir($vhConfDir, 0755) ) { throw new LSCMException( "Failed to create directory $vhConfDir." ); } $this->log("Created directory $vhConfDir", Logger::L_DEBUG); } $bytesWrittenToFile = file_put_contents( $vhConf, "\nCacheRoot $vhCacheRoot\n" ); if ( false === $bytesWrittenToFile ) { throw new LSCMException("Failed to create file $vhConf."); } $this->log("Created file $vhConf.", Logger::L_DEBUG); } public function applyVHConfChanges() { exec('/usr/local/directadmin/custombuild/build rewrite_confs'); } /** * * @since 1.13.7 * * @return array[] * * @throws LSCMException Thrown indirectly by Logger::debug() call. */ private function getHttpdConfDocrootMapInfo() { exec( 'grep -hros "DocumentRoot.*\|ServerAlias.*\|ServerName.*" ' . '/usr/local/directadmin/data/users/*/httpd.conf', $lines ); /** * [0]=servername, [1]=serveraliases, [2]=docroot, [3]=servername, etc. * Not unique & not sorted. * * Example: * ServerName www.daruby1.com * ServerAlias www.daruby1.com daruby1.com * DocumentRoot /home/daruby1/domains/daruby1.com/public_html * ServerName www.daruby1.com * ServerAlias www.daruby1.com daruby1.com * DocumentRoot /home/daruby1/domains/daruby1.com/private_html * ServerName www.dauser1.com * ServerAlias www.dauser1.com dauser1.com * DocumentRoot /home/dauser1/domains/dauser1.com/public_html * ServerName www.dauser1.com * ServerAlias www.dauser1.com dauser1.com * DocumentRoot /home/dauser1/domains/dauser1.com/private_html * * @noinspection SpellCheckingInspection */ $docRoots = array(); $curServerName = $curServerAliases = ''; foreach ( $lines as $line ) { if ( $curServerName == '' ) { if ( strpos($line, 'ServerName') === 0 ) { /** * 10 is strlen('ServerName') */ $curServerName = trim(substr($line, 10)); } } elseif ( strpos($line, 'ServerAlias') === 0 ) { /** * 11 is strlen('ServerAlias') */ $curServerAliases = trim(substr($line, 11)); } elseif ( strpos($line, 'DocumentRoot') === 0 ) { /** * 12 is strlen('DocumentRoot') */ $curDocRoot = trim(substr($line, 12), " \n\r\t\v\x00\""); /** * Avoid possible duplicate detections due to * public_html/private_html symlinks. */ if ( !isset($docRoots[$curDocRoot]) && is_dir($curDocRoot) && !is_link($curDocRoot) ) { $docRoots[$curDocRoot] = explode(' ', $curServerAliases); $docRoots[$curDocRoot][] = $curServerName; } /** * Looking for the next data set */ $curServerName = $curServerAliases = ''; } else { Logger::debug("Unused line when preparing docroot map: $line."); } } return $docRoots; } /** * * @since 1.13.7 * * @return array[] * * @throws LSCMException Thrown indirectly by Logger::debug() call. */ private function getOpenlitespeedConfDocrootMapInfo() { exec( 'grep -hros "docRoot.*\|vhDomain.*\|vhAliases.*" ' . '/usr/local/directadmin/data/users/*/openlitespeed.conf', $lines ); /** * [0]=docroot, [1]=servername, [2]=serveraliases, [3]=docroot, etc. * Not unique & not sorted. * * Example: * docRoot /home/test/domains/test.com/public_html * vhDomain test.com * vhAliases www.test.com * docRoot /home/test/domains/test.com/public_html * vhDomain testalias.com * vhAliases www.testalias.com * docRoot /home/test/domains/test.com/private_html * vhDomain test.com * vhAliases www.test.com * docRoot /home/test/domains/test.com/private_html * vhDomain testalias.com * vhAliases www.testalias.com * docRoot /home/test_2/domains/test2.com/public_html * vhDomain test2.com * vhAliases www.test2.com * docRoot /home/test_2/domains/test2.com/private_html * vhDomain test2.com * vhAliases www.test2.com * * @noinspection SpellCheckingInspection */ $docRoots = array(); $curServerName = $curDocRoot = ''; foreach ( $lines as $line ) { if ( $curDocRoot == '' ) { if ( strpos($line, 'docRoot') === 0 ) { /** * 7 is strlen('docRoot') */ $curDocRoot = trim(substr($line, 7)); } } elseif ( strpos($line, 'vhDomain') === 0 ) { /** * 8 is strlen('vhDomain') */ $curServerName = trim(substr($line, 8)); } elseif ( strpos($line, 'vhAliases') === 0 ) { /** * 9 is strlen('vhAliases') */ $curServerAlias = trim(substr($line, 9)); /** * Avoid possible duplicate detections due to * public_html/private_html symlinks. */ if ( is_dir($curDocRoot) && !is_link($curDocRoot) ) { if ( !isset($docRoots[$curDocRoot]) ) { $docRoots[$curDocRoot] = array( $curServerName, $curServerAlias ); } else { if ( !in_array($curServerName, $docRoots[$curDocRoot]) ) { $docRoots[$curDocRoot][] = $curServerName; } if ( !in_array($curServerAlias, $docRoots[$curDocRoot]) ) { $docRoots[$curDocRoot][] = $curServerAlias; } } } /** * Looking for the next data set */ $curDocRoot = $curServerName = ''; } else { Logger::debug("Unused line when preparing docroot map: $line."); } } return $docRoots; } /** * Gets a list of found docroots and associated server names. * Only needed for scan operation. * * @throws LSCMException Thrown indirectly by * $this->getHttpdConfDocrootMapInfo() call. * @throws LSCMException Thrown indirectly by * $this->getOpenlitespeedConfDocrootMapInfo() call. */ protected function prepareDocrootMap() { $docRootMapInfo = $this->getHttpdConfDocrootMapInfo(); $openlitespeedConfDocrootMapInfo = $this->getOpenlitespeedConfDocrootMapInfo(); foreach ( $openlitespeedConfDocrootMapInfo as $oDocRoot => $oDomains ) { if ( !isset($docRootMapInfo[$oDocRoot]) ) { $docRootMapInfo[$oDocRoot] = $oDomains; } else { foreach ( $oDomains as $oDomain ) { if ( !in_array($oDomain, $docRootMapInfo[$oDocRoot]) ) { $docRootMapInfo[$oDocRoot][] = $oDomain; } } } } $roots = array(); $servernames = array(); $index = 0; foreach ( $docRootMapInfo as $docRoot => $domains ) { $domains = array_unique($domains); $roots[$index] = $docRoot; foreach ( $domains as $domain ) { $servernames[$domain] = $index; } $index++; } $this->docRootMap = array( 'docroots' => $roots, 'names' => $servernames ); } /** * Check the user's httpd.conf file for a VirtualHost entry containing a * given servername/docroot combination and return the PHP handler version * if set. * * @param WPInstall $wpInstall * * @return string * * @throws LSCMException Thrown when a valid user data conf file could not * be found. */ protected function getCustomPhpHandlerVer( WPInstall $wpInstall ) { if ( ($serverName = $wpInstall->getServerName()) == null || ($docroot = $wpInstall->getDocRoot()) == null ) { return ''; } $escServerName = str_replace('.', '\.', $serverName); $escDocRoot = str_replace(array('.', '/'), array('\.', '\/'), $docroot); $user = $wpInstall->getOwnerInfo('user_name'); $httpdConfFile = "/usr/local/directadmin/data/users/$user/httpd.conf"; $olsConfFile = "/usr/local/directadmin/data/users/$user/openlitespeed.conf"; if ( file_exists($httpdConfFile) ) { $confFile = $httpdConfFile; $pattern = '/VirtualHost' . '(?:(?!<\/VirtualHost).)*' . "ServerName $escServerName" . '(?:(?!<\/VirtualHost).)*' . "DocumentRoot $escDocRoot" . '(?:(?!<\/VirtualHost).)*' . 'AddHandler.* \.php(\d\d)/sU'; } elseif ( file_exists($olsConfFile) ) { $confFile = $olsConfFile; $pattern = '/virtualHost\s' . '(?:(?!}\s*\n*virtualHost).)*?' . '{' . '(?:(?!}\s*\n*virtualHost).)*?' . "(?:\s|\n)docRoot\s+$escDocRoot(?:\s|\n)" . '(?:(?!}\s*\n*virtualHost).)*?' . "(?:\s|\n)vhDomain\s+$escServerName(?:\s|\n)" . '(?:(?!}\s*\n*virtualHost).)*?' . '(?:\s|\n)scripthandler(?:\s|\n)*{' . '(?:(?!}\s*\n*virtualHost).)*?' . '\sphp(\d\d)(?=\s|\n)/s'; } else { throw new LSCMException('Could not find valid user data conf file'); } if ( preg_match($pattern, file_get_contents($confFile), $m) ) { return $m[1]; } return ''; } /** * * @since 1.17.10 * * @param WPInstall $wpInstall * * @return PhpBinaryParts * * @throws LSCMException Thrown indirectly by * $this->getCustomPhpHandlerVer() call. */ public function getPhpBinaryParts( WPInstall $wpInstall ) { $binPath = '/usr/local/bin/php'; if ( ($ver = $this->getCustomPhpHandlerVer($wpInstall)) != '' ) { $customBin = "/usr/local/php$ver/bin/php"; if ( file_exists($customBin) && is_executable($customBin) ) { $binPath = $customBin; } } return new PhpBinaryParts($binPath, $this->phpOptions); } /** * @deprecated since 1.17.10 Override getPhpBinaryParts() instead. * * @param WPInstall $wpInstall * * @return string * * @throws LSCMException Thrown indirectly by * $this->getCustomPhpHandlerVer() call. */ public function getPhpBinary( WPInstall $wpInstall ) { $parts = $this->getPhpBinaryParts($wpInstall); $options = $parts->getOptionsString(); return $options === '' ? $parts->getBinPath() : $parts->getBinPath() . ' ' . $options; } } PK!Icii webcachemgr/src/Panel/CPanel.phpnuIwpanelName = 'cPanel/WHM'; $this->defaultSvrCacheRoot = '/home/lscache/'; /** @noinspection PhpUnhandledExceptionInspection */ parent::init2(); } protected function initConfPaths() { $this->apacheConf = '/etc/apache2/conf.d/includes/pre_main_global.conf'; $this->apacheVHConf = '/etc/apache2/conf.d/userdata/lscache_vhosts.conf'; } /** * * @return string */ protected function serverCacheRootSearch() { if ( file_exists($this->apacheConf) ) { return $this->getCacheRootSetting($this->apacheConf); } return ''; } /** * * @return string */ protected function vhCacheRootSearch() { $apacheUserdataDir = dirname($this->apacheVHConf); if ( file_exists($apacheUserdataDir) ) { return $this->cacheRootSearch($apacheUserdataDir); } return ''; } /** * * @param array $file_contents * @param string $vhCacheRoot * * @return array */ protected function addVHCacheRootSection( array $file_contents, $vhCacheRoot = 'lscache' ) { array_unshift( $file_contents, "\nCacheRoot $vhCacheRoot\n\n\n" ); return $file_contents; } /** * * @param string $vhConf * @param string $vhCacheRoot * * @throws LSCMException Thrown when virtual host conf directory cannot be * created. * @throws LSCMException Thrown when virtual host conf file cannot be * created. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->log() call. */ public function createVHConfAndSetCacheRoot( $vhConf, $vhCacheRoot = 'lscache' ) { $vhConfDir = dirname($vhConf); if ( !file_exists($vhConfDir) ) { if ( !mkdir($vhConfDir, 0755) ) { throw new LSCMException( "Failed to create directory $vhConfDir." ); } $this->log("Created directory $vhConfDir", Logger::L_DEBUG); } $vhConfFileCreated = ( file_put_contents( $vhConf, "\nCacheRoot $vhCacheRoot\n" ) !== false ); if ( !$vhConfFileCreated ) { throw new LSCMException("Failed to create file $vhConf."); } $this->log("Created file $vhConf.", Logger::L_DEBUG); } /** * * @throws LSCMException Thrown indirectly by * self::UpdateCpanelPluginConf() call. */ public function applyVHConfChanges() { exec('/scripts/ensure_vhost_includes --all-users'); if ( file_exists(self::THEME_JUPITER_USER_PLUGIN_DIR) || file_exists(self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR) ) { self::UpdateCpanelPluginConf( self::USER_PLUGIN_SETTING_VHOST_CACHE_ROOT, $this->vhCacheRoot ); } } /** * Gets a list of found docroots and associated server names. * Only needed for scan logic. * * @throws LSCMException Thrown when an error is encountered by * preg_split() call on trimmed $line value. * @throws LSCMException Thrown indirectly by Logger::debug() call. * * @noinspection SpellCheckingInspection */ protected function prepareDocrootMap() { exec( 'grep -hro ' . '--exclude="cache" --exclude="main" --exclude="*.cache" ' . '"documentroot.*\|serveralias.*\|servername.*" ' . '/var/cpanel/userdata/*', $lines ); /** * [0]=docroot, [1]=serveraliases, [2]=servername, [3]=docroot, etc. * Not unique & not sorted. * * Example: * documentroot: /home/user1/finches * serveralias: finches.com mail.finches.com www.finches.com www.finches.user1.com cpanel.finches.com autodiscover.finches.com whm.finches.com webmail.finches.com webdisk.finches.com * servername: finches.user1.com * documentroot: /home/user1/public_html/dookoo * serveralias: www.dookoo.user1.com * servername: dookoo.user1.com * documentroot: /home/user1/public_html/doo/doo2 * serveralias: www.doo2.user1.com * servername: doo2.user1.com * documentroot: /home/user1/finches * serveralias: finches.com mail.finches.com www.finches.com www.finches.user1.com * servername: finches.user1.com */ $cur = ''; $docroots = array(); foreach ( $lines as $line ) { if ( $cur == '' ) { if ( strpos($line, 'documentroot:') === 0 ) { /** * 13 is strlen('documentroot:') */ $cur = trim(substr($line, 13)); if ( !isset($docroots[$cur]) ) { if ( is_dir($cur) ) { $docroots[$cur] = ''; } else { /** * bad entry ignore */ $cur = ''; } } } } elseif ( strpos($line, 'serveralias:') === 0 ) { /** * 12 is strlen('serveralias:') */ $docroots[$cur] .= substr($line, 12); } elseif ( strpos($line, 'servername:') === 0 ) { /** * 11 is strlen('servername:') */ $docroots[$cur] .= substr($line, 11); /** * looking for the next docroot */ $cur = ''; } else { Logger::debug("Unused line when preparing docroot map: $line."); } } $roots = array(); $servernames = array(); $index = 0; foreach ( $docroots as $docroot => $line ) { $names = preg_split('/\s+/', trim($line), -1, PREG_SPLIT_NO_EMPTY); if ( $names === false ) { throw new LSCMException( 'prepareDocrootMap(): Error encountered when calling ' . 'preg_split() on trimmed $line.' ); } $names = array_unique($names); $roots[$index] = $docroot; foreach ( $names as $n ) { $servernames[$n] = $index; } $index++; } $this->docRootMap = array( 'docroots' => $roots, 'names' => $servernames ); } /** * * @since 1.17.10 * * @param WPInstall $wpInstall * * @return PhpBinaryParts */ public function getPhpBinaryParts( WPInstall $wpInstall ) { /** * cPanel php wrapper accurately detects the correct EA4 binary when * --ea-reference-dir is provided. The argument is shell-escaped here * so the resulting options string is safe to interpolate raw. */ $options = '--ea-reference-dir=' . escapeshellarg($wpInstall->getPath() . '/wp-admin'); if ( $this->phpOptions !== '' ) { $options .= ' ' . $this->phpOptions; } return new PhpBinaryParts('/usr/local/bin/php', $options); } /** * @deprecated since 1.17.10 Override getPhpBinaryParts() instead. * * @param WPInstall $wpInstall * * @return string */ public function getPhpBinary( WPInstall $wpInstall ) { $parts = $this->getPhpBinaryParts($wpInstall); $options = $parts->getOptionsString(); return $options === '' ? $parts->getBinPath() : $parts->getBinPath() . ' ' . $options; } /** * * @return bool */ public static function isCpanelPluginAutoInstallOn() { if ( file_exists(self::CPANEL_AUTOINSTALL_DISABLE_FLAG) ) { return false; } return true; } /** * * @return bool */ public static function turnOnCpanelPluginAutoInstall() { if ( !file_exists(self::CPANEL_AUTOINSTALL_DISABLE_FLAG) ) { return true; } return unlink(self::CPANEL_AUTOINSTALL_DISABLE_FLAG); } /** * * @return bool */ public static function turnOffCpanelPluginAutoInstall() { return touch(self::CPANEL_AUTOINSTALL_DISABLE_FLAG); } /** * * @return string * * @throws LSCMException Thrown when unable to find cPanel user-end plugin * installation script. * @throws LSCMException Thrown when failing to back up cPanel user-end * plugin data files. * @throws LSCMException Thrown indirectly by * self::backupCpanelPluginDataFiles() call. * @throws LSCMException Thrown indirectly by Logger::error() call. */ public function installCpanelPlugin() { if ( !file_exists(self::USER_PLUGIN_INSTALL_SCRIPT) ) { throw new LSCMException( 'Unable to find cPanel user-end plugin installation script.' . ' Please ensure that the LiteSpeed WHM plugin is already ' . 'installed.' ); } $existingInstall = ( file_exists(self::THEME_JUPITER_USER_PLUGIN_DIR) || file_exists(self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR) ); if ( $existingInstall ) { $backupDir = self::backupCpanelPluginDataFiles(); if ( $backupDir === false ) { throw new LSCMException( 'Failed to backup cPanel user-end plugin data files. ' . 'Aborting install/update operation.' ); } exec(self::USER_PLUGIN_INSTALL_SCRIPT); if ( !self::restoreCpanelPluginDataFiles($backupDir) ) { Logger::error( 'Failed to restore cPanel user-end plugin data files.' ); exec('/bin/rm -rf ' . escapeshellarg($backupDir)); } } else { exec(self::USER_PLUGIN_INSTALL_SCRIPT); } $this->updateCoreCpanelPluginConfSettings(); return ($existingInstall) ? 'update' : 'new'; } /** * Create a per-run, unpredictable, restrictive-permission temporary * directory for cPanel plugin data backup (V15, CWE-377/CWE-367). * * Uses random_bytes() on PHP 7+ and falls back to * openssl_random_pseudo_bytes() on PHP 5.6 when the OpenSSL extension is * available. When neither is available, a non-cryptographic suffix is * used; a local attacker who guesses the name can pre-create the path and * cause mkdir() to fail (DoS on install/update), but cannot exploit it for * traversal — mkdir() rejects an already-existing path outright. * * @since 1.17.10 * @since 1.17.10.1 Added non-crypto suffix fallback for * environments where both random_bytes() and * openssl_random_pseudo_bytes() are unavailable. * * @return string The path of the newly created directory. * * @throws LSCMException Thrown when failing to create the directory. */ protected static function createPluginBackupDir() { $base = sys_get_temp_dir(); if ( function_exists('random_bytes') ) { $suffix = bin2hex(random_bytes(8)); } elseif ( function_exists('openssl_random_pseudo_bytes') ) { $strong = false; $raw = openssl_random_pseudo_bytes(8, $strong); if ( $raw === false || !$strong ) { throw new LSCMException( 'Failed to generate cryptographically strong random bytes ' . 'for temporary directory name' ); } $suffix = bin2hex($raw); } else { $suffix = bin2hex(pack('NN', time() ^ mt_rand(), getmypid())); } $path = "$base/lscp-plugin-$suffix"; if ( !mkdir($path, 0700) ) { throw new LSCMException( "Failed to create temporary directory $path" ); } return $path; } /** * * @since 1.13.2 * @since 1.13.2.2 Made function static. * @since 1.13.5.2 Removed optional param $oldLogic. * @since 1.17.10 Returns per-run backup dir path (string) on success, * false on early return; no longer uses a fixed /tmp constant * (V15, CWE-377). * * @return string|false Per-run backup directory path on success, false * on early-return (no plugin install found or no conf file). * * @throws LSCMException Thrown when failing to create a temporary backup * directory. */ protected static function backupCpanelPluginDataFiles() { if ( file_exists(self::THEME_JUPITER_USER_PLUGIN_DIR) ) { $pluginDir = self::THEME_JUPITER_USER_PLUGIN_DIR; } elseif ( file_exists(self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR) ) { $pluginDir = self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR; } else { return false; } $backupDir = self::createPluginBackupDir(); /** * Move existing conf file (if needed), templates, and custom * translations to temp directory and remove default template dir to * prevent overwriting when moving back. */ $activeConfFile = self::getInstalledCpanelPluginActiveConfFileLocation($pluginDir); if ( $activeConfFile == '' || !file_exists($activeConfFile) ) { Util::rrmdir($backupDir); return false; } $backupCmds = ''; if ( $activeConfFile != self::USER_PLUGIN_CONF ) { $backupCmds .= '/bin/mv ' . escapeshellarg($activeConfFile) . ' ' . escapeshellarg($backupDir) . '/;'; } $custTransDir = $backupDir . '/cust'; $escPluginDir = escapeshellarg($pluginDir); $escBackupDir = escapeshellarg($backupDir); $escTmpCustTransDir = escapeshellarg($custTransDir); $escBackupLanding = escapeshellarg($backupDir . '/landing/default'); $escTmpReadme = escapeshellarg($custTransDir . '/README'); $backupCmds .= "/bin/mv $escPluginDir/landing $escBackupDir/;" . "/bin/rm -rf $escBackupLanding;" . "/bin/mv $escPluginDir/lang/cust $escTmpCustTransDir;" . "/bin/rm -rf $escTmpReadme"; exec($backupCmds); return $backupDir; } /** * * @since 1.13.2 * @since 1.13.2.2 Made function static. * @since 1.13.5.2 Removed optional param $oldLogic. * @since 1.17.10 Accepts per-run $backupDir path (V15, CWE-377). * * @param string $backupDir Per-run backup directory created by * backupCpanelPluginDataFiles(). * * @return bool */ protected static function restoreCpanelPluginDataFiles( $backupDir ) { $pluginInstalls = array(); if ( file_exists(self::THEME_JUPITER_USER_PLUGIN_DIR) ) { $pluginInstalls[] = self::THEME_JUPITER_USER_PLUGIN_DIR; } if ( file_exists(self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR) ) { $pluginInstalls[] = self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR; } if ( !file_exists($backupDir) || empty($pluginInstalls) ) { return false; } $tmpCpanelPluginConfFile = $backupDir . '/lswcm.conf'; foreach ( $pluginInstalls as $pluginInstall ) { $cpanelPluginLangDir = "$pluginInstall/lang"; if (!file_exists($cpanelPluginLangDir)) { mkdir($cpanelPluginLangDir, 0755); } if ( file_exists($tmpCpanelPluginConfFile) ) { $activeConfFile = self::getInstalledCpanelPluginActiveConfFileLocation( $pluginInstall ); if ($activeConfFile == '') { return false; } copy($tmpCpanelPluginConfFile, $activeConfFile); chmod($activeConfFile, 0644); } /** * Replace cPanel plugin templates, custom translations. */ $escBackupDir = escapeshellarg($backupDir); $escPluginInstall = escapeshellarg($pluginInstall); $escLangDir = escapeshellarg($cpanelPluginLangDir); exec( "/bin/cp -prf $escBackupDir/landing $escPluginInstall/;" . "/bin/cp -prf $escBackupDir/cust $escLangDir/" ); } exec('/bin/rm -rf ' . escapeshellarg($backupDir)); return true; } /** * * @since 1.13.2.2 Made function static. * * @throws LSCMException Thrown when unable to find the uninstallation * script. */ public static function uninstallCpanelPlugin() { $jupiterUninstallFile = self::THEME_JUPITER_USER_PLUGIN_DIR . '/' . self::USER_PLUGIN_RELATIVE_UNINSTALL_SCRIPT; $paperLanternUninstallFile = self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR . '/' . self::USER_PLUGIN_RELATIVE_UNINSTALL_SCRIPT; if ( file_exists($jupiterUninstallFile) ) { $uninstallFile = $jupiterUninstallFile; } elseif ( file_exists($paperLanternUninstallFile) ) { $uninstallFile = $paperLanternUninstallFile; } else { throw new LSCMException( 'Unable to find cPanel user-end plugin uninstallation script. ' . 'Plugin may already be uninstalled.' ); } exec(escapeshellarg($uninstallFile)); self::turnOffCpanelPluginAutoInstall(); } /** * Attempt to update core cPanel plugin settings used for basic plugin * operation to the currently discovered values. * * @since 1.13.2.2 * @since 1.13.5 Changed function visibility to public. * * @throws LSCMException Thrown indirectly by * self::UpdateCpanelPluginConf() call. * @throws LSCMException Thrown indirectly by $this->getVHCacheRoot() call. * @throws LSCMException Thrown indirectly by * self::UpdateCpanelPluginConf() call. */ public function updateCoreCpanelPluginConfSettings() { self::UpdateCpanelPluginConf( self::USER_PLUGIN_SETTING_LSWS_DIR, realpath(__DIR__ . '/../../../..') ); self::UpdateCpanelPluginConf( self::USER_PLUGIN_SETTING_VHOST_CACHE_ROOT, $this->getVHCacheRoot() ); } /** * * @since 1.13.2.2 Made function static. * * @param string $setting * @param mixed $value * * @throws LSCMException Thrown when unable to determine active cPanel * user-end plugin conf file location usually indicating that the * cPanel user-end plugin is not currently installed. * @throws LSCMException Thrown when unable to create cPanel user-end * plugin "data" directory for older versions of the cPanel user-end * plugin that require this directory. */ public static function UpdateCpanelPluginConf( $setting, $value ) { $pluginInstalls = array(); if ( file_exists(self::THEME_JUPITER_USER_PLUGIN_DIR) ) { $pluginInstalls[] = self::THEME_JUPITER_USER_PLUGIN_DIR; } else { $pluginInstalls[] = self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR; } foreach ( $pluginInstalls as $pluginInstall ) { $activeConfFile = self::getInstalledCpanelPluginActiveConfFileLocation( $pluginInstall ); if ( $activeConfFile == '' ) { throw new LSCMException( 'Unable to determine active conf file location for cPanel ' . 'user-end plugin. cPanel user-end plugin is likely ' . 'not installed.' ); } if ( !file_exists($activeConfFile) ) { $oldConf = ''; if ( file_exists("$pluginInstall/" . self::USER_PLUGIN_RELATIVE_CONF_OLD_2) ) { $oldConf = "$pluginInstall/" . self::USER_PLUGIN_RELATIVE_CONF_OLD_2; } elseif ( file_exists("$pluginInstall/" . self::USER_PLUGIN_RELATIVE_CONF_OLD) ) { $oldConf = "$pluginInstall/" . self::USER_PLUGIN_RELATIVE_CONF_OLD; } if ( $oldConf != '' ) { $dataDir = "$pluginInstall/" . self::USER_PLUGIN_RELATIVE_DATA_DIR; if ( $activeConfFile == "$pluginInstall/" . self::USER_PLUGIN_RELATIVE_CONF_OLD_2 && !file_exists($dataDir) && !mkdir($dataDir) ) { throw new LSCMException( "Failed to create directory $dataDir." ); } copy($oldConf, $activeConfFile); } } if ( file_exists($activeConfFile) ) { chmod($activeConfFile, 0644); switch ( $setting ) { case self::USER_PLUGIN_SETTING_LSWS_DIR: $pattern = '/LSWS_HOME_DIR = ".*"/'; $replacement = "LSWS_HOME_DIR = \"$value\""; break; case self::USER_PLUGIN_SETTING_VHOST_CACHE_ROOT: $pattern = '/VHOST_CACHE_ROOT = ".*"/'; $replacement = "VHOST_CACHE_ROOT = \"$value\""; break; default: return; } $content = file_get_contents($activeConfFile); if ( preg_match($pattern, $content) ) { file_put_contents( $activeConfFile, preg_replace($pattern, $replacement, $content) ); } else { file_put_contents( $activeConfFile, $replacement, FILE_APPEND ); } } } } /** * * @since 1.13.11 * * @param string $pluginDir * * @return string */ protected static function getInstalledCpanelPluginActiveConfFileLocation( $pluginDir ) { $versionFile = "$pluginDir/VERSION"; if ( file_exists($versionFile) ) { $verGreaterThan2_1_2_2 = Util::betterVersionCompare( file_get_contents($versionFile), '2.1.2.2', '>' ); if ( $verGreaterThan2_1_2_2 ) { return self::USER_PLUGIN_CONF; } } if ( file_exists("$pluginDir/" . self::USER_PLUGIN_RELATIVE_DATA_DIR) ) { return "$pluginDir/" . self::USER_PLUGIN_RELATIVE_CONF_OLD_2; } if ( file_exists($pluginDir) ) { return "$pluginDir/" . self::USER_PLUGIN_RELATIVE_CONF_OLD; } return ''; } } PK!/$(webcachemgr/src/Panel/PhpBinaryParts.phpnuIwbinPath = (string)$binPath; $this->optionsString = (string)$optionsString; } /** * * @since 1.17.10 * * @return string */ public function getBinPath() { return $this->binPath; } /** * * @since 1.17.10 * * @return string */ public function getOptionsString() { return $this->optionsString; } } PK! XX)webcachemgr/src/Panel/CustomPanelBase.phpnuIwinit() call. */ public function __construct( $dataFile, $custDataFile = '' ) { $this->dataFile = $dataFile; $this->customDataFile = $custDataFile; $this->error = $this->init(); } /** * * @return int * * @throws LSCMException Thrown indirectly by Logger::debug() call. */ protected function init() { $dataExists = false; try { if ( file_exists($this->dataFile) ) { $dataExists = true; $this->wpInstalls = $this->getDataFileData($this->dataFile); } if ( $this->customDataFile != '' && file_exists($this->customDataFile) ) { $dataExists = true; $this->custWpInstalls = $this->getDataFileData($this->customDataFile); } } catch ( LSCMException $e ) { Logger::debug($e->getMessage()); return $e->getCode(); } if ( !$dataExists ) { return self::ERR_NOT_EXIST; } return 0; } /** * * @since 1.15 * * @param string $dataFile * * @return false|string */ protected static function getDataFileContents( $dataFile ) { return file_get_contents($dataFile); } /** * * @param string $dataFile * * @return WPInstall[] * * @throws LSCMException Thrown when data file is corrupt. * @throws LSCMException Thrown when there is a data file version issue. * @throws LSCMException Thrown indirectly by $this->verifyDataFileVer() * call. */ protected function getDataFileData( $dataFile ) { $content = static::getDataFileContents($dataFile); if ( ($data = json_decode($content, true)) === null ) { /** * Data file may be in the legacy serialized format (pre-v1.15). * * I-7: every cPanel-supported runtime is PHP 7+, so the previous * PHP_VERSION < 7.0 LSCMException branch was dead code. Calling * unserialize() with `'allowed_classes' => false` blocks object * instantiation, which is the only gadget path of concern here. */ $data = unserialize($content, ['allowed_classes' => false]); } if ( $data === false || !is_array($data) || !isset($data['__VER__']) ) { throw new LSCMException( "$dataFile - Data is corrupt.", self::ERR_CORRUPTED ); } if ( ($err = $this->verifyDataFileVer($dataFile, $data['__VER__'])) ) { throw new LSCMException( "$dataFile - Data file version issue.", $err ); } unset($data['__VER__']); $wpInstalls = []; foreach ( $data as $utf8Path => $idata ) { $path = Utf8::decode($utf8Path); $i = new WPInstall($path); $siteUrl = isset($idata[WPInstall::FLD_SITEURL]) ? $idata[WPInstall::FLD_SITEURL] : null; $idata[WPInstall::FLD_SITEURL] = ($siteUrl !== null) ? urldecode($siteUrl) : null; $serverName = isset($idata[WPInstall::FLD_SERVERNAME]) ? $idata[WPInstall::FLD_SERVERNAME] : null; $idata[WPInstall::FLD_SERVERNAME] = ($serverName !== null) ? urldecode($serverName) : null; $i->initData($idata); $wpInstalls[$path] = $i; } return $wpInstalls; } /** * * @return int */ public function getError() { return $this->error; } /** * * @param bool $nonFatalOnly * * @return int */ public function getCount( $nonFatalOnly = false ) { $count = 0; if ( $this->wpInstalls != null ) { if ( $nonFatalOnly ) { foreach ( $this->wpInstalls as $install ) { if ( !$install->hasFatalError() ) { $count++; } } } else { $count += count($this->wpInstalls); } } if ( $this->custWpInstalls != null ) { if ( $nonFatalOnly ) { foreach ( $this->custWpInstalls as $custInstall ) { if ( !$custInstall->hasFatalError() ) { $count++; } } } else { $count += count($this->custWpInstalls); } } return $count; } /** * * @return null|WPInstall[] * * @noinspection PhpUnused */ public function getWPInstalls() { return $this->wpInstalls; } /** * * @return null|WPInstall[] * * @noinspection PhpUnused */ public function getCustWPInstalls() { return $this->custWpInstalls; } /** * * @return null|WPInstall[] */ public function getAllWPInstalls() { if ( $this->wpInstalls != null ) { if ( $this->custWpInstalls != null ) { return array_merge($this->wpInstalls, $this->custWpInstalls); } else { return $this->wpInstalls; } } elseif ( $this->custWpInstalls != null ) { return $this->custWpInstalls; } else { return null; } } /** * Get all known WPInstall paths. * * @return string[] */ public function getPaths() { $paths = []; if ( $this->wpInstalls != null ) { $paths = array_keys($this->wpInstalls); } if ( $this->custWpInstalls != null ) { $paths = array_merge($paths, array_keys($this->custWpInstalls)); } return $paths; } /** * * @param string $path * * @return WPInstall|null */ public function getWPInstall( $path ) { /** * V9.5 — match the literal path against the canonical keyset first. * Stored keys are already canonical (WPInstall::init() canonicalises * and addWPInstall() keys by getPath()), so a caller passing a * canonical path (the flag-action case) resolves to its bound install * even if an intermediate component was swapped after the path was * enqueued. Resolving via realpath() first would follow such a swap to * a victim tree and miss the binding, yielding an unbound WPInstall * downstream whose null expectedOwnerUid would skip Layer 2 of * addUserFlagFile(). */ if ( isset($this->wpInstalls[$path]) ) { return $this->wpInstalls[$path]; } elseif ( isset($this->custWpInstalls[$path]) ) { return $this->custWpInstalls[$path]; } if ( ($realPath = realpath($path)) === false ) { $index = $path; } else { $index = $realPath; } if ( isset($this->wpInstalls[$index]) ) { return $this->wpInstalls[$index]; } elseif ( isset($this->custWpInstalls[$index]) ) { return $this->custWpInstalls[$index]; } return null; } /** * * @return WPInstall[] */ public function getWorkingQueue() { return $this->workingQueue; } /** * * @param WPInstall $wpInstall */ public function addWPInstall( WPInstall $wpInstall ) { $this->wpInstalls[$wpInstall->getPath()] = $wpInstall; } /** * * @throws LSCMException Thrown indirectly by $this->saveDataFile() call. * @throws LSCMException Thrown indirectly by $this->saveDataFile() call. */ public function syncToDisk() { $this->saveDataFile($this->dataFile, $this->wpInstalls); if ( $this->customDataFile != '' ) { $this->saveDataFile($this->customDataFile, $this->custWpInstalls); } } /** * * @param string $dataFile * @param WPInstall[]|null $wpInstalls * * @throws LSCMException Thrown indirectly by $this->log() call. */ protected function saveDataFile( $dataFile, $wpInstalls ) { $data = [ '__VER__' => self::DATA_VERSION ]; if ( !empty($wpInstalls) ) { foreach ( $wpInstalls as $path => $install ) { if ( !$install->shouldRemove() ) { $utf8Path = Utf8::encode($path); $data[$utf8Path] = $install->getData(); $siteUrl = &$data[$utf8Path][WPInstall::FLD_SITEURL]; if ( $siteUrl != null ) { $siteUrl = urlencode($siteUrl); } $serverName = &$data[$utf8Path][WPInstall::FLD_SERVERNAME]; if ( $serverName != null ) { $serverName = urlencode($serverName); } } } ksort($data); } file_put_contents($dataFile, json_encode($data), LOCK_EX); chmod($dataFile, 0600); $this->log("Data file saved $dataFile", Logger::L_DEBUG); } /** * * @param string $dataFile * @param string $dataFileVer * * @return int * * @throws LSCMException Thrown indirectly by Logger::info() call. * @throws LSCMException Thrown indirectly by $this->updateDataFile() call. */ protected function verifyDataFileVer( $dataFile, $dataFileVer ) { $res = Util::betterVersionCompare($dataFileVer, self::DATA_VERSION); if ( $res == 1 ) { Logger::info( 'Data file version is higher than expected and cannot be used.' ); return self::ERR_VERSION_HIGH; } if ( $res == -1 && !$this->updateDataFile($dataFile, $dataFileVer) ) { return self::ERR_VERSION_LOW; } return 0; } /** * * @param string $dataFile * @param string $dataFileVer * * @return bool * * @throws LSCMException Thrown indirectly by Logger::info() call. * @throws LSCMException Thrown indirectly by Util::createBackup() call. * @throws LSCMException Thrown indirectly by Logger::error() call. */ public static function updateDataFile( $dataFile, $dataFileVer ) { Logger::info( "$dataFile - Old data file version detected. Attempting to " . 'update...' ); /** * Currently no versions are upgradeable to 1.5 */ $updatableVersions = []; if ( !in_array($dataFileVer, $updatableVersions) || ! Util::createBackup($dataFile) ) { Logger::error( "$dataFile - Data file could not be updated to version " . self::DATA_VERSION ); return false; } /** * Upgrade funcs will be called here. */ return true; } /** * * @param string $action * * @return string[] * * @throws LSCMException Thrown when "get docroots" command fails. * @throws LSCMException Thrown when $action value is unsupported. */ protected function prepareActionItems( $action ) { switch ( $action ) { case self::CMD_SCAN: case self::CMD_SCAN2: case self::CMD_DISCOVER_NEW: case self::CMD_DISCOVER_NEW2: try { return ControlPanel::getClassInstance()->getDocRoots(); } catch ( LSCMException $e ) { throw new LSCMException( $e->getMessage() . " Could not prepare $action action items." ); } case UserCommand::CMD_MASS_ENABLE: case UserCommand::CMD_MASS_DISABLE: case UserCommand::CMD_MASS_UPGRADE: case UserCommand::CMD_MASS_DASH_NOTIFY: case UserCommand::CMD_MASS_DASH_DISABLE: case self::CMD_MASS_UNFLAG: return $this->getPaths(); default: throw new LSCMException('Missing parameter(s).'); } } /** * * @param string $action * @param string $path * @param string[] $extraArgs * * @throws LSCMException Thrown when an invalid LSCWP version is selected * in action UserCommand::CMD_MASS_UPGRADE. * @throws LSCMException Thrown when LSCWP version fails to download in * action UserCommand::CMD_MASS_UPGRADE. * @throws LSCMException Thrown when LSCWP source package is not available * in action UserCommand::CMD_MASS_UPGRADE. * @throws LSCMException Thrown indirectly by $wpInstall->hasValidPath() * call. * @throws LSCMException Thrown indirectly by $wpInstall->addUserFlagFile() * call. * @throws LSCMException Thrown indirectly by $wpInstall->hasValidPath() * call. * @throws LSCMException Thrown indirectly by $wpInstall->refreshStatus() * call. * @throws LSCMException Thrown indirectly by $wpInstall->addUserFlagFile() * call. * @throws LSCMException Thrown indirectly by PluginVersion::getInstance() * call. * @throws LSCMException Thrown indirectly by * PluginVersion::getInstance()->getAllowedVersions() call. * @throws LSCMException Thrown indirectly by UserCommand::issue() call. * @throws LSCMException Thrown indirectly by $this->syncToDisk() call. * @throws LSCMException Thrown indirectly by $this->syncToDisk() call. */ protected function doWPInstallAction( $action, $path, array $extraArgs ) { if ( ($wpInstall = $this->getWPInstall($path)) == null ) { /** * V9.5 — for flag actions the path always originates from the * existing keyset (getPaths() canonical keys, or the single-flag * pre-validation in doSingleAction()). A miss here means the path * drifted between the time the list was built and this lookup — * indicative of a cross-tenant TOCTOU intermediate-component swap. * Constructing an unbound WPInstall would carry null * expectedOwnerUid, silently disabling Layer 2 of * addUserFlagFile() and allowing the privileged write to proceed * against an unverified (possibly swapped) path. Fail closed * instead. * * V9.6 — extend the fail-closed guard to every action that can * reach a root-context addUserFlagFile(false) on the * dispatcher-resolved object: * - CMD_ENABLE/CMD_DISABLE/CMD_DASH_NOTIFY/CMD_DASH_DISABLE can * call addUserFlagFile(false) directly when refreshStatus() * still shows a fatal error. * - All actions fed through UserCommand::issue() can call * addUserFlagFile(false) in root context via its error handler. * These paths have the same unbound-object exposure as the explicit * flag actions (§13/§14 of the fix plan). The fallback bare * construct is kept for discovery/custom install actions whose * paths do not originate from the existing keyset. * * V9.7 — the V9.6 explicit OR-list was incomplete: CMD_STATUS * (and all other issue-able commands) share the same * addUserFlagFile(false) exposure via UserCommand::issue()'s error * handler, and CMD_STATUS is reachable via the single-action UI * path (refresh_status_single). Centralise: guard every command * accepted by UserCommand::isSupportedIssueCmd() plus the explicit * flag commands so any future addition to the issue() command set * is protected automatically. * * V9.8 — CMD_UNFLAG/CMD_MASS_UNFLAG added to the guard. These * are not in isSupportedIssueCmd() (unflag is handled inline below, * not via UserCommand::issue()), so they must be listed explicitly. * An unbound WPInstall for an unflag miss would carry null * expectedOwnerUid, silently disabling the Layer 2 owner check in * the hardened removeFlagFile(false) path added in V9.8. */ if ( $action === self::CMD_FLAG || $action === self::CMD_MASS_FLAG || $action === self::CMD_UNFLAG || $action === self::CMD_MASS_UNFLAG || UserCommand::isSupportedIssueCmd($action) ) { $this->log( "Skipping $action: install path $path is not a known " . 'install (possible cross-tenant TOCTOU — ' . 'intermediate component swapped after the action ' . 'list was built).', Logger::L_INFO ); return; } $wpInstall = new WPInstall($path); $this->addWPInstall($wpInstall); } switch ( $action ) { case self::CMD_FLAG: case self::CMD_MASS_FLAG: if ( !$wpInstall->hasValidPath() ) { return; } if ( $wpInstall->addUserFlagFile(false) ) { $wpInstall->setCmdStatusAndMsg( UserCommand::EXIT_SUCC, 'Flag file set' ); } else { $wpInstall->setCmdStatusAndMsg( UserCommand::EXIT_FAIL, 'Could not create flag file' ); } $this->workingQueue[$path] = $wpInstall; return; case self::CMD_UNFLAG: case self::CMD_MASS_UNFLAG: if ( !$wpInstall->hasValidPath() ) { return; } if ( $wpInstall->removeFlagFile(false) ) { $wpInstall->setCmdStatusAndMsg( UserCommand::EXIT_SUCC, 'Flag file unset' ); } else { $wpInstall->setCmdStatusAndMsg( UserCommand::EXIT_FAIL, 'Could not remove flag file' ); } $this->workingQueue[$path] = $wpInstall; return; case UserCommand::CMD_ENABLE: case UserCommand::CMD_DISABLE: case UserCommand::CMD_DASH_NOTIFY: case UserCommand::CMD_DASH_DISABLE: if ( $wpInstall->hasFatalError() ) { $wpInstall->refreshStatus(); if ( $wpInstall->hasFatalError() ) { $wpInstall->addUserFlagFile(false); $wpInstall->setCmdStatusAndMsg( UserCommand::EXIT_FAIL, 'Install skipped and flagged due to Error status.' ); $this->workingQueue[$path] = $wpInstall; return; } } break; case UserCommand::CMD_MASS_UPGRADE: $lscwpVer = $extraArgs[1]; $isAllowedVer = in_array( $lscwpVer, PluginVersion::getInstance()->getAllowedVersions() ); if ( !$isAllowedVer ) { throw new LSCMException( 'Selected LSCWP version (' . htmlspecialchars($lscwpVer) . ') is invalid.' ); } break; //no default } if ( UserCommand::issue($action, $wpInstall, $extraArgs) ) { if ( $action == UserCommand::CMD_MASS_UPGRADE && ($wpInstall->getCmdStatus() & UserCommand::EXIT_FAIL) && preg_match( '/Download failed. Not Found/', $wpInstall->getCmdMsg() ) ) { $this->syncToDisk(); throw new LSCMException( 'Could not download version ' . htmlspecialchars($extraArgs[1]) . '.' ); } if ( $action == UserCommand::CMD_MASS_ENABLE && ($wpInstall->getCmdStatus() & UserCommand::EXIT_FAIL) && preg_match( '/Source Package not available/', $wpInstall->getCmdMsg() ) ) { $this->syncToDisk(); throw new LSCMException($wpInstall->getCmdMsg()); } $this->workingQueue[$path] = $wpInstall; } } /** * * @param string $action * @param null|string[] $list * @param string[]|string[][] $extraArgs * * @return string[] * * @throws LSCMException Thrown indirectly by $this->prepareActionItems() * call. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by Context::getActionTimeout() * call. * @throws LSCMException Thrown indirectly by $this->scan() call. * @throws LSCMException Thrown indirectly by $this->addNewWPInstall() * call. * @throws LSCMException Thrown indirectly by * $this->addCustomInstallations() call. * @throws LSCMException Thrown indirectly by * PluginVersion::getCurrentVersion() call. * @throws LSCMException Thrown indirectly by PluginVersion::getInstance() * call. * @throws LSCMException Thrown indirectly by * PluginVersion::getInstance()->setActiveVersion() call. * @throws LSCMException Thrown indirectly by $this->doWPInstallAction() * call. * @throws LSCMException Thrown indirectly by $this->syncToDisk() call. */ public function doAction( $action, $list, array $extraArgs = [] ) { if ( $list === null ) { $list = $this->prepareActionItems($action); } $count = count($list); $this->log("doAction $action for $count items", Logger::L_VERBOSE); $endTime = ($count > 1) ? Context::getActionTimeout() : 0; $finishedList = []; switch ( $action ) { case self::CMD_SCAN: case self::CMD_DISCOVER_NEW: foreach ( $list as $path ) { $this->scan($path, ($action == self::CMD_SCAN)); $finishedList[] = $path; if ( $endTime && time() >= $endTime ) { break; } } break; case self::CMD_ADD_NEW_WPINSTALL: foreach ( $list as $path) { $this->addNewWPInstall($path); $finishedList[] = $path; if ( $endTime && time() >= $endTime ) { break; } } break; case self::CMD_ADD_CUST_WPINSTALLS: $this->addCustomInstallations($extraArgs[0]); break; default: if ( $action == UserCommand::CMD_ENABLE || $action == UserCommand::CMD_MASS_ENABLE ) { /** * Ensure that the current version is locally downloaded. */ PluginVersion::getInstance() ->setActiveVersion(PluginVersion::getCurrentVersion()) ; } foreach ( $list as $path ) { $this->doWPInstallAction($action, $path, $extraArgs); $finishedList[] = $path; if ( $endTime && time() >= $endTime ) { break; } } } $this->syncToDisk(); if ( $action == self::CMD_SCAN || $action == self::CMD_SCAN2 ) { /** * Explicitly clear any data file errors after scanning in case of * multiple actions performed in the same process (cli). */ $this->error = 0; } return $finishedList; } /** * * @deprecated 1.13.3 Use $this->scan2() instead. * * @since 1.17.10 Added 'find -- ' end-of-options guard. * * @param string $docroot * @param bool $forceRefresh * * @return void * * @throws LSCMException Thrown indirectly by Context::getScanDepth() call. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by * $this->wpInstalls[$wp_path]->refreshStatus() call. */ protected function scan( $docroot, $forceRefresh = false ) { /** * V6 (CWE-59 SSRF/symlink traversal) — use 'find -P' (the default; NOT * '-L') so find does not descend into symlinked directories. As root, * scanning a tenant-owned docroot with '-L' let a planted symlink (e.g. * public_html/x -> /root) surface a wp-admin that resolves outside the * tenant tree, steering subsequent root operations off-tree. * The '--' prevents a docroot starting with '-' from being misread as a * find option (escapeshellarg protects the shell, not find's own parser). */ $directories = shell_exec( 'find -P -- ' . escapeshellarg($docroot) . ' -maxdepth ' . (int) Context::getScanDepth() . ' -name wp-admin -print' ); $hasMatches = false; if ( $directories ) { /** * Example: * /home/user/public_html/wordpress/wp-admin * /home/user/public_html/blog/wp-admin * /home/user/public_html/wp/wp-admin */ $hasMatches = preg_match_all( '|' . preg_quote($docroot, '|') . '(.*)(?=/wp-admin)|', $directories, $matches ); } if ( ! $hasMatches ) { /** * Nothing found. */ return; } $realDocroot = realpath($docroot); /** * V9/V9.2 (CWE-59/CWE-367 cross-tenant TOCTOU) — capture the * panel-assigned docroot owner once before the loop. The docroot is * invariant across iterations; reading it here avoids repeated lstat() * calls and makes the binding available to both new and existing * installs (V9.2 fix: previously only new installs were rebound, * leaving upgraded existing installs with null Layer 2 bindings). */ $rootStat = @lstat($realDocroot); /** @noinspection PhpUndefinedVariableInspection */ foreach ( $matches[1] as $path ) { $wp_path = realpath($docroot . $path); /** * V6 — defence-in-depth: drop any match that does not canonically * resolve to a location contained under the docroot, so a symlinked * leaf component cannot redirect a root operation off-tree. * * Note: this realpath() is a snapshot, not a lock. A path component * could be swapped for a symlink after this check. That residual * race is intentionally handled at the consumer, not here: * - per-install enable/disable/upgrade/status run privilege- * dropped as the install owner (UserCommand::runAsUser), where * following an owner-planted symlink crosses no trust boundary; * - the one root-context write into the untrusted tree, * WPInstall::addUserFlagFile(), drops to install-owner * credentials (V8) before the unlink and fopen so an * intermediate-directory swap redirecting the path off-tree * fails with EACCES (CWE-59/CWE-367 closed at the consumer). */ if ( $wp_path === false || $realDocroot === false || strpos($wp_path . '/', $realDocroot . '/') !== 0 ) { $this->log( "Scan match not contained under docroot $docroot. Skipping.", Logger::L_INFO ); continue; } $refresh = $forceRefresh; if ( !isset($this->wpInstalls[$wp_path]) ) { $this->wpInstalls[$wp_path] = new WPInstall($wp_path); $refresh = true; $this->log( "New installation found: $wp_path", Logger::L_INFO ); if ( $this->custWpInstalls != null && isset($this->custWpInstalls[$wp_path]) ) { unset($this->custWpInstalls[$wp_path]); $this->log( "Installation removed from custom data file: $wp_path", Logger::L_INFO ); } } else { $this->log( "Installation already found: $wp_path", Logger::L_DEBUG ); } /** * V9/V9.2 — bind expected owner unconditionally on every scan * match, not only newly discovered installs. Existing installs * (loaded from the data file) must be rebound on each scan so * that Layer 2 (expected-owner equality check in addUserFlagFile) * fires for the root-context flag path after an upgrade or after * the first scan that discovered the install. */ if ( $rootStat !== false ) { $this->wpInstalls[$wp_path]->setExpectedOwner( $rootStat['uid'], $rootStat['gid'] ); } if ( $refresh ) { $this->wpInstalls[$wp_path]->refreshStatus(); $this->workingQueue[$wp_path] = $this->wpInstalls[$wp_path]; } } } /** * * @since 1.13.3 * @since 1.15 Changed function visibility from 'public' to * 'public static'. * @since 1.17.10 Added 'find -- ' end-of-options guard. * * @param string $docroot * * @return string[] * * @throws LSCMException Thrown indirectly by Context::getScanDepth() call. */ public static function scan2( $docroot ) { /** * V6 (CWE-59 SSRF/symlink traversal) — use 'find -P' (the default; NOT * '-L') so find does not descend into symlinked directories. As root, * scanning a tenant-owned docroot with '-L' let a planted symlink (e.g. * public_html/x -> /root) surface a wp-admin that resolves outside the * tenant tree, steering subsequent root operations off-tree. * The '--' prevents a docroot starting with '-' from being misread as a * find option (escapeshellarg protects the shell, not find's own parser). */ $directories = shell_exec( 'find -P -- ' . escapeshellarg($docroot) . ' -maxdepth ' . (int) Context::getScanDepth() . ' -name wp-admin -print' ); $hasMatches = false; if ( $directories ) { /** * Example: * /home/user/public_html/wordpress/wp-admin * /home/user/public_html/blog/wp-admin * /home/user/public_html/wp/wp-admin */ $hasMatches = preg_match_all( '|' . preg_quote($docroot, '|') . '(.*)(?=/wp-admin)|', $directories, $matches ); } if ( ! $hasMatches ) { /** * Nothing found. */ return []; } $wpPaths = []; $realDocroot = realpath($docroot); /** @noinspection PhpUndefinedVariableInspection */ foreach ( $matches[1] as $path ) { $wpPath = realpath($docroot . $path); /** * V6 — defence-in-depth: only return matches that canonically * resolve to a location contained under the docroot, so a symlinked * leaf component cannot redirect a root operation off-tree. * * Note: this realpath() is a snapshot, not a lock. A path component * could be swapped for a symlink after this check. That residual * race is intentionally handled at the consumer, not here: * - per-install enable/disable/upgrade/status run privilege- * dropped as the install owner (UserCommand::runAsUser), where * following an owner-planted symlink crosses no trust boundary; * - the one root-context write into the untrusted tree, * WPInstall::addUserFlagFile(), drops to install-owner * credentials (V8) before the unlink and fopen so an * intermediate-directory swap redirecting the path off-tree * fails with EACCES (CWE-59/CWE-367 closed at the consumer). */ if ( $wpPath === false || $realDocroot === false || strpos($wpPath . '/', $realDocroot . '/') !== 0 ) { continue; } $wpPaths[] = $wpPath; } return $wpPaths; } /** * Add a new WPInstall object to WPInstallStorage's $wpInstalls[] given a * path to a WordPress installation and refresh its status. If a WPInstall * object already exists for the given path, refresh its status. * * @since 1.13.3 * * @param string $wpPath * * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by * $this->wpInstalls[$wpPath]->refreshStatus() call. */ protected function addNewWPInstall( $wpPath ) { /** * V9.4 (CWE-59/CWE-367 cross-tenant TOCTOU) — drift-rejection guard. * * scan2() returns canonical, docroot-contained paths (produced via * realpath() + containment check). If realpath() here no longer * resolves to the same value, an intermediate directory component was * swapped (symlinked) between scan2's containment validation and this * invocation — the TOCTOU window that spans the WHM UI's multi-request * handoff (scan request stores paths in $_SESSION; discovery request * re-resolves them here). * * Fail closed: skip the add entirely so the swapped-in (victim) path * is never registered, never bound an owner from, and never flagged. * This prevents a compromised realpath() result from poisoning the V9 * Layer 2 owner binding captured two lines below. * * A legitimate scan2 path is already canonical, so realpath() is * idempotent and the equality holds with no false positives. */ $realPath = realpath($wpPath); if ( $realPath === false || $realPath !== $wpPath ) { $this->log( "Skipping add: install path $wpPath no longer canonicalises to " . 'itself (possible cross-tenant TOCTOU — intermediate ' . 'component swapped between scan2 and addNewWPInstall).', Logger::L_INFO ); return; } if ( !isset($this->wpInstalls[$wpPath]) ) { $this->wpInstalls[$wpPath] = new WPInstall($wpPath); $this->log("New installation found: $wpPath", Logger::L_INFO); if ( $this->custWpInstalls != null && isset($this->custWpInstalls[$wpPath]) ) { unset($this->custWpInstalls[$wpPath]); $this->log( "Installation removed from custom data file: $wpPath", Logger::L_INFO ); } } else { $this->log( "Installation already found: $wpPath", Logger::L_DEBUG ); } /** * V9.3 (CWE-59/CWE-367 cross-tenant TOCTOU) — bind the install * directory's owner observed in root context at this scan-time * snapshot. scan2() already canonicalised $wpPath via realpath() and * validated containment under the panel-assigned docroot before * returning it. Persisting the lstat() uid/gid here lets the later * root-context flag write (addUserFlagFile(false), in a separate * process / request) compare against a known-good snapshot rather * than a same-instant read of the very directory it is about to * modify — closing the race that Layers 1/3 leave open. * * Applied unconditionally to both newly-discovered and already-known * installs so that pre-V9.3 records hydrated with a null binding are * rebound on the next scan, mirroring §9 (V9.2)'s treatment in * scan(). lstat() is used (not stat()) so a symlinked leaf reports * the link's own inode owner rather than its target's, preventing * a same-instant final-component symlink swap from binding a * cross-tenant uid. If lstat() fails (path vanished between scan2 * and here), binding is skipped silently; the later flag write will * itself refuse on its own lstat($this->path) failure. */ $installStat = @lstat($wpPath); if ( $installStat !== false ) { $this->wpInstalls[$wpPath]->setExpectedOwner( $installStat['uid'], $installStat['gid'] ); } $this->wpInstalls[$wpPath]->refreshStatus(); $this->workingQueue[$wpPath] = $this->wpInstalls[$wpPath]; } /** * * @param string[] $wpInstallsInfo * * @return void * * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by * $this->custWpInstalls[$wpPath]->refreshStatus() call. * @throws LSCMException Thrown indirectly by $this->log() call. * @throws LSCMException Thrown indirectly by $this->log() call. */ protected function addCustomInstallations( array $wpInstallsInfo ) { if ( $this->customDataFile == '' ) { $this->log( 'No custom data file set, could not add custom Installation.', Logger::L_INFO ); return; } if ( $this->custWpInstalls == null ) { $this->custWpInstalls = []; } for ( $i = 0; $i < count($wpInstallsInfo); $i++ ) { $info = preg_split('/\s+/', trim($wpInstallsInfo[$i])); $line = $i + 1; if ( count($info) != 4 ) { $this->log( 'Incorrect number of values for custom installation input ' . "string on line $line. Skipping.", Logger::L_INFO ); continue; } $wpPath = $info[0]; if ( !Util::isSafeAbsPath($wpPath) ) { $this->log( "Unsafe wpPath value on line $line. Skipping.", Logger::L_INFO ); continue; } if ( !file_exists("$wpPath/wp-admin") ) { $this->log( "No 'wp-admin' directory found for $wpPath on line " . "$line. Skipping.", Logger::L_INFO ); continue; } $docroot = $info[1]; if ( !Util::isSafeAbsPath($docroot) ) { $this->log( "Unsafe docroot value on line $line. Skipping.", Logger::L_INFO ); continue; } $realWpPath = realpath($wpPath); $realDocroot = realpath($docroot); if ( $realWpPath === false || $realDocroot === false || strpos($realWpPath . '/', $realDocroot . '/') !== 0 ) { $this->log( "wpPath $wpPath not contained under docroot $docroot on " . "line $line. Skipping.", Logger::L_INFO ); continue; } if ( !isset($this->wpInstalls[$wpPath]) ) { $this->custWpInstalls[$wpPath] = new WPInstall($wpPath); $this->custWpInstalls[$wpPath]->setDocRoot($docroot); $this->custWpInstalls[$wpPath]->setServerName($info[2]); $this->custWpInstalls[$wpPath]->setSiteUrlDirect($info[3]); $this->custWpInstalls[$wpPath]->refreshStatus(); $this->log( "New installation added to custom data file: $wpPath", Logger::L_INFO ); } else { $this->log( "Installation already found during scan: $wpPath. " . 'Skipping.', Logger::L_INFO ); } } } /** * Get all WPInstall command messages as a key=>value array. * * @return string[][] */ public function getAllCmdMsgs() { $succ = $fail = $err = []; foreach ( $this->workingQueue as $wpInstall ) { if ( ($msg = $wpInstall->getCmdMsg()) ) { $cmdStatus = $wpInstall->getCmdStatus(); switch( true ) { case $cmdStatus & UserCommand::EXIT_SUCC: $msgType = &$succ; break; case $cmdStatus & UserCommand::EXIT_FAIL: $msgType = &$fail; break; case $cmdStatus & UserCommand::EXIT_ERROR: $msgType = &$err; break; default: continue 2; } $msgType[] = "{$wpInstall->getPath()} - $msg"; } } return [ 'succ' => $succ, 'fail' => $fail, 'err' => $err ]; } /** * * @param string $msg * @param int $level * * @throws LSCMException Thrown indirectly by Logger::error() call. * @throws LSCMException Thrown indirectly by Logger::warn() call. * @throws LSCMException Thrown indirectly by Logger::notice() call. * @throws LSCMException Thrown indirectly by Logger::info() call. * @throws LSCMException Thrown indirectly by Logger::verbose() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. */ protected function log( $msg, $level ) { $msg = "WPInstallStorage - $msg"; switch ( $level ) { case Logger::L_ERROR: Logger::error($msg); break; case Logger::L_WARN: Logger::warn($msg); break; case Logger::L_NOTICE: Logger::notice($msg); break; case Logger::L_INFO: Logger::info($msg); break; case Logger::L_VERBOSE: Logger::verbose($msg); break; case Logger::L_DEBUG: Logger::debug($msg); break; //no default } } } PK!lparseCommands($args); } /** * Checks if current $wpInstallStorage object is capable of having the * given non-scan action performed. * * @param string $action * @param WPInstallStorage $wpInstallStorage * * @return void * * @throws LSCMException Thrown when scan data cannot be read. * @throws LSCMException Thrown when expected scan data format has changed. * @throws LSCMException Thrown when attempting to execute a "mass" * operation without any discovered installations. */ private function checkDataFile( $action, WPInstallStorage $wpInstallStorage ) { if ( $action == WPInstallStorage::CMD_SCAN2 ) { /** * Always allowed. */ return; } if ( ($err = $wpInstallStorage->getError()) ) { switch ($err) { case WPInstallStorage::ERR_NOT_EXIST: case WPInstallStorage::ERR_CORRUPTED: case WPInstallStorage::ERR_VERSION_HIGH: throw new LSCMException( 'Scan data could not be read! Please scan again ' . '(without the \'-n\' flag) before attempting any ' . "cache operations.\n" ); case WPInstallStorage::ERR_VERSION_LOW: throw new LSCMException( 'Scan data file format has been changed for this ' . 'version. Please scan again (without the \'-n\' ' . "flag) before attempting any cache operations.\n" ); //no default } } elseif ( strpos($action,'mass_') === 0 && $wpInstallStorage->getCount() == 0 ) { throw new LSCMException( 'No WordPress installations discovered in the previous scan. ' . 'If you have any newly installed WordPress ' . 'installations, please scan again or add them with ' . "command 'addinstalls'.\n" ); } } /** * * @param WPInstall $wpInstall */ private function printStatusMsg( WPInstall $wpInstall ) { $msg = "$this->currWpPath - Status: "; $status = $wpInstall->getStatus(); if ( $status & WPInstall::ST_PLUGIN_ACTIVE ) { $msg .= 'enabled'; if ( !$status & WPInstall::ST_LSC_ADVCACHE_DEFINED ) { $msg .= ', not caching'; } } else { $msg .= 'disabled'; } $msg .= ' | Flagged: '; $msg .= ($status & WPInstall::ST_FLAGGED) ? 'yes' : 'no'; $msg .= ' | Error: '; if ( $status & WPInstall::ST_ERR_SITEURL ) { $msg .= 'Could not retrieve WordPress siteURL.'; } elseif ( $status & WPInstall::ST_ERR_DOCROOT ) { $msg .= 'Could not match WordPress siteURL to a known control ' . 'panel docroot.'; } elseif ( $status & WPInstall::ST_ERR_EXECMD ) { $msg .= 'WordPress fatal error encountered during action ' . 'execution. This is most likely caused by custom code in ' . 'this WordPress installation.'; } elseif ( $status & WPInstall::ST_ERR_EXECMD_DB ) { $msg .= 'Error establishing WordPress database connection.'; } elseif ( $status & WPInstall::ST_ERR_TIMEOUT ) { $msg .= 'Timeout occurred during action execution.'; } elseif ( $status & WPInstall::ST_ERR_WPCONFIG ) { $msg .= 'Could not find a valid wp-config.php file.'; } echo "$msg\n\n"; } /** * * @param string[] $args * * @return void * * @throws LSCMException Thrown when -svr parameter is passed without a * value. * @throws LSCMException Thrown when -svr parameter value points to a * non-empty directory. * @throws LSCMException Thrown when -vh parameter is passed without a * value. * @throws LSCMException Thrown when -vh parameter value contains invalid * character '$'. * @throws LSCMException Thrown when -vh parameter value points to a * non-empty directory. * @throws LSCMException Thrown indirectly by * ControlPanel::getClassInstance() call. * @throws LSCMException Thrown indirectly by * $controlPanel->getServerCacheRoot() call. * @throws LSCMException Thrown indirectly by * $controlPanel->getVHCacheRoot() call. */ private function handleSetCacheRootInput( array &$args ) { if ( empty($args) ) { $this->cacheRootCmds[] = 'listCacheRoots'; return; } $controlPanel = ControlPanel::getClassInstance(); if ( ($key = array_search('-svr', $args)) !== false ) { if ( empty($args[$key + 1]) || ($this->svrCacheRootParam = trim($args[$key + 1])) == '' ) { throw new LSCMException( 'Invalid Command, missing server cache root value.' ); } if ( !Util::isSafeAbsPath($this->svrCacheRootParam) ) { throw new LSCMException( 'Invalid Command, server cache root must be an absolute path ' . 'containing only [A-Za-z0-9_./-] characters and no ' . '\'..\' segments.' ); } $currSvrCacheRoot = $controlPanel->getServerCacheRoot(); if ( $this->svrCacheRootParam != $currSvrCacheRoot ) { if ( !Util::is_dir_empty($this->svrCacheRootParam) ) { throw new LSCMException( 'Provided server level cache root must be an empty ' . 'directory.' ); } $this->cacheRootCmds[] = 'setSvrCacheRoot'; } unset($args[$key], $args[$key + 1]); } if ( ($key = array_search('-vh', $args)) !== false ) { $setvhCacheRoot = false; if ( empty($args[$key + 1]) || ($this->vhCacheRootParam = trim($args[$key + 1])) == '' ) { throw new LSCMException( 'Invalid Command, missing virtual host cache root value.' ); } if ( strpos($this->vhCacheRootParam, '$') !== false ) { throw new LSCMException( 'Invalid Command, virtual host cache root value cannot ' . 'contain any \'$\' characters. \'$vh_user\' will be ' . 'automatically added to the end of virtual host ' . 'cache root values starting with a \'/\'.' ); } if ( $this->vhCacheRootParam[0] === '/' ) { if ( !Util::isSafeAbsPath($this->vhCacheRootParam) ) { throw new LSCMException( 'Invalid Command, absolute virtual host cache root must ' . 'contain only [A-Za-z0-9_./-] characters and no ' . '\'..\' segments.' ); } } elseif ( !preg_match('#^[A-Za-z0-9_\-]+$#', $this->vhCacheRootParam) ) { throw new LSCMException( 'Invalid Command, non-absolute virtual host cache root must ' . 'contain only [A-Za-z0-9_-] characters.' ); } $currVHCacheRoot = $controlPanel->getVHCacheRoot(); if ( $this->vhCacheRootParam[0] === '/' ) { $updatedVhCacheRoot = rtrim($this->vhCacheRootParam, '/') . '/$vh_user'; if ( $updatedVhCacheRoot != $currVHCacheRoot && ! Util::is_dir_empty($this->vhCacheRootParam) ) { throw new LSCMException( 'Provided absolute path for virtual host level cache ' . 'root must be an empty directory.' ); } $this->vhCacheRootParam = $updatedVhCacheRoot; $setvhCacheRoot = true; } elseif ( $this->vhCacheRootParam != $currVHCacheRoot ) { $setvhCacheRoot = true; } unset($args[$key], $args[$key + 1]); if ( $setvhCacheRoot ) { $this->cacheRootCmds[] = 'setVHCacheRoot'; } } } /** * * @param string[] $args * * @return void * * @throws LSCMException Thrown when passed version set value is invalid. */ private function handleSetVersionInput( array &$args ) { if ( ($key = array_search('--list', $args)) !== false ) { unset($args[$key]); $this->versionCmd = 'list'; return; } if ( ($key = array_search('--latest', $args)) !== false ) { unset($args[$key]); $this->versionCmd = 'latest'; return; } if ( empty($args) ) { $this->versionCmd = 'active'; return; } $v = array_shift($args); if ( preg_match('/[1-9]\.\d(?:\.\d)*(?:\.\d)*/', $v) !== 1 ) { throw new LSCMException("Invalid version number ($v)."); } $this->versionCmd = $v; } /** * * @param string[] $args */ private function handleScanInput( array &$args ) { if ( ($key = array_search('-n', $args)) !== false ) { unset($args[$key]); $this->commands[] = WPInstallStorage::CMD_DISCOVER_NEW2; } else { $this->commands[] = WPInstallStorage::CMD_SCAN2; } if ( ($key = array_search('-e', $args)) !== false ) { unset($args[$key]); $this->commands[] = UserCommand::CMD_MASS_ENABLE; } } /** * * @param string[] $args */ private function handleScanNewInput( array &$args ) { if ( ($key = array_search('-en', $args)) !== false ) { unset($args[$key]); $this->commands[] = WPInstallStorage::CMD_DISCOVER_NEW_AND_ENABLE; } else { $this->commands[] = WPInstallStorage::CMD_DISCOVER_NEW2; } } /** * * @param string[] $args * * @return bool */ private function isMassOperation( array &$args ) { if ( ($key = array_search('-m', $args)) !== false ) { unset($args[$key]); return true; } return false; } /** * * @param string $cmd * @param string[] $args * * @throws LSCMException Thrown when expected WP path value is not * provided. * @throws LSCMException Thrown when provided an invalid WP path value. */ private function handleSingleOperationInput( $cmd, array &$args ) { $path = array_shift($args); if ( $path == null ) { throw new LSCMException('Invalid Command, missing WP path.'); } $wpInstall = new WPInstall($path); if ( !$wpInstall->hasValidPath() ) { throw new LSCMException("Invalid WP Path: $path."); } $this->commands[] = $cmd; $this->currWpPath = rtrim($path, '/'); } /** * * @param string $cmdType * @param string[] $args * * @throws LSCMException Thrown when neither -m nor -wppath parameters are * provided in notify command. * @throws LSCMException Thrown when -wppath parameter is passed without a * value in notify command. * @throws LSCMException Thrown when provided -wppath parameter value is * invalid in notify command. * @throws LSCMException Thrown when -msgfile parameter is passed without a * value in notify command. * @throws LSCMException Thrown when provided -msgfile parameter value * points to a non-existent file in notify command. * @throws LSCMException Thrown when unable to get file contents of the * file pointed to by provided -msgfile value in notify command. * @throws LSCMException Thrown when neither -msgfile nor -msg parameters * are provided in notify command. * @throws LSCMException Thrown when parameter -msg is passed without a * value in notify command. * @throws LSCMException Thrown when expected -plugin parameter is not * provided in notify command. * @throws LSCMException Thrown when provided -plugin parameter value does * not a known plugin slug in notify command. * @throws LSCMException Thrown when neither -m flag nor WP path value are * provided in remove command. * @throws LSCMException Thrown when provided WP path value is invalid in * remove command. */ private function handleDashNotifyInput( $cmdType, array &$args ) { if ( $cmdType == 'notify' ) { if ( ($key = array_search('-m', $args)) !== false ) { unset($args[$key]); $this->commands[] = UserCommand::CMD_MASS_DASH_NOTIFY; } else { if ( ($key = array_search('-wppath', $args)) === false ) { throw new LSCMException( 'Invalid Command, missing required \'-m\' or ' . '\'-wppath\' parameter.' ); } if ( empty($args[$key + 1]) ) { throw new LSCMException( 'Invalid Command, missing \'-wppath\' value.' ); } $path = $args[$key + 1]; $wpInstall = new WPInstall($path); if ( !$wpInstall->hasValidPath() ) { throw new LSCMException("Invalid WP Path: $path."); } $this->commands[] = UserCommand::CMD_DASH_NOTIFY; $this->currWpPath = rtrim($path, '/'); unset($args[$key], $args[$key + 1]); } if ( ($key = array_search('-msgfile', $args)) !== false ) { if ( empty($args[$key + 1]) ) { throw new LSCMException( 'Invalid Command, missing \'-msgfile\' value.' ); } $msgFilePath = $args[$key + 1]; if ( !file_exists($msgFilePath) ) { throw new LSCMException( 'Provided message file does not exist.' ); } if ( ($message = file_get_contents($msgFilePath)) === false ) { throw new LSCMException( 'Unable to retrieve provided message file content.' ); } } else { if ( ($key = array_search('-msg', $args)) === false ) { throw new LSCMException( 'Invalid Command, missing required \'-msgfile\' or ' . '\'-msg\' parameter.' ); } if ( empty($args[$key + 1]) ) { throw new LSCMException( 'Invalid Command, missing \'-msg\' value.' ); } $message = $args[$key + 1]; } $dashInput = array( 'msg' => $message ); unset($args[$key], $args[$key + 1]); if ( ($key = array_search('-plugin', $args)) !== false ) { if ( empty($args[$key + 1]) ) { throw new LSCMException( 'Invalid Command, missing \'-plugin\' value.' ); } $slug = $args[$key + 1]; $pluginInfoJSON = Util::get_url_contents( "https://api.wordpress.org/plugins/info/1.0/$slug.json" ); $pluginInfo = json_decode($pluginInfoJSON, true); if ( empty($pluginInfo['name']) ) { throw new LSCMException( 'Could not find a plugin matching the provided plugin ' . 'slug.' ); } $dashInput['slug'] = $slug; unset($args[$key], $args[$key + 1]); } $this->input = $dashInput; } elseif ( $cmdType == 'remove' ) { $arg1 = array_shift($args); if ( $arg1 == '-m' ) { $this->commands[] = UserCommand::CMD_MASS_DASH_DISABLE; } else { $path = $arg1; if ( $path == null ) { throw new LSCMException( 'Invalid Command, missing \'-m\' flag or WP path value.' ); } $wpInstall = new WPInstall($path); if ( !$wpInstall->hasValidPath() ) { throw new LSCMException("Invalid WP Path: $path."); } $this->commands[] = UserCommand::CMD_DASH_DISABLE; $this->currWpPath = rtrim($path, '/'); } } } /** * * @param string[] $args * * @throws LSCMException Thrown when command 'cpanelplugin' is used in a * non-cPanel environment. * @throws LSCMException Thrown indirectly by * ControlPanel::getClassInstance() call. */ private function handleCpanelPluginInput( array &$args ) { $controlPanel = ControlPanel::getClassInstance(); if ( !($controlPanel instanceof CPanel) ) { throw new LSCMException( 'Command \'cpanelplugin\' cannot be used in a non-cPanel ' . 'environment.' ); } switch ($args[0]) { case '--install': $this->specialCmd = self::SPECIAL_CMD_CPANEL_PLUGIN_INSTALL; unset($args[0]); break; case '--uninstall': $this->specialCmd = self::SPECIAL_CMD_CPANEL_PLUGIN_UNINSTALL; unset($args[0]); break; case '-autoinstall': if ( !isset($args[1]) ) { $this->specialCmd = self::SPECIAL_CMD_CPANEL_PLUGIN_AUTOINSTALL_STATUS; } elseif ( "$args[1]" === '1' ) { $this->specialCmd = self::SPECIAL_CMD_CPANEL_PLUGIN_AUTOINSTALL_ON; unset($args[1]); } elseif ( "$args[1]" === '0' ) { $this->specialCmd = self::SPECIAL_CMD_CPANEL_PLUGIN_AUTOINSTALL_OFF; unset($args[1]); } unset($args[0]); break; case '--fixconf': $this->specialCmd = self::SPECIAL_CMD_CPANEL_PLUGIN_FIX_CONF; unset($args[0]); break; //no default } } /** * * @param string[] $args * * @throws LSCMException Thrown when -wpinstall parameter is passed without * a value. * @throws LSCMException Thrown when expected 'docroot' value is not * provided when using parameter -wpinstall. * @throws LSCMException Thrown when expected 'server name' value is not * provided when using parameter -wpinstall. * @throws LSCMException Thrown when expected 'site url' value is not * provided when using parameter -wpinstall. * @throws LSCMException Thrown when -wpinstallsfile parameter is passed * without a value. * @throws LSCMException Thrown when provided -wpinstallsfile parameter * value points to a non-existent file. * @throws LSCMException Thrown when unable to get file contents of the * file pointed to by provided -wpinstallsfile parameter value. */ private function handleAddInstallsInput( array &$args ) { switch ($args[0]) { case '-wpinstall': if ( empty($args[1]) ) { throw new LSCMException( 'Invalid Command, missing \'\' value.' ); } $wpInstallsInfo = "$args[1]"; if ( empty($args[2]) ) { throw new LSCMException( 'Invalid Command, missing \'\' value.' ); } $wpInstallsInfo .= " $args[2]"; if ( empty($args[3]) ) { throw new LSCMException( 'Invalid Command, missing \'\' value.' ); } $wpInstallsInfo .= " $args[3]"; if ( empty($args[4]) ) { throw new LSCMException( 'Invalid Command, missing \'\' value.' ); } $wpInstallsInfo .= " $args[4]"; $this->commands[] = WPInstallStorage::CMD_ADD_CUST_WPINSTALLS; $this->input = array( 'addInstallsInfo' => array($wpInstallsInfo) ); unset($args[0], $args[1], $args[2], $args[3], $args[4]); break; case '-wpinstallsfile': if ( empty($args[1]) ) { throw new LSCMException( 'Invalid Command, missing \'-wpinstallsfile\' value.' ); } $wpInstallsFile = $args[1]; if ( !file_exists($wpInstallsFile) ) { throw new LSCMException( 'Provided wpinstalls file does not exist.' ); } $fileContent = file_get_contents($wpInstallsFile); if ( $fileContent === false ) { throw new LSCMException( 'Could not read wpinstalls file content.' ); } $this->commands[] = WPInstallStorage::CMD_ADD_CUST_WPINSTALLS; $this->input = array( 'addInstallsInfo' => explode("\n", trim($fileContent)) ); unset($args[0], $args[1]); break; // no default } } /** * * @throws LSCMException Thrown indirectly by * ControlPanel::getClassInstance() call. * @throws LSCMException Thrown indirectly by * $controlPanel->getServerCacheRoot() call. * @throws LSCMException Thrown indirectly by * $controlPanel->getVHCacheRoot() call. */ private function displayCacheRoots() { $controlPanel = ControlPanel::getClassInstance(); $svrCacheRoot = $controlPanel->getServerCacheRoot(); $vhCacheRoot = $controlPanel->getVHCacheRoot(); if ( $svrCacheRoot == ControlPanel::NOT_SET ) { $svrCacheRoot = 'Not Set'; } if ( $vhCacheRoot == ControlPanel::NOT_SET) { $vhCacheRoot = 'Not Set'; } echo <<handleSetCacheRootInput() call. * @throws LSCMException Thrown indirectly by * $this->handleSetVersionInput() call. * @throws LSCMException Thrown indirectly by * $this->handleSingleOperationInput() call. * @throws LSCMException Thrown indirectly by * $this->handleDashNotifyInput() call. * @throws LSCMException Thrown indirectly by * $this->handleDashNotifyInput() call. * @throws LSCMException Thrown indirectly by * $this->handleCpanelPluginInput() call. * @throws LSCMException Thrown indirectly by * $this->handleAddInstallsInput() call. */ private function parseCommands( array $args ) { $panelClassName = array_shift($args); /** * Initialize ControlPanel instance. */ ControlPanel::getClassInstance($panelClassName); $cmd = array_shift($args); switch ( $cmd ) { case 'setcacheroot': if ( $panelClassName == 'custom' ) { throw new LSCMException( 'Command \'setcacheroot\' cannot be used in the ' . 'CustomPanel context.' ); } $this->handleSetCacheRootInput($args); break; case 'setversion': $this->handleSetVersionInput($args); break; case 'scan': $this->handleScanInput($args); break; case 'scannew': $this->handleScanNewInput($args); break; case 'enable': case 'disable': case 'upgrade': /** @noinspection PhpMissingBreakStatementInspection */ case 'unflag': if ( $this->isMassOperation($args) ) { $this->commands[] = "mass_$cmd"; break; } //fall through case 'flag': case 'status': $this->handleSingleOperationInput($cmd, $args); break; case 'dashnotify': $this->handleDashNotifyInput('notify', $args); break; case 'dashnotifyremove': $this->handleDashNotifyInput('remove', $args); break; case 'cpanelplugin': $this->handleCpanelPluginInput($args); break; case 'addinstalls': $this->handleAddInstallsInput($args); break; default: throw new LSCMException('Invalid Command, Try --help.'); } if ( !empty($args) ) { throw new LSCMException('Invalid Command, Try --help.'); } } /** * * @param string $action * * @throws LSCMException Thrown indirectly by * ControlPanel::getClassInstance() call. * @throws LSCMException Thrown indirectly by * $controlPanel->setServerCacheRoot() call. * @throws LSCMException Thrown indirectly by * $controlPanel->setVHCacheRoot() call. * @throws LSCMException Thrown indirectly by Util::restartLsws() call. * @throws LSCMException Thrown indirectly by * $controlPanel->getVHCacheRoot() call. */ private function doCacheRootCommand( $action ) { $restartRequired = false; $controlPanel = ControlPanel::getClassInstance(); switch ( $action ) { case 'setSvrCacheRoot': $controlPanel->setServerCacheRoot($this->svrCacheRootParam); $restartRequired = true; break; case 'setVHCacheRoot': $controlPanel->setVHCacheRoot($this->vhCacheRootParam); $restartRequired = true; break; case 'listCacheRoots': /** * Wait until after verifyCacheSetup() has been run. */ $this->displayCacheRoots = true; break; //no default } if ( $restartRequired ) { Util::restartLsws(); } Util::ensureVHCacheRootInCage($controlPanel->getVHCacheRoot()); } /** * * @throws LSCMException Thrown indirectly by * ControlPanel::getClassInstance() call. * @throws LSCMException Thrown indirectly by * $controlPanel->installCpanelPlugin() call. * @throws LSCMException Thrown indirectly by * CPanel::uninstallCpanelPlugin() call. * @throws LSCMException Thrown indirectly by * $controlPanel->updateCoreCpanelPluginConfSettings() call. */ private function doSpecialCommand() { $controlPanel = ControlPanel::getClassInstance(); switch($this->specialCmd) { case self::SPECIAL_CMD_CPANEL_PLUGIN_INSTALL: /* @var $controlPanel CPanel */ switch ( $controlPanel->installCpanelPlugin() ) { case 'update': echo 'Updated LiteSpeed cPanel plugin to current ' . "version\n\n"; break; case 'new': echo 'LiteSpeed cPanel plugin installed. Auto install ' . "policy unchanged (use 'cpanelplugin -autoinstall" . " {0|1}' to manage).\n\n"; break; //no default } break; case self::SPECIAL_CMD_CPANEL_PLUGIN_UNINSTALL: CPanel::uninstallCpanelPlugin(); echo 'LiteSpeed cPanel plugin uninstalled successfully, auto ' . "install turned off.\n\n"; break; case self::SPECIAL_CMD_CPANEL_PLUGIN_AUTOINSTALL_STATUS: $state = (CPanel::isCpanelPluginAutoInstallOn()) ? 'On' : 'Off'; echo "Auto install is currently $state for the LiteSpeed " . "cPanel plugin.\n"; echo 'Note: if the plugin is already installed, it will ' . "continue to be refreshed on WHM plugin upgrades\n" . 'regardless of this setting. Use \'cpanelplugin ' . "--uninstall' to stop updates entirely.\n"; echo 'Use command \'cpanelplugin -autoinstall {0 | 1}\' to ' . "enable/disable fresh installation respectively.\n\n"; break; case self::SPECIAL_CMD_CPANEL_PLUGIN_AUTOINSTALL_ON: if ( CPanel::turnOnCpanelPluginAutoInstall() ) { echo 'Auto install is now On for LiteSpeed cPanel plugin.' . "\n\n"; } else { echo 'Failed to turn on auto install for LiteSpeed cPanel ' . "plugin.\n\n"; } break; case self::SPECIAL_CMD_CPANEL_PLUGIN_AUTOINSTALL_OFF: if ( CPanel::turnOffCpanelPluginAutoInstall() ) { echo 'Auto install is now Off for LiteSpeed cPanel plugin.' . ' (Already-installed plugin files will still be' . " refreshed on WHM plugin upgrades;\n" . "use 'cpanelplugin --uninstall' to stop updates" . " entirely.)\n\n"; } else { echo 'Failed to turn off auto install for LiteSpeed cPanel ' . "plugin.\n\n"; } break; case self::SPECIAL_CMD_CPANEL_PLUGIN_FIX_CONF: /* @var $controlPanel CPanel */ $controlPanel->updateCoreCpanelPluginConfSettings(); echo "Attempted to fix user-end cPanel Plugin conf.\n\n"; break; //no default } } /** * * @throws LSCMException Thrown indirectly by PluginVersion::getInstance() * call. * @throws LSCMException Thrown indirectly by * $pluginVerInstance->getAllowedVersions() call. * @throws LSCMException Thrown indirectly by * $pluginVerInstance->getLatestVersion() call. * @throws LSCMException Thrown indirectly by * $pluginVerInstance->setActiveVersion() call. * @throws LSCMException Thrown indirectly by * $pluginVerInstance->getCurrentVersion() call. * @throws LSCMException Thrown indirectly by * $pluginVerInstance->setActiveVersion() call. */ private function doVersionCommand() { $pluginVerInstance = PluginVersion::getInstance(); switch ( $this->versionCmd ) { case 'list': echo "Available versions are: \n" . implode("\n",$pluginVerInstance->getAllowedVersions()) . "\n"; break; case 'latest': $latest = $pluginVerInstance->getLatestVersion(); try { $currVer = $pluginVerInstance->getCurrentVersion(); } catch ( LSCMException $e ) { $currVer = ''; } if ( $latest == $currVer ) { echo "Current version, $latest, is already the latest " . "version.\n"; } else { $pluginVerInstance->setActiveVersion($latest); } break; case 'active': echo "Current active version is " . $pluginVerInstance->getCurrentVersion() . ".\n"; break; default: $pluginVerInstance->setActiveVersion($this->versionCmd); } } /** * * @throws LSCMException Thrown indirectly by Context::getLSCMDataFiles() * call. * @throws LSCMException Thrown indirectly by "new WPInstallStorage()" * call. * @throws LSCMException Thrown indirectly by $this->checkDataFile() call. * @throws LSCMException Thrown indirectly by PluginVersion::getInstance() * call. * @throws LSCMException Thrown indirectly by * $pluginVerInstance->getShortVersions() call. * @throws LSCMException Thrown indirectly by * $pluginVerInstance->getCurrentVersion() call. * @throws LSCMException Thrown indirectly by * DashNotifier::prepLocalDashPluginFiles() call. * @throws LSCMException Thrown indirectly by * ControlPanel::getClassInstance() call. * @throws LSCMException Thrown indirectly by * ControlPanel::getClassInstance()->getDocRoots() call. * @throws LSCMException Thrown indirectly by $wpInstallStorage->scan2() * call. * @throws LSCMException Thrown indirectly by $wpInstallStorage->doAction() * call. */ private function doWPInstallStorageAction() { $extraArgs = array(); $list = null; $originalAction = null; $lscmDataFiles = Context::getLSCMDataFiles(); $wpInstallStorage = new WPInstallStorage( $lscmDataFiles['dataFile'], $lscmDataFiles['custDataFile'] ); if ( $this->currWpPath ) { $list = array( $this->currWpPath ); } foreach ( $this->commands as $action ) { $this->checkDataFile($action, $wpInstallStorage); echo "\nPerforming $action operation. Please be patient...\n\n"; switch ( $action ) { case UserCommand::CMD_UPGRADE: case UserCommand::CMD_MASS_UPGRADE: $pluginVerInstance = PluginVersion::getInstance(); $extraArgs[] = implode( ',', $pluginVerInstance->getShortVersions() ); $extraArgs[] = $pluginVerInstance->getCurrentVersion(); break; case UserCommand::CMD_DASH_NOTIFY: case UserCommand::CMD_MASS_DASH_NOTIFY: DashNotifier::prepLocalDashPluginFiles(); $slug = ''; if ( isset($this->input['slug']) ) { $slug = $this->input['slug']; } $msgInfoJSON = json_encode( array( 'msg' => $this->input['msg'], 'plugin' => $slug, 'plugin_name' => '' ) ); $extraArgs[] = base64_encode($msgInfoJSON); break; case WPInstallStorage::CMD_ADD_CUST_WPINSTALLS: $list = array(); $extraArgs[] = $this->input['addInstallsInfo']; break; case WPInstallStorage::CMD_SCAN2: case WPInstallStorage::CMD_DISCOVER_NEW2: case WPInstallStorage::CMD_DISCOVER_NEW_AND_ENABLE: $wpPaths = array(); $docroots = ControlPanel::getClassInstance()->getDocRoots(); foreach ( $docroots as $docroot ) { $wpPaths = array_merge( $wpPaths, WPInstallStorage::scan2($docroot) ); } $list = array(); if ( $action == WPInstallStorage::CMD_DISCOVER_NEW2 || $action == WPInstallStorage::CMD_DISCOVER_NEW_AND_ENABLE ) { foreach( $wpPaths as $wpPath ) { if ( $wpInstallStorage->getWPInstall($wpPath) == null ) { $list[] = $wpPath; } } } else { $list = array_merge($list, $wpPaths); } $originalAction = $action; $action = WPInstallStorage::CMD_ADD_NEW_WPINSTALL; break; // no default case } $wpInstallStorage->doAction($action, $list, $extraArgs); if ( $originalAction == WPInstallStorage::CMD_DISCOVER_NEW_AND_ENABLE ) { $wpInstallStorage->doAction( UserCommand::CMD_MASS_ENABLE, $list ); } if ( $action == UserCommand::CMD_STATUS ) { $wpInstall = $wpInstallStorage->getWPInstall($this->currWpPath); $this->printStatusMsg($wpInstall); } if ( $originalAction != null ) { $action = $originalAction; } echo "\n$action complete!\n\n"; } } /** * * @throws LSCMException Thrown indirectly by $this->doCacheRootCommand() * call. * @throws LSCMException Thrown indirectly by * ControlPanel::getClassInstance() call. * @throws LSCMException Thrown indirectly by * $controlPanel->verifyCacheSetup() call. * @throws LSCMException Thrown indirectly by $this->displayCacheRoots() * call. * @throws LSCMException Thrown indirectly by $this->doSpecialCommand() * call. * @throws LSCMException Thrown indirectly by $this->doVersionCommand() * call. * @throws LSCMException Thrown indirectly by * $this->doWPInstallStorageAction() call. */ private function runCommand() { foreach ( $this->cacheRootCmds as $action ) { $this->doCacheRootCommand($action); } $controlPanel = ControlPanel::getClassInstance(); $controlPanel->verifyCacheSetup(); if ( $this->displayCacheRoots ) { $this->displayCacheRoots(); } if ( $this->specialCmd ) { $this->doSpecialCommand(); } elseif ( $this->versionCmd ) { $this->doVersionCommand(); } else { $this->doWPInstallStorageAction(); } } public static function run() { try { $cli = new self(); $cli->runCommand(); } catch ( Exception $e ) { echo "[ERROR] {$e->getMessage()}\n\n"; exit(1); } } } PK!u)Vaa'webcachemgr/src/RedefineGlobalFuncs.phpnuIw $timeout); } /** * This function is used to get the file owner by name. Useful in cases * where UID is not accepted or setting a files group to match its owner * (It is not safe to assume UID == GID or GID exists for username 'x'). * * @since 2.2.0 * * @param string $filepath * * @return array Keys are id, name, group_id */ public static function populateOwnerInfo( $filepath ) { clearstatcache(); $ownerID = fileowner($filepath); $ownerInfo = posix_getpwuid($ownerID); return array( 'user_id' => $ownerID, 'user_name' => $ownerInfo['name'], 'group_id' => filegroup($filepath) ); } /** * * @param string $file * @param string $owner * @param string $group */ public static function changeUserGroup( $file, $owner, $group ) { chown($file, $owner); chgrp($file, $group); } /** * Set file permissions of $file2 to match those of $file1. * * @since 2.2.0 * * @param string $file1 * @param string $file2 */ public static function matchPermissions( $file1, $file2 ) { /** * convert fileperms() returned dec to oct */ chmod($file2, (fileperms($file1) & 0777)); } /** * * @since 1.14.3 * * @param string $url * @param bool $headerOnly * * @return string */ public static function getUrlContentsUsingFileGetContents( $url, $headerOnly = false ) { if ( ini_get('allow_url_fopen') ) { /** * silence warning when OpenSSL missing while getting LSCWP ver * file. */ $url_content = @file_get_contents($url); if ( $url_content !== false ) { if ( $headerOnly ) { return implode("\n", $http_response_header); } return $url_content; } } return ''; } /** * * @since 1.14.3 * * @param string $url * @param bool $headerOnly * * @return string */ public static function getUrlContentsUsingPhpCurl( $url, $headerOnly = false ) { if ( function_exists('curl_version') ) { $ch = curl_init(); curl_setopt_array( $ch, array( CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => $headerOnly, CURLOPT_NOBODY => $headerOnly, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1 ) ); $url_content = curl_exec($ch); curl_close($ch); if ( $url_content !== false ) { return $url_content; } } return ''; } /** * * @since 1.14.3 * * @param string $url * @param string $headerOnly * * @return string */ public static function getUrlContentsUsingExecCurl( $url, $headerOnly = false ) { $cmd = 'curl -s'; if ( $headerOnly ) { $cmd .= ' -I'; } exec("$cmd " . escapeshellarg($url), $output, $ret); if ( $ret === 0 ) { return implode("\n", $output); } return ''; } /** * * @param string $url * @param bool $headerOnly * * @return string */ public static function get_url_contents( $url, $headerOnly = false ) { $content = self::getUrlContentsUsingFileGetContents($url, $headerOnly); if ( $content != '' ) { return $content; } $content = self::getUrlContentsUsingPhpCurl($url, $headerOnly); if ( $content != '' ) { return $content; } return self::getUrlContentsUsingExecCurl($url, $headerOnly); } /** * * @param string $dir * * @return false|string */ public static function DirectoryMd5( $dir ) { if ( !is_dir($dir) ) { return false; } $fileMd5s = array(); $d = dir($dir); while ( ($entry = $d->read()) !== false ) { if ( $entry != '.' && $entry != '..' ) { $currEntry = "$dir/$entry"; if ( is_dir($currEntry) ) { $fileMd5s[] = self::DirectoryMd5($currEntry); } else { $fileMd5s[] = md5_file($currEntry); } } } $d->close(); return md5(implode('', $fileMd5s)); } /** * * @param string $file * @param string $backup * * @return bool * * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. */ private static function matchFileSettings( $file, $backup ) { clearstatcache(); $ownerID = fileowner($file); $groupID = filegroup($file); if ( $ownerID === false || $groupID === false ) { Logger::debug("Could not get owner/group of file $file"); unlink($backup); Logger::debug("Removed file $backup"); return false; } self::changeUserGroup($backup, $ownerID, $groupID); self::matchPermissions($file, $backup); return true; } /** * * @param string $filepath * @param string $bak * * @return string */ private static function getBackupSuffix( $filepath, $bak = '_lscachebak_orig' ) { $i = 1; if ( file_exists($filepath . $bak) ) { $bak = sprintf("_lscachebak_%02d", $i); while ( file_exists($filepath . $bak) ) { $i++; $bak = sprintf("_lscachebak_%02d", $i); } } return $bak; } /** * * @param string $filepath * * @return bool * * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by Logger::verbose() call. * @throws LSCMException Thrown indirectly by self::matchFileSettings() * call. * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by Logger::info() call. */ public static function createBackup( $filepath ) { $backup = $filepath . self::getBackupSuffix($filepath); if ( !copy($filepath, $backup) ) { Logger::debug( "Could not backup file $filepath to location $backup" ); return false; } Logger::verbose("Created file $backup"); if ( !self::matchFileSettings($filepath, $backup) ) { Logger::debug( "Could not backup file $filepath to location $backup" ); return false; } Logger::debug('Matched owner/group setting for both files'); Logger::info( "Successfully backed up file $filepath to location $backup" ); return true; } /** * * @param string $zipFile * @param string $dest * * @return bool * * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. */ public static function unzipFile( $zipFile, $dest ) { if ( class_exists('\ZipArchive') ) { $zipArchive = new ZipArchive(); if ( $zipArchive->open($zipFile) === true ) { $realDest = realpath($dest); if ( $realDest === false ) { $zipArchive->close(); Logger::debug( "Could not unzip $zipFile: destination directory does not exist." ); return false; } $realDest = rtrim($realDest, '/') . '/'; $slipDetected = false; for ( $i = 0; $i < $zipArchive->numFiles; $i++ ) { $entryName = $zipArchive->getNameIndex($i); if ( $entryName === false ) { continue; } /** * Resolve the entry path without relying on realpath() * (extracted file does not exist yet). Walk each segment, * collapsing '.' and '..', then check the result is * confined to $realDest. */ $parts = []; foreach ( explode('/', $realDest . $entryName) as $part ) { if ( $part === '' || $part === '.' ) { continue; } if ( $part === '..' ) { array_pop($parts); } else { $parts[] = $part; } } $resolvedPath = '/' . implode('/', $parts); if ( strncmp($realDest, $resolvedPath . '/', strlen($realDest)) !== 0 ) { $slipDetected = true; break; } } if ( $slipDetected ) { $zipArchive->close(); Logger::debug( "Zip-slip attempt detected in $zipFile - extraction aborted." ); return false; } $extracted = $zipArchive->extractTo($dest); $zipArchive->close(); if ( $extracted ) { return true; } } Logger::debug("Could not unzip $zipFile using ZipArchive."); } else { Logger::debug( "Could not unzip $zipFile: ZipArchive extension unavailable." ); } return false; } /** * Returns true if $path is a non-empty absolute filesystem path * containing only characters safe for use in shell commands and Apache * configuration (alphanumerics, underscore, hyphen, period, forward * slash) and no '..' traversal segments. * * Use this to gate values before interpolating them into shell commands * or writing them into configuration files. * * @since 1.17.10 * * @param string $path * * @return bool */ public static function isSafeAbsPath( $path ) { if ( !is_string($path) || $path === '' || $path[0] !== '/' ) { return false; } if ( !preg_match('#^/[A-Za-z0-9_./\-]*$#', $path) ) { return false; } $normalizedPath = rtrim($path, '/'); if ( $normalizedPath === '' ) { return false; } foreach ( array_slice(explode('/', $normalizedPath), 1) as $segment ) { if ( $segment === '' || $segment === '.' || $segment === '..' ) { return false; } } return true; } /** * Check if a given directory is empty. * * @param string $dir * * @return bool */ public static function is_dir_empty( $dir ) { if ( !($handle = @opendir($dir)) ) { return true; } while ( ($entry = readdir($handle)) !== false ) { if ( $entry != '.' && $entry != '..' ) { return false; } } return true; } /** * * @param string $vhCacheRoot */ public static function ensureVHCacheRootInCage( $vhCacheRoot ) { $cageFsFile = '/etc/cagefs/cagefs.mp'; if ( file_exists($cageFsFile) ) { if ( $vhCacheRoot[0] == '/' ) { $cageVhCacheRoot = '%' . str_replace('/$vh_user', '', $vhCacheRoot); $matchFound = preg_grep( "!^\s*" . str_replace('!', '\!', $cageVhCacheRoot) . "!im", file($cageFsFile) ); if ( !$matchFound ) { file_put_contents( $cageFsFile, "\n$cageVhCacheRoot", FILE_APPEND ); exec('/usr/sbin/cagefsctl --remount-all'); } } } } /** * Recursively a directory's contents and optionally the directory itself. * * @param string $dir Directory path * @param bool $keepParent Only remove directory contents when true. * * @return bool */ public static function rrmdir( $dir, $keepParent = false ) { if ( !is_string($dir) || $dir === '' || $dir === '/' || $dir === '.' || $dir === '..' ) { return false; } /** * V14 (CWE-59): if the top-level path itself is a symlink, never descend * through it. is_dir() follows symlinks, so recursing here would * enumerate and delete the link target's contents. Remove only the * link node instead. */ if ( is_link($dir) ) { return $keepParent ? false : unlink($dir); } if ( is_dir($dir) ) { if ( ($matches = glob("$dir/*")) === false ) { return false; } foreach ( $matches as $file ) { /** * V14 (CWE-59): never descend into symlinked directories. A symlink * whose target is a directory makes is_dir() true, which would * cause recursion to delete files outside the intended tree. * Remove the link node itself instead. */ if ( is_link($file) ) { unlink($file); } elseif ( is_dir($file) ) { self::rrmdir($file); } else { unlink($file); } } if ( !$keepParent ) { rmdir($dir); } return true; } return false; } /** * Wrapper for idn_to_utf8() function call to avoid "undefined" exceptions * when PHP intl module is not installed and enabled. * * @since 1.13.13.1 * * @param string $domain * @param int $flags * @param int|null $variant * @param array|null $idna_info * * @return false|string */ public static function tryIdnToUtf8( $domain, $flags = 0, $variant = null, &$idna_info = null ) { if ( empty($domain) || !function_exists('idn_to_utf8') ) { return $domain; } if ( defined('INTL_IDNA_VARIANT_UTS46') ) { if ( $variant == null ) { $variant = INTL_IDNA_VARIANT_UTS46; } return idn_to_utf8($domain, $flags, $variant, $idna_info); } return idn_to_utf8($domain, $flags); } /** * Wrapper for idn_to_ascii() function call to avoid "undefined" exceptions * when PHP intl module is not installed and enabled. * * @since 1.13.13.1 * * @param string $domain * @param int|null $flags * @param int|null $variant * @param array|null $idna_info * * @return false|string */ public static function tryIdnToAscii( $domain, $flags = null, $variant = null, &$idna_info = null ) { if ( empty($domain) || !function_exists('idn_to_ascii') ) { return $domain; } if ( $flags == null ) { $flags = IDNA_DEFAULT; } if ( defined('INTL_IDNA_VARIANT_UTS46') ) { if ( $variant == null ) { $variant = INTL_IDNA_VARIANT_UTS46; } return idn_to_ascii($domain, $flags, $variant, $idna_info); } return idn_to_ascii($domain, $flags); } /** * Version comparison function capable of properly comparing versions with * trailing ".0" groups such as '6.1' which is equal to '6.1.0' which is * equal to '6.1.000.0' etc. * * @since 1.14.2 * * @param string $ver1 * @param string $ver2 * @param string|null $operator * * @return bool|int */ public static function betterVersionCompare( $ver1, $ver2, $operator = null ) { $pattern = '/(\.0+)+($|-)/'; return version_compare( preg_replace($pattern, '', $ver1), preg_replace($pattern, '', $ver2), $operator ); } /** * * @since 1.15.0.1 * * @param string $constantName * @param array|bool|float|int|null|string $value * @param bool $caseInsensitive Optional * parameter used for define calls in PHP versions below 7.3. * * @return bool * * @noinspection PhpDeprecationInspection Ignore deprecation of define() * parameter $case_insensitive for PHP versions below 7.3. * @noinspection RedundantSuppression */ public static function define_wrapper( $constantName, $value, $caseInsensitive = false ) { if ( PHP_VERSION_ID < 70300 ) { return define($constantName, $value, $caseInsensitive); } else { return define($constantName, $value); } } /** * * @since 1.17.1.1 * * @param int $wpStatus * * @return string[] [ stateMsg => string, link => string ] */ public static function getFatalErrorStateMessageAndLink( $wpStatus ) { $stateMsg = $anchor = ''; if ( $wpStatus & WPInstall::ST_ERR_EXECMD ) { $stateMsg = 'WordPress fatal error encountered during action ' . 'execution. This is most likely caused by custom code in ' . 'this WordPress installation.'; $anchor = '#fatal-error-encountered-during-action-execution'; } if ( $wpStatus & WPInstall::ST_ERR_EXECMD_DB ) { $stateMsg = 'Error establishing WordPress database connection.'; } elseif ( $wpStatus & WPInstall::ST_ERR_TIMEOUT ) { $stateMsg = 'Timeout occurred during action execution.'; $anchor = '#timeout-occurred-during-action-execution'; } elseif ( $wpStatus & WPInstall::ST_ERR_SITEURL ) { $stateMsg = 'Could not retrieve WordPress siteURL.'; $anchor = '#could-not-retrieve-wordpress-siteurl'; } elseif ( $wpStatus & WPInstall::ST_ERR_DOCROOT ) { $stateMsg = 'Could not match WordPress siteURL to a known ' . 'control panel docroot.'; $anchor = '#could-not-match-wordpress-siteurl-to-a-known-' . 'cpanel-docroot'; } elseif ( $wpStatus & WPInstall::ST_ERR_WPCONFIG ) { $stateMsg = 'Could not find a valid wp-config.php file.'; $anchor = '#could-not-find-a-valid-wp-configphp-file'; } $stateMsg .= ' Click for more information.'; return array( 'stateMsg' => $stateMsg, 'link' => 'https://docs.litespeedtech.com/lsws/cp/cpanel/' . "whm-litespeed-plugin/troubleshooting/$anchor" ); } /** * Locate a usable CA-certificate bundle in a panel-agnostic way. * * Probes well-known locations on the major Linux distributions and * supported control panels in priority order (OS-level bundles are * preferred over panel-managed ones). Returns the first readable path, * or '' when nothing is found (callers should then rely on the tool's * built-in default trust store). * * @return string Absolute path to a CA bundle, or '' if none found. */ public static function getSystemCaBundle() { static $resolved = null; if ( $resolved !== null ) { return $resolved; } $candidates = array( // OS-level bundles — preferred; kept current by the distro. '/etc/ssl/certs/ca-certificates.crt', // Debian/Ubuntu/Alpine '/etc/pki/tls/certs/ca-bundle.crt', // RHEL/CentOS/AlmaLinux/Rocky '/etc/ssl/cert.pem', // FreeBSD/OpenBSD/macOS '/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem',// RHEL update-ca-trust '/etc/ssl/ca-bundle.pem', // SUSE/openSUSE // Panel-managed bundles — fallback when OS bundle is absent. '/usr/local/cpanel/3rdparty/share/ca-bundle/curl-ca-bundle.crt', '/opt/psa/var/certificates/ca-bundle.crt', // Plesk '/usr/local/directadmin/conf/carootcert.pem', // DirectAdmin ); foreach ( $candidates as $path ) { if ( is_file($path) && is_readable($path) ) { return $resolved = $path; } } return $resolved = ''; } /** * Build the wget '--ca-certificate=...' argument string. * * Returns the shell-quoted flag with a trailing space when a bundle is * found, or '' when nothing was found (callers should omit the flag and * rely on the system default trust store — never pass * --no-check-certificate). * * @return string */ public static function getWgetCaArg() { $bundle = self::getSystemCaBundle(); return $bundle === '' ? '' : '--ca-certificate=' . escapeshellarg($bundle) . ' '; } /** * Build the curl '--cacert ...' argument string. * * Returns the shell-quoted flag with a trailing space when a bundle is * found, or '' when nothing was found (callers should omit the flag and * rely on the system default trust store — never pass --insecure). * * @return string */ public static function getCurlCaArg() { $bundle = self::getSystemCaBundle(); return $bundle === '' ? '' : '--cacert ' . escapeshellarg($bundle) . ' '; } } PK!++ webcachemgr/src/AjaxResponse.phpnuIwheaderContent) ) { $output .= "{$m->headerContent}\n\n"; } $output .= $m->ajaxContent; ob_clean(); echo $output; exit; } /** * * @since 1.9 * * @param string $ajaxContent */ public static function setAjaxContent( $ajaxContent ) { self::me()->ajaxContent = $ajaxContent; } /** * * @since 1.9 * * @param string $headerContent */ public static function setHeaderContent( $headerContent ) { self::me()->headerContent = $headerContent; } } PK!<GGwebcachemgr/src/Logger.phpnuIwlogFileLvl and $this->logEchoLvl. */ protected $logLvl; /** * @var string File that log messages will be written to (if writable). */ protected $logFile; /** * @var int Highest log message level allowed to be written to the log * file. */ protected $logFileLvl; /** * @var string Additional tag to be added at the start of any log messages. */ protected $addTagInfo = ''; /** * @var bool When set to true, log messages will not be written to the log * file until this logger object is destroyed. */ protected $bufferedWrite; /** * @var LogEntry[]|object[] Stores created objects that implement all * LogEntry class public functions. */ protected $msgQueue = array(); /** * @var int Highest log message level allowed to echo. */ protected $logEchoLvl; /** * @var bool When set to true, echoing of log messages is suppressed. */ protected $bufferedEcho; /** * @var string[][] Leveraged by control panel GUI to store and retrieve * display messages. Also used as temporary storage for display only * messages by UserCommand. */ protected $uiMsgs = array( self::UI_INFO => array(), self::UI_SUCC => array(), self::UI_ERR => array(), self::UI_WARN => array() ); /** * * @param ContextOption $ctxOption */ final protected function __construct( ContextOption $ctxOption ) { $this->logFile = $ctxOption->getDefaultLogFile(); $this->logFileLvl = $ctxOption->getLogFileLvl(); $this->bufferedWrite = $ctxOption->isBufferedWrite(); $this->logEchoLvl = $ctxOption->getLogEchoLvl(); $this->bufferedEcho = $ctxOption->isBufferedEcho(); $this->logLvl = max($this->logEchoLvl, $this->logFileLvl); } /** * * @throws LSCMException Thrown indirectly by $this->writeToFile() call. */ public function __destruct() { if ( $this->bufferedWrite ) { $this->writeToFile($this->msgQueue); } } /** * * @param ContextOption $contextOption * * @throws LSCMException Thrown when a static Logger instance has already * been initialized. */ public static function Initialize( ContextOption $contextOption ) { if ( static::$instance != null ) { throw new LSCMException( 'Logger cannot be initialized twice.', LSCMException::E_PROGRAM ); } static::$instance = new static($contextOption); } /** * Set static::$instance to a pre-created logger object. * * This function is intended as an alternative to Initialize() and will * throw an exception if static::$instance is already set. * * @since 1.9.1 * * @param object $loggerObj * * @throws LSCMException Thrown when Logger instance is already set. */ public static function setInstance( $loggerObj ) { if ( static::$instance != null ) { throw new LSCMException( 'Logger instance already set.', LSCMException::E_PROGRAM ); } static::$instance = $loggerObj; } /** * * @since 1.9 * * @param string $logFile * * @throws LSCMException Thrown indirectly by static::me() call. */ public static function changeLogFileUsed( $logFile ) { static::me()->p_setLogFile($logFile); } /** * * @since 1.9 * * @param string $addInfo * * @throws LSCMException Thrown indirectly by static::me() call. */ public static function setAdditionalTagInfo( $addInfo ) { static::me()->p_setAddTagInfo($addInfo); } /** * * @since 1.9.1 * * @param string $msg * @param int $type */ public function p_addUiMsg( $msg, $type ) { switch ($type) { case static::UI_INFO: case static::UI_SUCC: case static::UI_ERR: case static::UI_WARN: $this->uiMsgs[$type][] = $msg; break; //no default } } /** * * @since 1.9.1 * * @param LogEntry[]|object[] $entries Array of objects that implement all * LogEntry class public functions. * * @throws LSCMException Thrown indirectly by $this->echoEntries() call. */ public function p_echoEntries( array $entries ) { $this->echoEntries($entries); } /** * * @since 1.9.1 * * @return string */ public function p_getAddTagInfo() { return $this->addTagInfo; } /** * * @since 1.9.1 * * @return bool */ public function p_getBufferedEcho() { return $this->bufferedEcho; } /** * * @since 1.9.1 * * @return bool */ public function p_getBufferedWrite() { return $this->bufferedWrite; } /** * * @since 1.9.1 * * @return string */ public function p_getLogFile() { return $this->logFile; } /** * * @since 1.9.1 * * @return LogEntry[]|object[] */ public function p_getMsgQueue() { return $this->msgQueue; } /** * * @since 1.9.1 * * @param int $type * * @return string[] */ public function p_getUiMsgs( $type ) { switch ($type) { case static::UI_INFO: case static::UI_SUCC: case static::UI_ERR: case static::UI_WARN: return $this->uiMsgs[$type]; default: return array(); } } /** * * @since 1.9.1 * * @param string $msg * @param int $lvl * * @throws LSCMException Thrown indirectly by $this->log() call. */ public function p_log( $msg, $lvl ) { $this->log($msg, $lvl); } /** * * @since 1.9.1 * * @param string $addInfo */ public function p_setAddTagInfo( $addInfo ) { $this->addTagInfo = $addInfo; } /** * * @since 1.9.1 * * @param string $logFile */ public function p_setLogFile( $logFile ) { $this->logFile = $logFile; } /** * * @since 1.9.1 * * @param int $logFileLvl */ public function p_setLogFileLvl( $logFileLvl ) { $this->logFileLvl = $logFileLvl; } /** * * @since 1.9.1 * * @param LogEntry[]|object[] $msgQueue */ public function p_setMsgQueue( array $msgQueue ) { $this->msgQueue = $msgQueue; } /** * * @since 1.9.1 * * @param LogEntry[]|object[] $entries Array of objects that implement all * LogEntry class public functions. * * @throws LSCMException Thrown indirectly by $this->writeToFile() call. */ public function p_writeToFile( array $entries ) { $this->writeToFile($entries); } /** * * @since 1.9 * * @return string * * @throws LSCMException Thrown indirectly by static::me() call. */ public static function getAdditionalTagInfo() { return static::me()->p_getAddTagInfo(); } /** * * @since 1.9 * * @return string * * @throws LSCMException Thrown indirectly by static::me() call. */ public static function getLogFilePath() { return static::me()->p_getLogFile(); } /** * * @since 1.9 * * @return LogEntry[]|object[] Array of objects that implement all LogEntry * class public functions. * * @throws LSCMException Thrown indirectly by static::me() call. */ public static function getLogMsgQueue() { return static::me()->p_getMsgQueue(); } /** * * @param int $type * * @return string[] * * @throws LSCMException Thrown indirectly by static::me() call. */ public static function getUiMsgs( $type ) { return static::me()->p_getUiMsgs($type); } /** * Processes any buffered output, writing it to the log file, echoing it * out, or both. * * @throws LSCMException Thrown indirectly by static::me() call. * @throws LSCMException Thrown indirectly by $m->p_writeToFile() call. * @throws LSCMException Thrown indirectly by $m->p_echoEntries() call. */ public static function processBuffer() { $clear = false; $m = static::me(); if ( $m->p_getBufferedWrite() ) { $m->p_writeToFile($m->p_getMsgQueue()); $clear = true; } if ( $m->p_getBufferedEcho() ) { $m->p_echoEntries($m->p_getMsgQueue()); $clear = true; } if ( $clear ) { $m->p_setMsgQueue(array()); } } /** * Deprecated 06/25/19. Visibility going to be changed to "protected". * * @deprecated * * @param string $msg * @param int $type * * @throws LSCMException Thrown indirectly by static::me() call. */ public static function addUiMsg( $msg, $type ) { static::me()->p_addUiMsg($msg, $type); } /** * Calls addUiMsg() with message level static::UI_INFO. * * @param string $msg * * @throws LSCMException Thrown indirectly by static::addUiMsg() call. */ public static function uiInfo( $msg ) { static::addUiMsg($msg, static::UI_INFO); } /** * Calls addUiMsg() with message level static::UI_SUCC. * * @param string $msg * * @throws LSCMException Thrown indirectly by static::addUiMsg() call. */ public static function uiSuccess( $msg ) { static::addUiMsg($msg, static::UI_SUCC); } /** * Calls addUiMsg() with message level static::UI_ERR. * * @param string $msg * * @throws LSCMException Thrown indirectly by static::addUiMsg() call. */ public static function uiError( $msg ) { static::addUiMsg($msg, static::UI_ERR); } /** * Calls addUiMsg() with message level static::UI_WARN. * * @param string $msg * * @throws LSCMException Thrown indirectly by static::addUiMsg() call. */ public static function uiWarning( $msg ) { static::addUiMsg($msg, static::UI_WARN); } /** * * @param string $msg * @param int $lvl * * @throws LSCMException Thrown indirectly by static::me() call. * @throws LSCMException Thrown indirectly by static::me()->p_log() call. */ public static function logMsg( $msg, $lvl ) { static::me()->p_log($msg, $lvl); } /** * Calls logMsg() with message level static::L_ERROR. * * @param string $msg * * @throws LSCMException Thrown indirectly by static::logMsg() call. */ public static function error( $msg ) { static::logMsg($msg, static::L_ERROR); } /** * Calls logMsg() with message level static::L_WARN. * * @param string $msg * * @throws LSCMException Thrown indirectly by static::logMsg() call. */ public static function warn( $msg ) { static::logMsg($msg, static::L_WARN); } /** * Calls logMsg() with message level static::L_NOTICE. * * @param string $msg * * @throws LSCMException Thrown indirectly by static::logMsg() call. */ public static function notice( $msg ) { static::logMsg($msg, static::L_NOTICE); } /** * Calls logMsg() with message level static::L_INFO. * * @param string $msg * * @throws LSCMException Thrown indirectly by static::logMsg() call. */ public static function info( $msg ) { static::logMsg($msg, static::L_INFO); } /** * Calls logMsg() with message level static::L_VERBOSE. * * @param string $msg * * @throws LSCMException Thrown indirectly by static::logMsg() call. */ public static function verbose( $msg ) { static::logMsg($msg, static::L_VERBOSE); } /** * Calls logMsg() with message level static::L_DEBUG. * * @param string $msg * * @throws LSCMException Thrown indirectly by static::logMsg() call. */ public static function debug( $msg ) { static::logMsg($msg, static::L_DEBUG); } /** * * @return Logger|object Object that implements all Logger class public * functions. * * @throws LSCMException Thrown when Logger instance has not yet been * initialized. */ protected static function me() { if ( static::$instance == null ) { throw new LSCMException( 'Logger Uninitialized.', LSCMException::E_PROGRAM ); } return static::$instance; } /** * * @param string $msg * @param int $lvl * * @throws LSCMException Thrown indirectly by $this->writeToFile() call. * @throws LSCMException Thrown indirectly by $this->echoEntries() call. */ protected function log( $msg, $lvl ) { $entry = new LogEntry($msg, $lvl); $this->msgQueue[] = $entry; if ( !$this->bufferedWrite ) { $this->writeToFile(array( $entry )); } if ( !$this->bufferedEcho ) { $this->echoEntries(array( $entry )); } } /** * * @param LogEntry[]|object[] $entries Array of objects that implements all * LogEntry class public functions. * * @throws LSCMException Thrown indirectly by $e->getOutput() call. */ protected function writeToFile( array $entries ) { $content = ''; foreach ( $entries as $e ) { $content .= $e->getOutput($this->logFileLvl); } if ( $content != '' ) { if ( $this->logFile ) { file_put_contents( $this->logFile, $content, FILE_APPEND | LOCK_EX ); } else { error_log($content); } } } /** * * @param LogEntry[]|object[] $entries Array of objects that implement all * LogEntry class public functions. * * @throws LSCMException Thrown indirectly by $entry->getOutput() call. */ protected function echoEntries( array $entries ) { foreach ( $entries as $entry ) { if ( ($msg = $entry->getOutput($this->logEchoLvl)) !== '' ) { echo $msg; } } } /** * * @param int $lvl * * @return string */ public static function getLvlDescr( $lvl ) { switch ($lvl) { case static::L_ERROR: return 'ERROR'; case static::L_WARN: return 'WARN'; case static::L_NOTICE: return 'NOTICE'; case static::L_INFO: return 'INFO'; case static::L_VERBOSE: return 'DETAIL'; case static::L_DEBUG: return 'DEBUG'; default: /** * Do silently. */ return ''; } } /** * Not used yet. Added for later cases where shared log level should be * changed to match panel log level. * * @deprecated 1.9.1 Deprecated on 11/22/19. Function is likely not needed * after recent logger changes. * * @param int $lvl * * @return bool * * @throws LSCMException Thrown indirectly by static::me() call. */ public static function setLogFileLvl( $lvl ) { $lvl = (int)$lvl; if ( static::isValidLogFileLvl($lvl) ) { if ( $lvl > static::L_DEBUG ) { $lvl = static::L_DEBUG; } static::me()->p_setLogFileLvl($lvl); return true; } return false; } /** * * @param int $lvl * * @return bool */ protected static function isValidLogFileLvl( $lvl ) { if ( is_int($lvl) && $lvl >= 0 ) { return true; } return false; } /** * Prevent cloning here and in extending classes. */ final protected function __clone() {} } PK!)webcachemgr/src/WpWrapper/WpConstants.phpnuIwget_var($query, $x, $y); } /** * https://developer.wordpress.org/reference/functions/is_plugin_active/ * * @since 1.17 * * @param string $plugin * * @return bool */ public static function isPluginActive( $plugin ) { /** @noinspection PhpUndefinedFunctionInspection */ return is_plugin_active($plugin); } /** * https://developer.wordpress.org/reference/functions/is_plugin_active_for_network/ * * @since 1.17 * * @param string $plugin * * @return bool */ public static function isPluginActiveForNetwork( $plugin ) { /** @noinspection PhpUndefinedFunctionInspection */ return is_plugin_active_for_network($plugin); } /** * https://developer.wordpress.org/reference/functions/wp_filesystem/ * * @since 1.17 * * @param array|false $args * @param string|false $context * @param bool $allow_relaxed_file_ownership * * @return bool|null */ public static function WpFilesystem( $args = false, $context = false, $allow_relaxed_file_ownership = false ) { /** @noinspection PhpUndefinedFunctionInspection */ return WP_Filesystem($args, $context, $allow_relaxed_file_ownership); } /** * https://developer.wordpress.org/reference/functions/unzip_file/ * * @since 1.17 * * @param string $file * @param string $to * * @return true|WP_Error * * @noinspection PhpUndefinedClassInspection * */ public static function unzipFile( $file, $to ) { /** @noinspection PhpUndefinedFunctionInspection */ return unzip_file($file, $to); } /** * https://developer.wordpress.org/reference/functions/deactivate_plugins/ * * @since 1.17 * * @param string|string[] $plugins * @param bool $silent * @param bool|null $network_wide */ public static function deactivatePlugins( $plugins, $silent = false, $network_wide = null ) { /** @noinspection PhpUndefinedFunctionInspection */ deactivate_plugins($plugins, $silent, $network_wide); } /** * https://developer.wordpress.org/reference/functions/delete_plugins/ * * @since 1.17 * * @param string[] $plugins * * @return bool|null|WP_Error * * @noinspection PhpUndefinedClassInspection */ public static function deletePlugins( array $plugins ) { /** @noinspection PhpUndefinedFunctionInspection */ return delete_plugins($plugins); } /** * https://developer.wordpress.org/reference/functions/activate_plugin/ * * @since 1.17 * * @param string $plugin * @param string $redirect * @param bool $network_wide * @param bool $silent * * @return null|WP_Error * * @noinspection PhpUndefinedClassInspection */ public static function activatePlugin( $plugin, $redirect = '', $network_wide = false, $silent = false ) { /** @noinspection PhpUndefinedFunctionInspection */ return activate_plugin($plugin, $redirect, $network_wide, $silent); } /** * https://developer.wordpress.org/reference/functions/add_filter/ * * @since 1.17 * * @param string $hook_name * @param callable $callback * @param int $priority * @param int $accepted_args * * @return true */ public static function addFilter( $hook_name, callable $callback, $priority = 10, $accepted_args = 1 ) { /** @noinspection PhpUndefinedFunctionInspection */ return add_filter($hook_name, $callback, $priority, $accepted_args); } /** * https://developer.wordpress.org/reference/functions/remove_filter/ * * @since 1.17 * * @param string $hook_name * @param callable|string|array $callback * @param int $priority * * @return bool */ public static function removeFilter( $hook_name, $callback, $priority = 10 ) { /** @noinspection PhpUndefinedFunctionInspection */ return remove_filter($hook_name, $callback, $priority); } /** * https://developer.wordpress.org/reference/functions/is_wp_error/ * * @since 1.17 * * @param mixed $thing * * @return bool */ public static function isWpError( $thing ) { /** @noinspection PhpUndefinedFunctionInspection */ return is_wp_error($thing); } /** * https://developer.wordpress.org/reference/functions/wp_clean_plugins_cache/ * * @since 1.17 * * @param bool $clear_update_cache */ public static function wpCleanPluginsCache( $clear_update_cache = true ) { /** @noinspection PhpUndefinedFunctionInspection */ wp_clean_plugins_cache($clear_update_cache); } /** * https://developer.wordpress.org/reference/functions/get_plugin_data/ * * @since 1.17 * * @param string $plugin_file * @param bool $markup * @param bool $translate * * @return array */ public static function getPluginData( $plugin_file, $markup = true, $translate = true ) { /** @noinspection PhpUndefinedFunctionInspection */ return get_plugin_data($plugin_file, $markup, $translate); } /** * https://developer.wordpress.org/reference/functions/get_locale/ * * @since 1.17 * * @return string */ public static function getLocale() { /** @noinspection PhpUndefinedFunctionInspection */ return get_locale(); } /** * https://developer.wordpress.org/reference/functions/apply_filters/ * * @since 1.17 * * @param string $hook_name * @param mixed $value * @param mixed $args * * @return mixed */ public static function applyFilters( $hook_name, $value, $args ) { /** @noinspection PhpUndefinedFunctionInspection */ return apply_filters($hook_name, $value, $args); } /** * https://developer.wordpress.org/reference/functions/wp_plugin_directory_constants/ * * @since 1.17 */ public static function wpPluginDirectoryConstants() { /** @noinspection PhpUndefinedFunctionInspection */ wp_plugin_directory_constants(); } /** * https://developer.wordpress.org/reference/functions/wp_cookie_constants/ * * @since 1.17 */ public static function wpCookieConstants() { /** @noinspection PhpUndefinedFunctionInspection */ wp_cookie_constants(); } }PK!Œ02webcachemgr/src/WpWrapper/WpTextdomainRegistry.phpnuIwwpTextdomainRegistry = new \WP_Textdomain_Registry(); } /** * * @since 1.17 * * @return \WP_Textdomain_Registry * * @noinspection PhpUndefinedClassInspection */ public function getWpWpTextdomainRegistryObject() { return $this->wpTextdomainRegistry; } }PK!M ,webcachemgr/src/WpWrapper/PluginUpgrader.phpnuIwpluginUpgrader = new \Plugin_Upgrader($skin); } /** * * @since 1.17 * * @return \Plugin_Upgrader * * @noinspection PhpUndefinedClassInspection */ public function getWpPluginUpgraderObject() { return $this->pluginUpgrader; } /** * * @since 1.17 * * @return array|WP_Error * * @noinspection PhpUndefinedClassInspection */ public function getResult() { return $this->pluginUpgrader->result; } /** * https://developer.wordpress.org/reference/classes/wp_upgrader/init/ * * @since 1.17 */ public function init() { $this->pluginUpgrader->init(); } /** * https://developer.wordpress.org/reference/classes/plugin_upgrader/upgrade_strings/ * * @since 1.17 */ public function upgradeStrings() { $this->pluginUpgrader->upgrade_strings(); } /** * https://developer.wordpress.org/reference/classes/wp_upgrader/run/ * * @since 1.17 * * @param array $options * * @return array|false|WP_Error * * @noinspection PhpUndefinedClassInspection */ public function run( array $options ) { return $this->pluginUpgrader->run($options); } }PK!srr"webcachemgr/src/WpWrapper/Wpdb.phpnuIwblogs; } /** * https://developer.wordpress.org/reference/classes/wpdb/get_col/ * * @since 1.17 * * @global \wpdb $wpdb * * @param string|null $query * @param int $x * * @return array * * @noinspection PhpUndefinedClassInspection */ public static function getCol( $query = null, $x = 0 ) { global $wpdb; return $wpdb->get_col($query, $x); } }PK!##%webcachemgr/src/WpWrapper/WpQuery.phpnuIwwpQuery = new \WP_Query($query); } /** * * @since 1.17 * * @return \WP_Query * * @noinspection PhpUndefinedClassInspection */ public function getWpWpQueryObject() { return $this->wpQuery; } }PK!7webcachemgr/src/WPDashMsgs.phpnuIwdataFile = realpath(__DIR__ . '/../../..') . '/admin/lscdata/wpDashMsgs.data'; $this->init(); } protected function init() { if ( file_exists($this->dataFile) ) { $data = json_decode(file_get_contents($this->dataFile), true); if ( $data && is_array($data) ) { $this->msgData = $data; } } if ( !isset($this->msgData[self::KEY_RAP_MSGS]) ) { $this->msgData[self::KEY_RAP_MSGS] = array(); } if ( !isset($this->msgData[self::KEY_BAM_MSGS]) ) { $this->msgData[self::KEY_BAM_MSGS] = array(); } /** * Set default rap message and plugin slug. */ $this->msgData[self::KEY_RAP_MSGS] = array_merge( array( 'default' => array( 'msg' => 'Greetings! This is your hosting company ' . 'encouraging you to click the button to install the ' . 'LiteSpeed Cache plugin. This plugin will speed up ' . 'your WordPress site dramatically. Please contact us ' . 'with any questions.', 'slug' => 'litespeed-cache' ) ), $this->msgData[self::KEY_RAP_MSGS] ); } /** * * @param string $type * * @return string[]|string[][] */ public function getMsgData( $type = '' ) { switch ($type) { case self::MSG_TYPE_RAP: return $this->msgData[self::KEY_RAP_MSGS]; case self::MSG_TYPE_BAM: return $this->msgData[self::KEY_BAM_MSGS]; default: return $this->msgData; } } /** * * @param string $type * @param string $msgId * @param string $msg * @param string $slug * * @return bool */ public function addMsg( $type, $msgId, $msg, $slug = '' ) { if ( $msgId === '' || $msgId === NULL || ($msgId == 'default' && $type == self::MSG_TYPE_RAP) || strlen($msgId) > 50 || preg_match('/[^a-zA-Z0-9_-]/', $msgId) ) { return false; } switch ($type) { case self::MSG_TYPE_RAP: $this->msgData[self::KEY_RAP_MSGS][$msgId] = array( 'msg' => $msg, 'slug' => $slug ); break; case self::MSG_TYPE_BAM: $this->msgData[self::KEY_BAM_MSGS][$msgId] = array( 'msg' => $msg ); break; default: return false; } $this->saveDataFile(); return true; } /** * * @param string $type * @param string $msgId * * @return bool */ public function deleteMsg( $type, $msgId ) { if ( $msgId === '' || $msgId === NULL ) { return false; } switch ($type) { case self::MSG_TYPE_RAP: if ( $msgId == 'default' ) { return false; } $key = self::KEY_RAP_MSGS; break; case self::MSG_TYPE_BAM: $key = self::KEY_BAM_MSGS; break; default: return false; } if ( isset($this->msgData[$key][$msgId]) ) { unset($this->msgData[$key][$msgId]); $this->saveDataFile(); return true; } return false; } protected function saveDataFile() { file_put_contents($this->dataFile, json_encode($this->msgData)); } } PK!xm!webcachemgr/src/LSCMException.phpnuIwrunAsUser() return status. */ const E_NON_FATAL = 103; } PK!ɠ+++webcachemgr/src/ThirdParty/Polyfill/LICENSEnuIwCopyright (c) 2015-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.PK!s,webcachemgr/src/ThirdParty/Polyfill/Utf8.phpnuIw * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Lsc\Wp\ThirdParty\Polyfill; /** * @since 1.16.1 */ class Utf8 { /** * * @since 1.16.1 * * @param $s * * @return false|string */ public static function encode($s) { $s .= $s; $len = strlen($s); for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) { if ( $s[$i] < "\x80" ) { $s[$j] = $s[$i]; } elseif ( $s[$i] < "\xC0" ) { $s[$j] = "\xC2"; $s[++$j] = $s[$i]; } else { $s[$j] = "\xC3"; $s[++$j] = chr(ord($s[$i]) - 64); } } return substr($s, 0, $j); } /** * * @since 1.16.1 * * @param $s * * @return false|string */ public static function decode($s) { $s = (string) $s; $len = strlen($s); for ($i = 0, $j = 0; $i < $len; ++$i, ++$j) { switch ($s[$i] & "\xF0") { case "\xC0": case "\xD0": $c = (ord($s[$i] & "\x1F") << 6) | ord($s[++$i] & "\x3F"); $s[$j] = $c < 256 ? chr($c) : '?'; break; case "\xF0": ++$i; // fallthrough case "\xE0": $s[$j] = '?'; $i += 2; break; default: $s[$j] = $s[$i]; } } return substr($s, 0, $j); } }PK!.lwebcachemgr/src/WPCaller.phpnuIwinit() call. */ private function __construct( WPInstall $curInstall, $loadLscwp ) { $this->currInstall = $curInstall; $this->loadLscwp = $loadLscwp; $this->init(); } /** * * @since 1.13.4.4 * * @throws LSCMException Thrown indirectly by $this->initWp() call. */ private function init() { $this->advancedCacheFile = "{$this->currInstall->getPath()}/wp-content/advanced-cache.php"; $this->initWp(); } /** * * @param WPInstall $currInstall * @param bool $loadLscwp * * @return WPCaller * * @throws LSCMException Thrown indirectly by "new self()" call. */ public static function getInstance( WPInstall $currInstall, $loadLscwp = true ) { if ( self::$instance == null || self::$instance->currInstall !== $currInstall ) { self::$instance = new self($currInstall, $loadLscwp); } return self::$instance; } /** * * @param int $errno Not used at this time. * @param string $errstr * * @return bool * * @noinspection PhpUnusedParameterInspection */ public static function warning_handler( $errno, $errstr ) { if ( in_array( $errstr, [ 'ini_set() has been disabled for security reasons', 'Constant FS_METHOD already defined' ] ) ) { /** * Throw this warning out. */ return true; } return false; } /** * Deprecated 03/12/19 as this function is no longer used. * * Prevents database table options not in the $allowedOptions list * from having their value updated by others during execution. * * Run when WP function apply_filters('pre_update_option', ...) is called * in WP function update_option(). * * @deprecated * * @param mixed $value New option value. * @param string $option Option name in db. * @param mixed $old_value Old option value. * * @return mixed */ public static function lock_database( $value, $option, $old_value ) { if ( in_array( $option, [ 'litespeed-cache-conf', '_transient_lscwp_whm_install', 'active_plugins', '_transient_doing_cron', '_site_transient_update_plugins', 'uninstall_plugins' ] ) ) { return $value; } return $old_value; } /** * Redefine disabled PHP global/core functions that no longer exist * (PHP 8+). * * @since 1.13.10 */ private static function redefineDisabledFunctions() { if ( Util::betterVersionCompare(phpversion(), '8.0', '>=') ) { include_once(__DIR__ . '/RedefineGlobalFuncs.php'); } } /** * * @return string[] */ public function getOutputResult() { return $this->outputResult; } /** * Adds key value pair to $this->outputResult to be grabbed later in * the $output variable of the UserCommand::issue() exec call. * * @param string $key * @param mixed $value */ private function outputResult( $key, $value ) { $this->outputResult[$key] = $value; } /** * * @deprecated 1.9 Use Logger::getLogMsgQueue() to get these messages as * LogEntry objects. * * @return string[] * * @throws LSCMException Thrown indirectly by Logger::getLogMsgQueue() * call. */ public function getDebugMsgs() { $debugMsgs = []; foreach ( Logger::getLogMsgQueue() as $logEntry ) { $label = Logger::getLvlDescr($logEntry->getLvl()); $debugMsgs[] = "[$label] {$logEntry->getMsg()}"; } return $debugMsgs; } /** * @deprecated 1.9 Deprecated 07/30/19. Use * Logger::getUiMsgs(Logger::UI_ERR) to get these messages. * * @return string[] * * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. */ public function getErrMsgs() { return Logger::getUiMsgs(Logger::UI_ERR); } /** * * @deprecated 1.9 Deprecated 07/30/19. Use * Logger::getUiMsgs(Logger::UI_SUCC) to get these messages. * * @return string[] * * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. */ public function getSuccMsgs() { return Logger::getUiMsgs(Logger::UI_SUCC); } /** * * WP Variables $table_prefix * * @global string $table_prefix * * @return string */ private function getSiteURL() { global $table_prefix; $siteURL = WpFuncs::getOption('siteurl'); if ( !$siteURL ) { return ''; } if ( strpos($siteURL, self::LSCWP_HTTP_HOST_TEST) !== false ) { /** * User is setting WP_SITEURL using fake $_SERVER['HTTP_HOST']. * Get siteurl value from DB directly. */ return WpFuncs::getVar( "SELECT option_value FROM {$table_prefix}options " . "WHERE option_name = 'siteurl'" ); } return $siteURL; } /** * * @since 1.17.0.3 * * @param string $advCacheFileContents * * @return bool */ private static function advancedCacheFileBelongsToLscwp( $advCacheFileContents ) { return ( self::advancedCacheFileHasLscacheDefine($advCacheFileContents) || self::advancedCacheFileHasPlaceholderMsg($advCacheFileContents) ); } /** * * @since 1.13.4.3 * * @return bool */ private function generic3rdPartyAdvCachePluginExists() { if ( Util::betterVersionCompare( $this->installedLscwpVer, '3.0.4', '>=' ) ) { if ( file_exists($this->advancedCacheFile) ) { $advCacheFileContents = file_get_contents($this->advancedCacheFile); if ( $advCacheFileContents !== '' ) { /** * Old LSCWP advanced-cache.php file is no longer used in * these versions but is also never cleaned up. As a result, * any existing advanced-cache.php files need to have their * contents checked to avoid detecting an old LSCWP * advanced-cache.php file as a generic 3rd-party * advanced-cache plugin. */ return !self::advancedCacheFileBelongsToLscwp( $advCacheFileContents ); } } } elseif ( !defined('LSCACHE_ADV_CACHE') || WpConstants::getWpConstant('LSCACHE_ADV_CACHE') !== true ) { return true; } return false; } /** * * @since 1.13.8 Added optional parameter $output. * * @param WPInstall $install * @param bool $output * * @return int * * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by $install->addUserFlagFile() * call. * @throws LSCMException Thrown indirectly by $install->addUserFlagFile() * call. * @throws LSCMException Thrown indirectly by Logger::notice() call. * @throws LSCMException Thrown indirectly by Logger::notice() call. */ private function checkStatus( WPInstall $install, $output = false ) { if ( $output ) { if ( ($siteUrl = $this->getSiteURL()) === '' ) { Logger::uiError( 'Could not retrieve siteURL to match against known ' . 'docroots.' ); $install->addUserFlagFile(); return (WPInstall::ST_ERR_SITEURL | WPInstall::ST_FLAGGED); } $this->outputResult('SITEURL', $siteUrl); } $status = 0; /** * Check if plugin files exist first, as status in db could be stale if * LSCWP was removed manually. */ if ( file_exists($this->pluginEntry) && WpFuncs::isPluginActive(self::LSCWP_PLUGIN) ) { $status |= WPInstall::ST_PLUGIN_ACTIVE; //TODO: Get rid of ST_LSC_ADVCACHE_DEFINED status or replace with // new "is caching enabled" define check. if ( $this->generic3rdPartyAdvCachePluginExists() ) { $status |= WPInstall::ST_FLAGGED; } else { $status |= WPInstall::ST_LSC_ADVCACHE_DEFINED; } } else { $status |= WPInstall::ST_PLUGIN_INACTIVE; } if ( $install->hasFlagFile() ) { $status |= WPInstall::ST_FLAGGED; } if ( $status & WPInstall::ST_FLAGGED ) { Logger::notice( 'Install is ' . (($install->addUserFlagFile()) ? '' : 'not ') . 'flagged' ); } return $status; } /** * * @param bool $output * * @return int * * @throws LSCMException Thrown indirectly by $this->checkStatus() call. */ public function updateStatus( $output = false ) { $status = $this->checkStatus($this->currInstall, $output); $this->currInstall->setStatus($status); if ( $output ) { $this->outputResult('STATUS', $status); } if ( $status & WPInstall::ST_ERR_SITEURL ) { return UserCommand::EXIT_FAIL; } return UserCommand::EXIT_SUCC; } /** * * @return int * * @throws LSCMException Thrown indirectly by $this->updateStatus() call. */ private function getCurrStatus() { $this->updateStatus(); return $this->currInstall->getStatus(); } /** * Check if any known cache plugins that do not use an advanced-cache.php * file are active for this WordPress installation. If any of these plugins * are found, that plugin's slug is returned. * * @since 1.9.1 * * @return string Empty string or detected active cache plugin slug. */ private function checkForKnownNonAdvCachePlugins() { /** * Only one plugin at the moment. */ $slug = 'wp-fastest-cache'; $plugin = 'wp-fastest-cache/wpFastestCache.php'; /** * Check if plugin files exist first, as status in db could be * stale if plugin files were removed manually. */ if ( file_exists( WpConstants::getWpConstant('WP_PLUGIN_DIR') . "/$plugin" ) && WpFuncs::isPluginActive($plugin) ) { return $slug; } return ''; } /** * * @param bool $isMassAction * @param bool $isNewInstall * * @return bool * * @throws LSCMException Thrown indirectly by $this->getCurrStatus() call. * @throws LSCMException Thrown indirectly by * $this->currInstall->addUserFlagFile() call. * @throws LSCMException Thrown indirectly by Logger::uiSuccess() call. * @throws LSCMException Thrown indirectly by Logger::notice() call. * @throws LSCMException Thrown indirectly by * $this->currInstall->addUserFlagFile() call. * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by Logger::notice() call. * @throws LSCMException Thrown indirectly by Logger::uiSuccess() call. * @throws LSCMException Thrown indirectly by Logger::notice() call. * @throws LSCMException Thrown indirectly by * $this->currInstall->addUserFlagFile() call. * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by Logger::notice() call. */ private function canEnable( $isMassAction, $isNewInstall ) { $status = $this->getCurrStatus(); if ( $status & WPInstall::ST_PLUGIN_INACTIVE ) { if ( !$isNewInstall && $isMassAction ) { $this->currInstall->addUserFlagFile(); Logger::uiSuccess( 'LSCWP Detected As Manually Disabled - Flag Set' ); Logger::notice( 'Ignore - Previously disabled, flag it from mass operation' ); return false; } $thirdPartyCachePluginSlug = $this->checkForKnownNonAdvCachePlugins(); if ( $thirdPartyCachePluginSlug != '' ) { $this->currInstall->addUserFlagFile(); Logger::uiError( 'Cannot Enable LSCWP - Detected another active cache ' . "plugin \"$thirdPartyCachePluginSlug\". Flag set." ); Logger::notice( 'Ignore - Detected another active cache plugin ' . "\"$thirdPartyCachePluginSlug\". Flagged." ); return false; } } elseif ( !$isNewInstall ) { /** * already active */ if ( $status & WPInstall::ST_LSC_ADVCACHE_DEFINED ) { Logger::uiSuccess('LSCWP Already Enabled - No Action Taken'); Logger::notice('Ignore - Already enabled'); } else { $this->currInstall->addUserFlagFile(); Logger::uiError( 'LSCWP Already Enabled But Not Caching - Detected another ' . 'active cache plugin. Please visit the WordPress ' . 'Dashboard for further instructions.' ); Logger::notice( 'Ignore - Existing install but advanced cache not set' ); } return false; } return true; } /** * * @return int * * @throws LSCMException Thrown indirectly by $this->canEnable() call. * @throws LSCMException Thrown indirectly by $this->enable_lscwp() call. * @throws LSCMException Thrown indirectly by * $this->directEnableNewInstall() call. */ public function directEnable() { $isNewInstall = !file_exists($this->pluginEntry); if ( !$this->canEnable(false, $isNewInstall) ) { $this->outputResult('STATUS', $this->currInstall->getStatus()); return UserCommand::EXIT_FAIL; } $this->outputResult( 'STATUS', ( ($isNewInstall) ? $this->directEnableNewInstall() : $this->enable_lscwp() ) ); return UserCommand::EXIT_SUCC; } /** * * @return int * * @throws LSCMException Thrown when unable to extract downloaded LSCWP * files. * @throws LSCMException Thrown indirectly by $this->downloadLSCWPZip() * call. * @throws LSCMException Thrown indirectly by $this->enable_lscwp() call. * @throws LSCMException Thrown indirectly by * $this->removeLscwpPluginFiles() call. */ private function directEnableNewInstall() { $pluginDir = WpConstants::getWpConstant('WP_PLUGIN_DIR'); $lscwpZip = "$pluginDir/litespeed-cache.latest-stable.zip"; $this->downloadLSCWPZip($lscwpZip); WpFuncs::WpFilesystem(); $unzipRet = WpFuncs::unzipFile($lscwpZip, $pluginDir); unlink($lscwpZip); if ( $unzipRet !== true ) { throw new LSCMException( 'Unable to extract downloaded LSCWP files.', LSCMException::E_NON_FATAL ); } $this->currInstall->addNewLscwpFlagFile(); PluginVersion::tryCopyLscwpDefaultConf($pluginDir); $this->installedLscwpVer = $this->getPluginVersionFromFile(); $status = $this->enable_lscwp(); if ( $status & WPInstall::ST_PLUGIN_INACTIVE) { $this->removeLscwpPluginFiles(); } else { $this->updateTranslationFiles(); } return $status; } /** * * @param string $lscwpZip * * @return null * * @throws LSCMException Thrown when LSCWP download operation fails. */ private function downloadLscwpZip( $lscwpZip ) { $pluginDir = WpConstants::getWpConstant('WP_PLUGIN_DIR'); $url = 'https://downloads.wordpress.org/plugin/' . 'litespeed-cache.latest-stable.zip'; exec( "wget -q --tries=1 " . Util::getWgetCaArg() . escapeshellarg($url) . " -P " . escapeshellarg($pluginDir), $output1, $return_var1 ); if ( $return_var1 === 0 && file_exists($lscwpZip) ) { return; } /** * Fall back to curl in case wget is disabled for user. */ exec( "cd " . escapeshellarg($pluginDir) . " && curl -O -s --retry 1 " . Util::getCurlCaArg() . escapeshellarg($url), $output2, $return_var2 ); if ( $return_var2 === 0 && file_exists($lscwpZip) ) { return; } throw new LSCMException( "Failed to download LSCWP with wget exit status $return_var1 and " . "curl exit status $return_var2.", LSCMException::E_NON_FATAL ); } /** * * @param array $extraArgs Not used at this time. * @param bool $massOp True when called from massEnable(). * * @return int * * @throws LSCMException Thrown indirectly by PluginVersion::getInstance() * call. * @throws LSCMException Thrown indirectly by * PluginVersion::getInstance()->prepareUserInstall() call. * @throws LSCMException Thrown indirectly by $this->canEnable() call. * @throws LSCMException Thrown indirectly by $this->enable_lscwp() call. * @throws LSCMException Thrown indirectly by * $this->removeLscwpPluginFiles() call. * * @noinspection PhpUnusedParameterInspection */ public function enable( array $extraArgs, $massOp = false ) { $isNewInstall = PluginVersion::getInstance()->prepareUserInstall( WpConstants::getWpConstant('WP_PLUGIN_DIR') ); if ( $isNewInstall ) { $this->installedLscwpVer = $this->getPluginVersionFromFile(); $this->currInstall->addNewLscwpFlagFile(); } if ( !$this->canEnable($massOp, $isNewInstall) ) { $status = $this->currInstall->getStatus(); $ret = UserCommand::EXIT_FAIL; } else { $status = $this->enable_lscwp(); $ret = UserCommand::EXIT_SUCC; } if ( $isNewInstall ) { if ( $status & WPInstall::ST_PLUGIN_INACTIVE ) { $this->removeLscwpPluginFiles(); } else { $this->updateTranslationFiles(); } } $this->outputResult('STATUS', $this->currInstall->getStatus()); return $ret; } /** * * @param string[] $extraArgs * * @return int * * @throws LSCMException Thrown indirectly by $this->enable() call. */ public function massEnable( array $extraArgs ) { $ret = $this->enable($extraArgs, true); if ( $this->massIncr != '' ) { $this->outputResult('MASS_INCR', $this->massIncr); } return $ret; } /** * * @param bool $isMassAction * * @return bool * * @throws LSCMException Thrown indirectly by $this->getCurrStatus() call. * @throws LSCMException Thrown indirectly by Logger::notice() call. * @throws LSCMException Thrown indirectly by Logger::uiSuccess() call. * @throws LSCMException Thrown indirectly by * $this->currInstall->addUserFlagFile() call. * @throws LSCMException Thrown indirectly by Logger::uiSuccess() call. * @throws LSCMException Thrown indirectly by Logger::notice() call. * @throws LSCMException Thrown indirectly by * $this->currInstall->addUserFlagFile() call. * @throws LSCMException Thrown indirectly by Logger::uiSuccess() call. */ private function canDisable( $isMassAction ) { $status = $this->getCurrStatus(); if ( $status & WPInstall::ST_PLUGIN_INACTIVE ) { Logger::notice('Ignore - Already disabled'); Logger::uiSuccess( 'LiteSpeed Cache Already Disabled - No Action Taken' ); return false; } if ( $isMassAction ) { if ( !($status & WPInstall::ST_LSC_ADVCACHE_DEFINED) ) { $this->currInstall->addUserFlagFile(); Logger::uiSuccess( 'LSCWP Detected As Manually Enabled But Not Caching - Flag ' . 'Set. If desired, this installation can be disabled ' . 'from the Manage Cache Installations screen.' ); Logger::notice( 'Ignore for mass disable - Installed manually as advanced ' . 'cache not set.' ); return false; } if ( WpFuncs::isPluginActiveForNetwork(self::LSCWP_PLUGIN) ) { $this->currInstall->addUserFlagFile(); Logger::uiSuccess( 'LiteSpeed Cache Detected As Network Activated - Flag Set ' . '& No Action Taken' ); return false; } } return true; } /** * * @param string[] $extraArgs Not used at this time. * @param bool $massOp True when called from MassDisable(). * * @return int * * @throws LSCMException Thrown indirectly by $this->canDisable() call. * @throws LSCMException Thrown indirectly by $this->performDisable() call. * @throws LSCMException Thrown indirectly by Logger::uiSuccess() call. * * @noinspection PhpUnusedParameterInspection */ public function disable( array $extraArgs, $massOp = false ) { if ( !$this->canDisable($massOp) ) { $ret = UserCommand::EXIT_FAIL; } else { if ( $this->performDisable(true) & WPInstall::ST_PLUGIN_ACTIVE ) { $ret = UserCommand::EXIT_FAIL; } else { Logger::uiSuccess('LiteSpeed Cache Disabled'); $this->massIncr = 'SUCC'; $ret = UserCommand::EXIT_SUCC; } } $this->outputResult('STATUS', $this->currInstall->getStatus()); return $ret; } /** * * @param string[] $extraArgs * * @return int * * @throws LSCMException Thrown indirectly by $this->disable() call. */ public function massDisable( array $extraArgs ) { $ret = $this->disable($extraArgs, true); if ( $this->massIncr != '' ) { $this->outputResult('MASS_INCR', $this->massIncr); } return $ret; } /** * Includes LSCWP files needed to properly disable the LSCWP plugin. * * @since 1.13 Removed param $lscwpVer. */ private function includeDisableRequiredFiles() { $dir = WpConstants::getWpConstant('WP_PLUGIN_DIR') . '/litespeed-cache'; switch (true) { case Util::betterVersionCompare( $this->installedLscwpVer, '3.0', '>=' ): require_once "$dir/src/admin.cls.php"; break; case Util::betterVersionCompare( $this->installedLscwpVer, '1.1.2.2', '>' ): require_once "$dir/admin/litespeed-cache-admin.class.php"; break; default: require_once "$dir/admin/class-litespeed-cache-admin.php"; } if ( Util::betterVersionCompare( $this->installedLscwpVer, '1.1.0', '<' ) && Util::betterVersionCompare( $this->installedLscwpVer, '1.0.6', '>' ) ) { require_once "$dir/admin/class-litespeed-cache-admin-rules.php"; } } /** * * @param bool $uninstall * * @return int * * @throws LSCMException Thrown indirectly by $this->disable_lscwp() call. */ private function performDisable( $uninstall ) { $this->includeDisableRequiredFiles(); return $this->disable_lscwp($uninstall); } /** * * @param string[] $fromVersions * @param string $toVersion * @param bool $massOp Not used at this time. * * @return bool * * @noinspection PhpUnusedParameterInspection */ private function canUpgrade( array $fromVersions, $toVersion, $massOp ) { if ( !file_exists($this->pluginEntry) || $toVersion == $this->installedLscwpVer ) { return false; } foreach ( $fromVersions as $fromVer ) { $fromVerParts = explode('.', $fromVer); $installedVerParts = explode('.', $this->installedLscwpVer); $i = 0; while ( isset($fromVerParts[$i]) ) { $fromVerPart = $fromVerParts[$i]; if ( $fromVerPart == 'x' ) { return true; } if ( !isset($installedVerParts[$i]) || $installedVerParts[$i] != $fromVerPart ) { continue 2; } $i++; } if ( !isset($installedVerParts[$i]) ) { return true; } } return false; } /** * * @param string[] $extraArgs * @param bool $massOp * * @return int * * @throws LSCMException Thrown indirectly by $this->updateStatus() call. * @throws LSCMException Thrown indirectly by $this->upgrade_lscwp() call. */ public function upgrade( array $extraArgs, $massOp = false ) { $toVersion = $extraArgs[1]; if ( !$this->canUpgrade( explode(',', $extraArgs[0]), $toVersion, $massOp ) ) { $this->updateStatus(true); return UserCommand::EXIT_FAIL; } $this->upgrade_lscwp($toVersion); return UserCommand::EXIT_SUCC; } /** * * @param string[] $extraArgs * * @return int * * @throws LSCMException Thrown indirectly by $this->upgrade() call. */ public function massUpgrade( array $extraArgs ) { $ret = $this->upgrade($extraArgs, true); if ( $this->massIncr != '' ) { $this->outputResult('MASS_INCR', $this->massIncr); } return $ret; } /** * * @param bool $uninstall */ private function deactivate_lscwp( $uninstall ) { WpFuncs::deactivatePlugins(self::LSCWP_PLUGIN); if ( $uninstall ) { //Todo: add some msg about having removed plugin files? WpFuncs::deletePlugins([ self::LSCWP_PLUGIN ]); } } /** * @since 1.17.5 * * @return array */ private function getWpdBlogIds() { return Wpdb::getCol('SELECT blog_id FROM ' . Wpdb::getBlogs() . ';'); } /** * * @param bool $uninstall * * @return int * * @throws LSCMException Thrown indirectly by $this->getCurrStatus() call. */ private function disable_lscwp( $uninstall ) { if ( WpConstants::getWpConstant('MULTISITE') ) { foreach ( $this->getWpdBlogIds() as $blogId ) { WpFuncs::switchToBlog($blogId); $this->deactivate_lscwp($uninstall); WpFuncs::restoreCurrentBlog(); } } else { $this->deactivate_lscwp($uninstall); } return $this->getCurrStatus(); } /** * * @return int * * @throws LSCMException Thrown indirectly by $this->getCurrStatus() call. * @throws LSCMException Thrown indirectly by $this->performDisable() call. * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by * $this->currInstall->addUserFlagFile() call. * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by Logger::uiSuccess() call. */ private function enable_lscwp() { /** * Should not check directly, can error on success due to object cache. */ WpFuncs::activatePlugin(self::LSCWP_PLUGIN); $status = $this->getCurrStatus(); switch (true) { case !($status & WPInstall::ST_LSC_ADVCACHE_DEFINED): $status = $this->performDisable(true); Logger::uiError( 'Detected ' . "{$this->currInstall->getPath()}/wp-content/" . 'advanced-cache.php as belonging to another cache ' . 'plugin. Please deactivate the related cache plugin ' . 'and try again. You may also try manually installing ' . 'through the WordPress Dashboard and following the ' . 'instructions given.' ); $this->massIncr = 'FAIL'; break; case ($status & WPInstall::ST_PLUGIN_ACTIVE): if ( !is_writable($this->currInstall->getWpConfigFile()) && ( !defined('WP_CACHE') || WpConstants::getWpConstant('WP_CACHE') !== true ) ) { /** * LSCACHE_ADV_CACHE is incorrectly defined true at this point. * Detected status must be manually corrected. */ $status &= ~WPInstall::ST_LSC_ADVCACHE_DEFINED; $this->currInstall->setStatus($status); $this->currInstall->addUserFlagFile(); $status = $this->currInstall->getStatus(); Logger::uiError( 'LSCWP Enabled But Not Caching - Please visit the ' . 'WordPress Dashboard for further instructions.' ); } else { Logger::uiSuccess('LSCWP Enabled'); } $this->massIncr = 'SUCC'; break; } return $status; } /** * * @param string $ver * @param bool $runHooks * * @throws LSCMException Thrown when LSCWP plugin version upgrade fails. */ private function upgrade_lscwp( $ver, $runHooks = true ) { /** * Label the following $upgraderWrapper output (Cannot be buffered). */ echo "[UPGRADE]\n"; $upgraderWrapper = new PluginUpgrader; $upgraderWrapper->init(); $upgraderWrapper->upgradeStrings(); if ( $runHooks ) { WpFuncs::addFilter( 'upgrader_pre_install', [ $upgraderWrapper->getWpPluginUpgraderObject(), 'deactivate_plugin_before_upgrade' ], 10, 2 ); WpFuncs::addFilter( 'upgrader_clear_destination', [ $upgraderWrapper->getWpPluginUpgraderObject(), 'delete_old_plugin' ], 10, 4 ); } $upgraderWrapper->run( [ 'package' => 'https://downloads.wordpress.org/plugin/' . "litespeed-cache.$ver.zip", 'destination' => WpConstants::getWpConstant('WP_PLUGIN_DIR'), 'clear_destination' => true, 'clear_working' => true, 'hook_extra' => [ 'plugin' => $this->pluginEntry, 'type' => 'plugin', 'action' => 'update' ] ] ); /** * Start new messages on a new line */ echo "\n"; if ( $runHooks ) { /** * Cleanup our hooks, in case something else does an upgrade on * this connection. */ WpFuncs::removeFilter( 'upgrader_pre_install', [ $upgraderWrapper->getWpPluginUpgraderObject(), 'deactivate_plugin_before_upgrade' ] ); WpFuncs::removeFilter( 'upgrader_clear_destination', [ $upgraderWrapper->getWpPluginUpgraderObject(), 'delete_old_plugin' ] ); } if ( !$upgraderWrapper->getResult() || WpFuncs::isWpError($upgraderWrapper->getResult()) ) { throw new LSCMException( "Failed to upgrade to v$ver.", LSCMException::E_NON_FATAL ); } $this->updateTranslationFiles(); /** * Force refresh of plugin update information */ WpFuncs::wpCleanPluginsCache(); } /** * Gets LSCWP version from the litespeed-cache.php file. * * @return string */ private function getPluginVersionFromFile() { $lscwp_data = WpFuncs::getPluginData($this->pluginEntry, false, false); return $lscwp_data['Version']; } /** * Checks for local plugin translation files and copies them to the plugin * languages directory if able. This function will also attempt to inform * the root user when a locale's translation should be retrieved or removed. */ public function updateTranslationFiles() { $locale = WpFuncs::getLocale(); if ( $locale == 'en_US' ) { return; } $langDir = $this->currInstall->getPath() . '/wp-content/languages/plugins'; if ( !file_exists($langDir) ) { mkdir($langDir, 0755); } $localTranslationDir = Context::LOCAL_PLUGIN_DIR . "/$this->installedLscwpVer/translations"; $moFileName = "litespeed-cache-$locale.mo"; $poFileName = "litespeed-cache-$locale.po"; $localMoFile = "$localTranslationDir/$moFileName"; $localPoFile = "$localTranslationDir/$poFileName"; $zipFile = "$localTranslationDir/$locale.zip"; $translationFlag = "$localTranslationDir/" . PluginVersion::TRANSLATION_CHECK_FLAG_BASE . "_$locale"; if ( file_exists($localMoFile) && file_exists($localPoFile) ) { copy($localMoFile, "$langDir/$moFileName"); copy($localPoFile, "$langDir/$poFileName"); } elseif ( file_exists($zipFile) ) { WpFuncs::WpFilesystem(); if ( WpFuncs::unzipFile($zipFile, $langDir) !== true ) { $this->outputResult( 'BAD_TRANSLATION', "$locale $this->installedLscwpVer" ); } } elseif ( !file_exists($translationFlag) || (time() - filemtime($translationFlag)) > 86400 ) { $this->outputResult( 'GET_TRANSLATION', "$locale $this->installedLscwpVer" ); } } /** * * @since 1.13.4.4 * @since 1.17.0.3 Added required parameter $advCacheFileContents. * * @param string $advCacheFileContents * * @return bool */ private static function advancedCacheFileHasLscacheDefine( $advCacheFileContents ) { return (strpos($advCacheFileContents, 'LSCACHE_ADV_CACHE') !== false); } /** * Check if advanced-cache.php file contains LSCWP placeholder text. This * file with generic placeholder text was re-added by LSCWP for improved * compatibility with WordPress versions lower than v5.3. * * @since 1.17.0.3 * * @param string $advCacheFileContent * * @return bool */ private static function advancedCacheFileHasPlaceholderMsg( $advCacheFileContent ) { return ( strpos( $advCacheFileContent, 'A compatibility placeholder for WordPress < v5.3' ) !== false ); } private function includeLSCWPAdvancedCacheFile() { if ( file_exists($this->advancedCacheFile) ) { $advCacheFileContents = file_get_contents($this->advancedCacheFile); if ( $advCacheFileContents !== '' && $this->advancedCacheFileHasLscacheDefine( $advCacheFileContents ) ) { include_once $this->advancedCacheFile; } } } /** * * @throws LSCMException Thrown indirectly by * $this->currInstall->removePluginFiles() call. */ public function removeLscwpPluginFiles() { $this->currInstall->removePluginFiles(dirname($this->pluginEntry)); } /** * * @param string[] $extraArgs * @param bool $massOp Not used at this time. * * @return int * * @throws LSCMException Thrown indirectly by * DashNotifier::prepareUserInstall() call. * @throws LSCMException Thrown indirectly by DashNotifier::doNotify() * call. * @throws LSCMException Thrown indirectly by Logger::uiSuccess() call. * @throws LSCMException Thrown indirectly by Logger::uiError() call. * * @noinspection PhpUnusedParameterInspection */ public function dashNotify( array $extraArgs, $massOp = false ) { if ( DashNotifier::canNotify($this->currInstall->getPath()) ) { DashNotifier::prepareUserInstall(); if ( DashNotifier::doNotify(base64_decode($extraArgs[0])) ) { Logger::uiSuccess('Notified Successfully'); $this->massIncr = 'SUCC'; return UserCommand::EXIT_SUCC; } Logger::uiError('Failed to Notify'); $this->massIncr = 'FAIL'; } else { $this->massIncr = 'BYPASS'; } return UserCommand::EXIT_FAIL; } /** * * @param string[] $extraArgs * * @return int * * @throws LSCMException Thrown indirectly by $this->dashNotify() call. */ public function massDashNotify( array $extraArgs ) { $ret = $this->dashNotify($extraArgs, true); if ( $this->massIncr != '' ) { $this->outputResult('MASS_INCR', $this->massIncr); } return $ret; } /** * * @param string[] $extraArgs Unused for now. * @param bool $massOp Unused for now. * * @return int * * @throws LSCMException Thrown indirectly by Logger::uiSuccess() call. * * @noinspection PhpUnusedParameterInspection */ public function dashDisable( array $extraArgs, $massOp = false ) { if ( WpConstants::getWpConstant('MULTISITE') ) { foreach ( $this->getWpdBlogIds() as $blogId ) { WpFuncs::switchToBlog($blogId); DashNotifier::deactivate(true); WpFuncs::restoreCurrentBlog(); } } else { DashNotifier::deactivate(true); } if ( WpFuncs::isPluginActive(DashNotifier::DASH_PLUGIN) ) { $this->massIncr = 'FAIL'; return UserCommand::EXIT_FAIL; } Logger::uiSuccess('Dash Notifier Disabled'); $this->massIncr = 'SUCC'; return UserCommand::EXIT_SUCC; } /** * * @param string[] $extraArgs * * @return int * * @throws LSCMException Thrown indirectly by $this->dashDisable() call. */ public function massDashDisable( array $extraArgs ) { $ret = $this->dashDisable($extraArgs, true); if ( $this->massIncr != '' ) { $this->outputResult('MASS_INCR', $this->massIncr); } return $ret; } /** * * @since 1.12 * * @param bool $setOutputResult * * @return string */ public function getQuicCloudAPIKey( $setOutputResult = false ) { $key = WpFuncs::applyFilters('litespeed_conf', 'api_key', null); if ( $key == 'api_key' || $key == null ) { $key = ''; } if ( $setOutputResult ) { $this->outputResult('API_KEY', $key); } return $key; } /** * Set global server and environment variables. * * @since 1.9.8 * * @param string $key * @param mixed $val */ private function setEnvVar( $key, $val ) { $_SERVER[$key] = $val; putenv("$key=$val"); } /** * Checks if the current WordPress installation is a multisite install and * does some preload setup if so. * * Patterns and multisite check logic based on WordPress function * is_multisite(). * * @since 1.9.8 * * @return bool * * @throws LSCMException Thrown when DOMAIN_CURRENT_SITE is not found with * MULTISITE defined. * @throws LSCMException Thrown when PATH_CURRENT_SITE is not found with * MULTISITE defined. */ private function isMultisite() { $config_content = file_get_contents($this->currInstall->getWpConfigFile()); $isMultiSite = ( preg_match( '/define\(\s*[\'"]MULTISITE[\'"]\s*,[^;]*;/', $config_content, $m1 ) && preg_match( '/define\(\s*[\'"]MULTISITE[\'"]\s*,\s*true\s*\)\s*;/', $m1[0] ) ) || ( preg_match( '/define\(\s*[\'"]SUBDOMAIN_INSTALL[\'"]\s*,[^;]*;/', $config_content ) || preg_match( '/define\(\s*[\'"]VHOST[\'"]\s*,[^;]*;/', $config_content ) || preg_match( '/define\(\s*[\'"]SUNRISE[\'"]\s*,[^;]*;/', $config_content ) ); if ( !$isMultiSite ) { return false; } if ( !preg_match( '/define\(\s*[\'"]DOMAIN_CURRENT_SITE[\'"]\s*,' . '\s*[\'"](.+)[\'"]\s*\)\s*;/', $config_content, $m2 ) ) { throw new LSCMException( 'Cannot find DOMAIN_CURRENT_SITE with MULTISITE defined.' ); } $this->currInstall->setServerName($m2[1]); if ( !preg_match( '/define\(\s*[\'"]PATH_CURRENT_SITE[\'"]\s*,' . '\s*[\'"](.+)[\'"]\s*\)\s*;/', $config_content, $m3 ) ) { throw new LSCMException( 'Cannot find PATH_CURRENT_SITE with MULTISITE defined.' ); } $this->setEnvVar('REQUEST_URI', $m3[1]); Util::define_wrapper('WP_NETWORK_ADMIN', true); return true; } /** * * WP Variables: $wpdb, $shortcode_tags * * @global \wpdb $wpdb * @global array $shortcode_tags * * @throws LSCMException Thrown when detected WordPress version is lower * then 4.0. * @throws LSCMException Thrown when unable to find a required WordPress * include file. * @throws LSCMException Thrown indirectly by $this->isMultisite() call. * * @noinspection PhpUndefinedClassInspection */ private function initWp() { /** * Declared global variables for use in included files. * * @noinspection PhpUnusedLocalVariableInspection */ global $wpdb, $shortcode_tags; error_reporting(E_ALL); /** * Attempt to override any WordPress memory limits. */ Util::define_wrapper('WP_MEMORY_LIMIT', '512M'); Util::define_wrapper('WP_MAX_MEMORY_LIMIT', '512M'); /** * Only load core WordPress functionality. */ Util::define_wrapper('SHORTINIT', true); $wpPath = $this->currInstall->getPath(); /** * Set WP version data global variables, including $wp_version. */ include_once "$wpPath/wp-includes/version.php"; /** @noinspection PhpUndefinedVariableInspection $wp_version is defined * and made available in previous version.php include */ if ( Util::betterVersionCompare($wp_version, '4.0', '<') ) { throw new LSCMException( "Detected WordPress version as $wp_version. Version 4.0 ' . 'required at minimum." ); } /** * Set needed server variables. */ $_SERVER['SCRIPT_FILENAME'] = "$wpPath/wp-admin/plugins.php"; if ( !$this->isMultisite() ) { $this->setEnvVar('REQUEST_URI', ''); } /** * Set for LSCWP v1.1.5.1+ plugin logic. */ if ( $docRoot = $this->currInstall->getDocRoot() ) { /** * For enable/disable. */ $this->setEnvVar('DOCUMENT_ROOT', $docRoot); } $serverName = $this->currInstall->getServerName(); if ( empty($serverName) ) { $serverName = self::LSCWP_HTTP_HOST_TEST; } /** * For security plugins. */ $this->setEnvVar('HTTP_HOST', $serverName); /** * Version specific includes may fail on RC releases. */ $includeFiles = [ '/wp-load.php', '/wp-includes/default-constants.php', '/wp-includes/formatting.php', '/wp-includes/meta.php', '/wp-includes/l10n.php', '/wp-includes/class-wp-walker.php', '/wp-includes/capabilities.php' ]; if ( Util::betterVersionCompare($wp_version, '4.4.0', '>=') ) { $includeFiles[] = '/wp-includes/class-wp-roles.php'; $includeFiles[] = '/wp-includes/class-wp-role.php'; $includeFiles[] = '/wp-includes/class-wp-user.php'; $includeFiles[] = '/wp-includes/rest-api.php'; $includeFiles[] = '/wp-includes/class-wp-http-encoding.php'; $includeFiles[] = '/wp-includes/class-wp-http-proxy.php'; $includeFiles[] = '/wp-includes/class-wp-http-response.php'; $includeFiles[] = '/wp-includes/class-wp-http-curl.php'; $includeFiles[] = '/wp-includes/class-wp-http-cookie.php'; } $includeFiles[] = '/wp-includes/query.php'; $includeFiles[] = '/wp-includes/theme.php'; $includeFiles[] = '/wp-includes/class-wp-theme.php'; $includeFiles[] = '/wp-includes/user.php'; $includeFiles[] = '/wp-includes/general-template.php'; $includeFiles[] = '/wp-includes/link-template.php'; $includeFiles[] = '/wp-includes/post.php'; $includeFiles[] = '/wp-includes/kses.php'; $includeFiles[] = '/wp-includes/cron.php'; $includeFiles[] = '/wp-includes/update.php'; $includeFiles[] = '/wp-includes/shortcodes.php'; $includeFiles[] = '/wp-includes/http.php'; if ( Util::betterVersionCompare($wp_version, '5.9.0', '>=') ) { $includeFiles[] = '/wp-includes/class-wp-http.php'; } else { $includeFiles[] = '/wp-includes/class-http.php'; } if ( Util::betterVersionCompare($wp_version, '4.6.0', '>=') ) { $includeFiles[] = '/wp-includes/class-wp-http-requests-response.php'; } if ( Util::betterVersionCompare($wp_version, '4.7.0', '>=') ) { $includeFiles[] = '/wp-includes/class-wp-http-requests-hooks.php'; /** * Content contained in /wp-includes/query.php for earlier versions. */ $includeFiles[] = '/wp-includes/class-wp-query.php'; } if ( Util::betterVersionCompare($wp_version, '5.0.0', '>=') ) { $includeFiles[] = '/wp-includes/blocks.php'; $includeFiles[] = '/wp-includes/class-wp-block-parser.php'; } if ( Util::betterVersionCompare($wp_version, '6.1.0', '>=') ) { $includeFiles[] = '/wp-includes/class-wp-textdomain-registry.php'; } $includeFiles[] = '/wp-includes/ms-functions.php'; $includeFiles[] = '/wp-includes/ms-deprecated.php'; $includeFiles[] = '/wp-includes/pluggable.php'; $includeFiles[] = '/wp-admin/includes/plugin.php'; $includeFiles[] = '/wp-admin/includes/file.php'; $includeFiles[] = '/wp-admin/includes/class-wp-upgrader.php'; $includeFiles[] = '/wp-admin/includes/misc.php'; $includeFiles[] = '/wp-admin/includes/template.php'; if ( Util::betterVersionCompare($wp_version, '6.5.0', '>=') ) { $includeFiles[] = '/wp-includes/class-wp-plugin-dependencies.php'; } set_error_handler('\Lsc\Wp\WPCaller::warning_handler'); /** * Force WP to use PHP I/O file handling. */ Util::define_wrapper('FS_METHOD', 'direct'); /** * Trigger an early return from WP Rocket advanced-cache.php to prevent * WP Rocket from serving a cached copy and killing the process. This * occurs when calling an action from our control panel plugins and is * fixed by more closely matching the environment of a direct cli call. */ unset($_SERVER['REQUEST_METHOD']); self::redefineDisabledFunctions(); foreach ( $includeFiles as $relFilePath ) { $file = $wpPath . $relFilePath; if ( !file_exists($file) ) { throw new LSCMException( "Could not include missing file $file." ); } include_once $file; } restore_error_handler(); /** * Needs to be defined after including files. */ Util::define_wrapper('WP_ADMIN', true); /** * Define common WP constants and set 'wp_plugin_paths' array. */ WpFuncs::wpPluginDirectoryConstants(); /** * Do not load other plugins. */ $GLOBALS['wp_plugin_paths'] = []; WpFuncs::wpCookieConstants(); /** * Create global wp_query (WordPress) object entry. Needed during * LSCWP uninstall. */ $GLOBALS['wp_the_query'] = (new WpQuery())->getWpWpQueryObject(); $GLOBALS['wp_query'] = $GLOBALS['wp_the_query']; if ( Util::betterVersionCompare($wp_version, '6.1.0', '>=') ) { $GLOBALS['wp_textdomain_registry'] = (new WpTextdomainRegistry())->getWpWpTextdomainRegistryObject(); } $this->pluginEntry = WpConstants::getWpConstant('WP_PLUGIN_DIR') . '/' . self::LSCWP_PLUGIN ; if ( $this->loadLscwp && file_exists($this->pluginEntry) ) { include $this->pluginEntry; $this->installedLscwpVer = $this->getPluginVersionFromFile(); if ( Util::betterVersionCompare( $this->installedLscwpVer, '3.0.4', '<' ) ) { $this->includeLSCWPAdvancedCacheFile(); } } } } PK!*ME E 4webcachemgr/src/View/Model/DashNotifierViewModel.phpnuIwwpInstallStorage = $wpInstallStorage; $this->wpDashMsgs = $wpDashMsgs; $this->init(); } protected function init() { $this->setIconDir(); $this->setStoredMsgIds(); $this->setDiscoveredCount(); } /** * * @param string $field * @return null|string */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } protected function setIconDir() { $iconDir = ''; try { $iconDir = Context::getOption()->getIconDir(); } catch ( LSCMException $e ) { Logger::debug($e->getMessage() . ' Could not get icon directory.'); } $this->tplData[self::FLD_ICON_DIR] = $iconDir; } protected function setStoredMsgIds() { $msgs = $this->wpDashMsgs->getMsgData(); $this->tplData[self::FLD_RAP_MSG_IDS] = array_keys($msgs[WPDashMsgs::KEY_RAP_MSGS]); $this->tplData[self::FLD_BAM_MSG_IDS] = array_keys($msgs[WPDashMsgs::KEY_BAM_MSGS]); } protected function setDiscoveredCount() { $this->tplData[self::FLD_DISCOVERED_COUNT] = $this->wpInstallStorage->getCount(); } /** * * @return string */ public function getTpl() { return realpath(__DIR__ . '/../Tpl') . '/DashNotifier.tpl'; } } PK!h4o((5webcachemgr/src/View/Model/VersionManageViewModel.phpnuIwinit() call. */ public function __construct( WPInstallStorage $wpInstallStorage ) { $this->wpInstallStorage = $wpInstallStorage; $this->init(); } /** * * @throws LSCMException Thrown indirectly by $this->setIconPath() call. * @throws LSCMException Thrown indirectly by $this->setActiveVerData() * call. * @throws LSCMException Thrown indirectly by $this->setVerListData() call. * @throws LSCMException Thrown indirectly by $this->setMsgData() call. */ protected function init() { $this->setIconPath(); $this->setActiveVerData(); $this->setVerListData(); $this->setStateData(); $this->setMsgData(); } /** * * @param string $field * * @return null|boolean|string|string[] */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } /** * * @throws LSCMException Thrown indirectly by Logger::debug() call. */ protected function setIconPath() { $iconPath = ''; try { $iconDir = Context::getOption()->getIconDir(); $iconPath = "$iconDir/lscwpCurrentVersion.svg"; } catch ( LSCMException $e ) { Logger::debug($e->getMessage() . ' Could not get icon directory.'); } $this->tplData[self::FLD_ICON] = $iconPath; } /** * * @throws LSCMException Thrown indirectly by Logger::debug() call. */ protected function setActiveVerData() { try { $currVer = PluginVersion::getCurrentVersion(); } catch ( LSCMException $e ) { Logger::debug( $e->getMessage() . ' Could not get active LSCWP version.' ); $currVer = false; } $this->tplData[self::FLD_ACTIVE_VER] = $currVer; } protected function setStateData() { if ( $this->wpInstallStorage->getError() == 0 ) { if ( $this->wpInstallStorage->getCount(true) > 0 ) { $this->tplData[self::FLD_STATE] = self::ST_INSTALLS_DISCOVERED; } else { $this->tplData[self::FLD_STATE] = self::ST_NO_NON_ERROR_INSTALLS_DISCOVERED; } } else { $this->tplData[self::FLD_STATE] = self::ST_SCAN_NEEDED; } } /** * * @throws LSCMException Thrown indirectly by PluginVersion::getInstance() * call. * @throws LSCMException Thrown indirectly by Logger::debug() call. */ protected function setVerListData() { $vermgr = PluginVersion::getInstance(); try { $verList = $vermgr->getShortVersions(); $allowedList = $vermgr->getAllowedVersions(); } catch ( LSCMException $e ) { Logger::debug( $e->getMessage() . ' Could not retrieve version list.' ); $verList = $allowedList = array(); } $this->tplData[self::FLD_VERSION_LIST] = $verList; $this->tplData[self::FLD_ALLOWED_VER_LIST] = $allowedList; } /** * * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. */ protected function setMsgData() { $this->tplData[self::FLD_ERR_MSGS] = Logger::getUiMsgs(Logger::UI_ERR); } /** * * @return string * * @throws LSCMException Thrown indirectly by Context::getOption() call. */ public function getTpl() { return Context::getOption()->getSharedTplDir() . '/VersionManage.tpl'; } } PK!) >webcachemgr/src/View/Model/MassDashNotifyProgressViewModel.phpnuIwinit() call. */ public function __construct() { $this->init(); } /** * * @throws LSCMException Thrown indirectly by $this->setIconPath() call. */ protected function init() { $this->setIconPath(); $this->grabSessionData(); } /** * * @param string $field * * @return null|mixed */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } /** * * @throws LSCMException Thrown indirectly by Logger::debug() call. */ protected function setIconPath() { $iconPath = ''; try { $iconPath = Context::getOption()->getIconDir() . '/wpNotifier.svg'; } catch ( LSCMException $e ) { Logger::debug("{$e->getMessage()} Could not get icon directory."); } $this->tplData[self::FLD_ICON] = $iconPath; } protected function grabSessionData() { $info = $_SESSION[$this->sessionKey]; $this->tplData[self::FLD_INSTALLS_COUNT] = count($info['installs']); } /** * * @return string * * @throws LSCMException Thrown indirectly by Context::getOption() call. */ public function getTpl() { return Context::getOption()->getSharedTplDir() . '/MassDashNotifyProgress.tpl'; } } PK!]B" " 9webcachemgr/src/View/Model/MassEnableDisableViewModel.phpnuIwwpInstallStorage = $wpInstallStorage; $this->init(); } protected function init() { $this->setIconPath(); $this->setActiveVerData(); $this->setStateData(); } /** * * @param string $field * @return null|mixed */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } protected function setIconPath() { $iconPath = ''; try { $iconDir = Context::getOption()->getIconDir(); $iconPath = "{$iconDir}/massEnableDisableCache.svg"; } catch ( LSCMException $e ) { Logger::debug($e->getMessage() . ' Could not get icon directory.'); } $this->tplData[self::FLD_ICON] = $iconPath; } protected function setActiveVerData() { try { $currVer = PluginVersion::getCurrentVersion(); } catch ( LSCMException $e ) { Logger::debug($e->getMessage() . ' Could not get active LSCWP version.'); $currVer = false; } $this->tplData[self::FLD_ACTIVE_VER] = $currVer; } protected function setStateData() { if ( $this->wpInstallStorage->getError() == 0 ) { if ( $this->wpInstallStorage->getCount(true) > 0 ) { $this->tplData[self::FLD_STATE] = self::ST_INSTALLS_DISCOVERED; } else { $this->tplData[self::FLD_STATE] = self::ST_NO_INSTALLS_DISCOVERED; } } else { $this->tplData[self::FLD_STATE] = self::ST_SCAN_NEEDED; } } public function getTpl() { return Context::getOption()->getSharedTplDir() . '/MassEnableDisable.tpl'; } } PK!pLp~~?webcachemgr/src/View/Model/MassDashDisableProgressViewModel.phpnuIwinit() call. */ public function __construct() { $this->init(); } /** * * @throws LSCMException Thrown indirectly by $this->setIconPath() call. */ protected function init() { $this->setIconPath(); $this->grabSessionData(); } /** * * @param string $field * * @return null|mixed */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } /** * * @throws LSCMException Thrown indirectly by Logger::debug() call. */ protected function setIconPath() { $iconPath = ''; try { $iconPath = Context::getOption()->getIconDir() . '/wpNotifier.svg'; } catch ( LSCMException $e ) { Logger::debug("{$e->getMessage()} Could not get icon directory."); } $this->tplData[self::FLD_ICON] = $iconPath; } protected function grabSessionData() { $info = $_SESSION[$this->sessionKey]; $this->tplData[self::FLD_INSTALLS_COUNT] = count($info['installs']); } /** * * @return string * * @throws LSCMException Thrown indirectly by Context::getOption() call. */ public function getTpl() { return Context::getOption()->getSharedTplDir() . '/MassDashDisableProgress.tpl'; } } PK![J J =webcachemgr/src/View/Model/FlagUnflagAllProgressViewModel.phpnuIwinit() call. */ public function __construct( $action ) { switch ( $action ) { case 'flag': case 'unflag': $this->action = $action; break; default: throw new LSCMException( 'Unrecognized $action value passed to FlagUnflagAllProgressViewModel constructor.' ); } $this->init(); } /** * * @throws LSCMException Thrown indirectly by $this->setIconPath() call. */ protected function init() { $this->setIconPath(); $this->setAction(); $this->grabSessionData(); } /** * * @param string $field * * @return null|int|string */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } /** * * @throws LSCMException Thrown indirectly by Logger::debug() call. */ protected function setIconPath() { $iconPath = ''; try { $iconPath = Context::getOption()->getIconDir() . '/manageCacheInstallations.svg'; } catch ( LSCMException $e ) { Logger::debug("{$e->getMessage()}. Could not get icon directory."); } $this->tplData[self::FLD_ICON] = $iconPath; } protected function setAction() { $this->tplData[self::FLD_ACTION] = $this->action; } protected function grabSessionData() { $this->tplData[self::FLD_INSTALLS_COUNT] = count($_SESSION['mass_' . $this->action . '_info']['installs']); } /** * * @return string * * @throws LSCMException Thrown indirectly by Context::getOption() call. */ public function getTpl() { return Context::getOption()->getSharedTplDir() . '/FlagUnflagAllProgress.tpl'; } } PK!{]7webcachemgr/src/View/Model/CacheRootNotSetViewModel.phpnuIwgetSharedTplDir() . '/CacheRootNotSet.tpl'; } } PK!w8webcachemgr/src/View/Model/ScanProgressStepViewModel.phpnuIwmgrStep = $this->tplData[self::FLD_MGR_STEP] = $mgrStep; $this->init(); } /** * * @since 1.13.3 * * @throws LSCMException Thrown indirectly. */ protected function init() { $this->setTitle(); $this->setIconPath(); $this->grabSessionData(); } /** * * @since 1.13.3 * * @param string $field * @return null|int|string */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } /** * * @since 1.13.3 */ protected function setTitle() { if ( $this->mgrStep == self::OP_SCAN ) { $title = 'Scanning/Re-scanning For All WordPress Installations...'; } else { $title = 'Discovering New WordPress Installations...'; } $this->tplData[self::FLD_TITLE] = $title; } /** * * @since 1.13.3 * * @throws LSCMException Thrown indirectly. */ protected function setIconPath() { $iconPath = ''; try { $iconDir = Context::getOption()->getIconDir(); $iconPath = "{$iconDir}/manageCacheInstallations.svg"; } catch ( LSCMException $e ) { Logger::debug($e->getMessage() . ' Could not get icon directory.'); } $this->tplData[self::FLD_ICON] = $iconPath; } /** * * @since 1.13.3 */ protected function grabSessionData() { $info = isset($_SESSION['scanInfo']) && is_array($_SESSION['scanInfo']) ? $_SESSION['scanInfo'] : []; if ( !empty($info['homeDirs']) && is_array($info['homeDirs']) ) { $total = count($info['homeDirs']); } elseif ( !empty($info['installs']) && is_array($info['installs']) ) { $total = count($info['installs']); } else { $total = 0; } $this->tplData[self::FLD_TOTAL_COUNT] = $total; } /** * * @since 1.13.3 * * @return string * @throws LSCMException Thrown indirectly. */ public function getTpl() { $info = isset($_SESSION['scanInfo']) && is_array($_SESSION['scanInfo']) ? $_SESSION['scanInfo'] : []; if ( !empty($info['homeDirs']) ) { return Context::getOption()->getSharedTplDir() . '/ScanProgressStep1.tpl'; } return Context::getOption()->getSharedTplDir() . '/ScanProgressStep2.tpl'; } } PK!S[[Awebcachemgr/src/View/Model/MassEnableDisableProgressViewModel.phpnuIwinit() call. */ public function __construct( $action ) { $this->action = ($action === 'disable') ? 'disable' : 'enable'; $this->sessionKey = 'mass' . ucfirst($this->action) . 'Info'; $this->init(); } /** * * @throws LSCMException Thrown indirectly by $this->setIconPath(). * @throws LSCMException Thrown indirectly by $this->setActiveVerData() * call. */ protected function init() { $this->setIconPath(); $this->tplData[self::FLD_ACTION] = $this->action; $this->grabSessionData(); $this->setActiveVerData(); } /** * * @param string $field * * @return null|mixed */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } /** * * @throws LSCMException Thrown indirectly by Logger::debug() call. */ protected function setIconPath() { $iconPath = ''; try { $iconPath = Context::getOption()->getIconDir() . '/massEnableDisableCache.svg'; } catch ( LSCMException $e ) { Logger::debug("{$e->getMessage()} Could not get icon directory."); } $this->tplData[self::FLD_ICON] = $iconPath; } protected function grabSessionData() { $info = $_SESSION[$this->sessionKey]; $this->tplData[self::FLD_INSTALLS_COUNT] = count($info['installs']); } /** * * @throws LSCMException Thrown indirectly by Logger::debug() call. */ protected function setActiveVerData() { try { $activeVer = PluginVersion::getCurrentVersion(); } catch ( LSCMException $e ) { Logger::debug( "{$e->getMessage()} Could not get active LSCWP version." ); $activeVer = false; /** * Unset session data early. */ if ( $this->tplData[self::FLD_ACTION] == 'enable' ) { unset($_SESSION[$this->sessionKey]); } } $this->tplData[self::FLD_ACTIVE_VER] = $activeVer; } /** * * @return string * * @throws LSCMException Thrown indirectly by Context::getOption() call. */ public function getTpl() { return Context::getOption()->getSharedTplDir() . '/MassEnableDisableProgress.tpl'; } } PK!z/́88.webcachemgr/src/View/Model/ManageViewModel.phpnuIw [ 'sort' => 'disabled', 'state' => '', 'btn_content' => '', 'btn_title' => 'Click to enable LSCache', 'onclick' => 'onclick="javascript:lscwpEnableSingle(this);"', 'btn_attributes' => 'data-uk-tooltip', 'btn_state' => '' ], 'enabled' => [ 'sort' => 'enabled', 'state' => '', 'btn_content' => '', 'btn_title' => 'Click to disable LSCache', 'onclick' => 'onclick="javascript:lscwpDisableSingle(this);"', 'btn_attributes' => 'data-uk-tooltip', 'btn_state' => '' ], 'adv_cache' => [ 'sort' => 'warning', 'state' => '', 'btn_content' => '', 'btn_title' => 'Click to disable LSCache', 'onclick' => 'onclick="javascript:lscwpDisableSingle(this);"', 'btn_attributes' => 'data-uk-tooltip', 'btn_state' => '' ], 'disabled_no_active_ver' => [ 'sort' => 'disabled', 'state' => '', 'btn_content' => '' . '', 'btn_title' => '', 'onclick' => '', 'btn_attributes' => '', 'btn_state' => 'disabled', ], 'error' => [ 'sort' => 'error', /** * 'state' added individually later. */ 'btn_title' => '', 'btn_content' => '', 'onclick' => '', 'btn_attributes' => '', 'btn_state' => 'disabled' ] ]; /** * @since 1.13.3 * @var string[][] */ protected $flagInfo = [ 'unflagged' => [ 'sort' => 'unflagged', 'icon' => '' . '', 'btn_title' => 'Click to set flag', 'onclick' => 'onclick="javascript:lscwpFlagSingle(this);"', 'btn_attributes' => 'data-uk-tooltip' ], 'flagged' => [ 'sort' => 'flagged', 'icon' => '' . '', 'btn_title' => 'Click to unset flag', 'onclick' => 'onclick="javascript:lscwpUnflagSingle(this);"', 'btn_attributes' => 'data-uk-tooltip' ], ]; /** * * @param WPInstallStorage $wpInstallStorage * * @throws LSCMException Thrown indirectly by $this->init() call. */ public function __construct( WPInstallStorage $wpInstallStorage ) { $this->wpInstallStorage = $wpInstallStorage; $this->init(); } /** * * @throws LSCMException thrown indirectly by $this->setIconDir() call. * @throws LSCMException thrown indirectly by $this->setActiveVerData() * call. * @throws LSCMException thrown indirectly by $this->setMsgData() call. */ protected function init() { $this->setIconDir(); $this->setBtnDataAndListVisibility(); $this->setActiveVerData(); $this->setListAndCountData(); $this->setMsgData(); } /** * * @param string $field * * @return null|mixed */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } /** * * @throws LSCMException Thrown indirectly by Logger::debug() call. */ protected function setIconDir() { $iconDir = ''; try { $iconDir = Context::getOption()->getIconDir(); } catch ( LSCMException $e ) { Logger::debug("{$e->getMessage()}. Could not get icon directory."); } $this->tplData[self::FLD_ICON_DIR] = $iconDir; } /** * * @throws LSCMException Thrown indirectly by Logger::uiInfo() call. */ protected function setBtnDataAndListVisibility() { $scanBtnName = 'Re-scan'; $btnState = 'disabled'; if ( ($errStatus = $this->wpInstallStorage->getError()) !== 0 ) { $this->tplData[self::FLD_SHOW_LIST] = false; if ( $errStatus == WPInstallStorage::ERR_NOT_EXIST ) { $scanBtnName = 'Scan'; $msg = 'Start by clicking Scan. This will discover all ' . 'active WordPress installations and add them to a list ' . 'below.'; } elseif ( $errStatus == WPInstallStorage::ERR_VERSION_LOW ) { $scanBtnName = 'Scan'; $msg = 'To further improve Cache Management features ' . 'in this version, current installations must be ' . 're-discovered. Please perform a Scan now.'; } else { $msg = 'Scan data could not be read. Please perform a Re-scan.'; } Logger::uiInfo($msg); } else { $this->tplData[self::FLD_SHOW_LIST] = true; if ( $this->wpInstallStorage->getCount() > 0 ) { $btnState = ''; } } $this->tplData[self::FLD_SCAN_BTN_NAME] = $scanBtnName; $this->tplData[self::FLD_BTN_STATE] = $btnState; } protected function setListAndCountData() { $listData = []; $countData = [ self::COUNT_DATA_INSTALLS => 0, self::COUNT_DATA_ENABLED => 0, self::COUNT_DATA_DISABLED => 0, self::COUNT_DATA_WARN => 0, self::COUNT_DATA_ERROR => 0, self::COUNT_DATA_FLAGGED => 0, self::COUNT_DATA_UNFLAGGED => 0 ]; $wpInstalls = $this->wpInstallStorage->getAllWPInstalls(); if ( $wpInstalls !== null ) { $countData[self::COUNT_DATA_INSTALLS] = count($wpInstalls); foreach ( $wpInstalls as $wpInstall ) { $listData[$wpInstall->getPath()] = [ 'statusData' => $this->getStatusDisplayData($wpInstall, $countData), 'flagData' => $this->getFlagDisplayData($wpInstall, $countData), 'siteUrl' => Util::tryIdnToUtf8( (string)$wpInstall->getData(WPInstall::FLD_SITEURL) ) ]; } } $this->tplData[self::FLD_LIST_DATA] = $listData; $this->tplData[self::FLD_COUNT_DATA] = $countData; } /** * * @param WPInstall $wpInstall * @param int[] $countData * * @return string[] */ protected function getStatusDisplayData( WPInstall $wpInstall, array &$countData ) { $wpStatus = $wpInstall->getStatus(); if ( $wpInstall->hasFatalError($wpStatus) ) { $countData[self::COUNT_DATA_ERROR]++; $fatalErrStateInfo = Util::getFatalErrorStateMessageAndLink($wpStatus); $currStatusData = $this->statusInfo['error']; $currStatusData['state'] = ''; } elseif ( ($wpStatus & WPInstall::ST_PLUGIN_INACTIVE ) ) { $countData[self::COUNT_DATA_DISABLED]++; if ( !$this->getTplData(self::FLD_ACTIVE_VER) ) { $currStatusData = $this->statusInfo['disabled_no_active_ver']; } else { $currStatusData = $this->statusInfo['disabled']; } } elseif ( !($wpStatus & WPInstall::ST_LSC_ADVCACHE_DEFINED) ) { $countData[self::COUNT_DATA_WARN]++; $currStatusData = $this->statusInfo['adv_cache']; } else { $countData[self::COUNT_DATA_ENABLED]++; $currStatusData = $this->statusInfo['enabled']; } return $currStatusData; } /** * * @param WPInstall $wpInstall * @param int[] $countData * * @return string[] */ protected function getFlagDisplayData( WPInstall $wpInstall, array &$countData ) { if ( ($wpInstall->getStatus() & WPInstall::ST_FLAGGED ) ) { $countData[self::COUNT_DATA_FLAGGED]++; $currFlagData = $this->flagInfo['flagged']; } else { $countData[self::COUNT_DATA_UNFLAGGED]++; $currFlagData = $this->flagInfo['unflagged']; } return $currFlagData; } /** * * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by Logger::uiWarning() call. */ protected function setActiveVerData() { try { $currVer = PluginVersion::getCurrentVersion(); } catch ( LSCMException $e ) { Logger::debug( "{$e->getMessage()} Could not get active LSCWP version." ); Logger::uiWarning( 'Active LiteSpeed Cache Plugin version is not set. Enable ' . 'operations cannot be performed. Please go to ' . 'Version Manager to ' . 'select a version.' ); $currVer = false; } $this->tplData[self::FLD_ACTIVE_VER] = $currVer; } /** * * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. */ protected function setMsgData() { $this->tplData[self::FLD_INFO_MSGS] = Logger::getUiMsgs(Logger::UI_INFO); $this->tplData[self::FLD_WARN_MSGS] = Logger::getUiMsgs(Logger::UI_WARN); $msgs = $this->wpInstallStorage->getAllCmdMsgs(); $this->tplData[self::FLD_SUCC_MSGS] = array_merge( $msgs['succ'], Logger::getUiMsgs(Logger::UI_SUCC) ); $this->tplData[self::FLD_ERR_MSGS] = array_merge( $msgs['fail'], $msgs['err'], Logger::getUiMsgs(Logger::UI_ERR) ); } /** * * @return string * * @throws LSCMException Thrown indirectly by Context::getOption() call. */ public function getTpl() { return Context::getOption()->getSharedTplDir() . '/Manage.tpl'; } } PK!35webcachemgr/src/View/Model/VersionChangeViewModel.phpnuIwinit(); } protected function init() { $this->setIconPath(); $this->grabSessionData(); } /** * * @param string $field * @return null|int|string */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } protected function setIconPath() { $iconPath = ''; try { $iconDir = Context::getOption()->getIconDir(); $iconPath = "{$iconDir}/lscwpCurrentVersion.svg"; } catch ( LSCMException $e ) { Logger::debug($e->getMessage() . ' Could not get icon directory.'); } $this->tplData[self::FLD_ICON] = $iconPath; } protected function grabSessionData() { $info = $_SESSION['verInfo']; $this->tplData[self::FLD_INSTALLS_COUNT] = count($info['installs']); $this->tplData[self::FLD_VER_NUM] = $info['verNum']; } public function getTpl() { return Context::getOption()->getSharedTplDir() . '/VersionChange.tpl'; } } PK!^=%=%8webcachemgr/src/View/Model/Ajax/CacheMgrRowViewModel.phpnuIwwpInstall = $wpInstall; $this->init(); } protected function init() { $this->getActiveVerData(); $this->setListRowData(); } /** * * @param string $field * * @return null|mixed */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } /** * * @param string $type * * @return string */ public function getSortVal( $type ) { $listData = $this->getTplData(self::FLD_LIST_DATA); return $listData[$this->wpInstall->getPath()]["{$type}Data"]['sort']; } protected function setListRowData() { $this->tplData[self::FLD_LIST_DATA] = [ $this->wpInstall->getPath() => [ 'statusData' => $this->getStatusDisplayData(), 'flagData' => $this->getFlagDisplayData(), 'siteUrl' => Util::tryIdnToUtf8( (string)$this->wpInstall->getData(WPInstall::FLD_SITEURL) ) ] ]; } /** * * @return string[] */ protected function getStatusDisplayData() { $statusInfo = [ 'disabled' => [ 'sort' => 'disabled', 'state' => '', 'btn_content' => '', 'btn_title' => 'Click to enable LSCache', 'onclick' => 'onclick="javascript:lscwpEnableSingle(this);"', 'btn_attributes' => 'data-uk-tooltip', 'btn_state' => '' ], 'enabled' => [ 'sort' => 'enabled', 'state' => '', 'btn_content' => '', 'btn_title' => 'Click to disable LSCache', 'onclick' => 'onclick="javascript:lscwpDisableSingle(this);"', 'btn_attributes' => 'data-uk-tooltip', 'btn_state' => '' ], 'adv_cache' => [ 'sort' => 'warning', 'state' => '', 'btn_content' => '', 'btn_title' => 'Click to disable LSCache', 'onclick' => 'onclick="javascript:lscwpDisableSingle(this);"', 'btn_attributes' => 'data-uk-tooltip', 'btn_state' => '' ], 'disabled_no_active_ver' => [ 'sort' => 'disabled', 'state' => '', 'btn_content' => '', 'onclick' => '', 'btn_attributes' => '', 'btn_state' => 'disabled' ], 'error' => [ 'sort' => 'error', /** * 'state' added individually later. */ 'btn_title' => '', 'btn_content' => '', 'onclick' => '', 'btn_attributes' => '', 'btn_state' => 'disabled' ], 'removed' => [ 'sort' => 'removed', 'state' => '', 'btn_content' => '', 'onclick' => '', 'btn_attributes' => '', 'btn_state' => 'disabled' ] ]; $wpStatus = $this->wpInstall->getStatus(); if ( $wpStatus & WPInstall::ST_ERR_REMOVE ) { $currStatusData = $statusInfo['removed']; } elseif ( $this->wpInstall->hasFatalError($wpStatus) ) { $fatalErrStateInfo = Util::getFatalErrorStateMessageAndLink($wpStatus); $currStatusData = $statusInfo['error']; $currStatusData['state'] = ''; } elseif ( ($wpStatus & WPInstall::ST_PLUGIN_INACTIVE ) ) { if ( !$this->getActiveVerData() ) { $currStatusData = $statusInfo['disabled_no_active_ver']; } else { $currStatusData = $statusInfo['disabled']; } } elseif ( !($wpStatus & WPInstall::ST_LSC_ADVCACHE_DEFINED) ) { $currStatusData = $statusInfo['adv_cache']; } else { $currStatusData = $statusInfo['enabled']; } return $currStatusData; } /** * * @return string[] */ protected function getFlagDisplayData() { $flagInfo = [ 0 => [ 'sort' => 'unflagged', 'icon' => '', 'btn_title' => 'Click to set flag', 'onclick' => 'onclick="lscwpFlagSingle(this);"', 'btn_attributes' => 'data-uk-tooltip' ], 1 => [ 'sort' => 'flagged', 'icon' => '', 'btn_title' => 'Click to unset flag', 'onclick' => 'onclick="lscwpUnflagSingle(this);"', 'btn_attributes' => 'data-uk-tooltip' ], 2 => [ 'sort' => 'removed', 'icon' => '', 'btn_title' => '', 'onclick' => '', 'btn_attributes' => '' ] ]; $wpStatus = $this->wpInstall->getStatus(); if ( $wpStatus & WPInstall::ST_ERR_REMOVE ) { $currFlagData = $flagInfo[2]; } elseif ( ($wpStatus & WPInstall::ST_FLAGGED ) ) { $currFlagData = $flagInfo[1]; } else { $currFlagData = $flagInfo[0]; } return $currFlagData; } /** * * @return bool|string */ protected function getActiveVerData() { try { return PluginVersion::getCurrentVersion(); } catch ( LSCMException $e ) { //don't care about the exception in ajax load. return false; } } /** * * @param string $tplID * * @return null|string * * @throws LSCMException Thrown indirectly by Context::getOption() call. */ public function getTpl( $tplID ) { $sharedTplDir = Context::getOption()->getSharedTplDir(); switch ( $tplID ) { case 'actions_td': return "$sharedTplDir/Ajax/CacheMgrActionsCol.tpl"; case 'status_td': return "$sharedTplDir/Ajax/CacheMgrStatusCol.tpl"; case 'flag_td': return "$sharedTplDir/Ajax/CacheMgrFlagCol.tpl"; //no default } } } PK!Q>229webcachemgr/src/View/Model/UnflagAllProgressViewModel.phpnuIwinit() call. */ public function __construct() { $this->init(); } /** * * @throws LSCMException Thrown indirectly by $this->setIconPath() call. */ protected function init() { $this->setIconPath(); $this->grabSessionData(); } /** * * @param string $field * * @return null|int|string */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } /** * * @throws LSCMException Thrown indirectly by Logger::debug() call. */ protected function setIconPath() { $iconPath = ''; try { $iconPath = Context::getOption()->getIconDir() . '/manageCacheInstallations.svg'; } catch ( LSCMException $e ) { Logger::debug("{$e->getMessage()}. Could not get icon directory."); } $this->tplData[self::FLD_ICON] = $iconPath; } protected function grabSessionData() { $this->tplData[self::FLD_INSTALLS_COUNT] = count($_SESSION['unflagInfo']['installs']); } /** * * @return string * * @throws LSCMException Thrown indirectly by Context::getOption() call. */ public function getTpl() { return Context::getOption()->getSharedTplDir() . '/UnflagAllProgress.tpl'; } } PK!`-2webcachemgr/src/View/Model/MissingTplViewModel.phpnuIwinit($msg); } private function init( $msg ) { $this->tplData[self::FLD_MSG] = $msg; } /** * * @param string $field * @return null|string */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } public function getTpl() { return Context::getOption()->getSharedTplDir() . '/MissingTpl.tpl'; } } PK!Ju 4webcachemgr/src/View/Model/ScanProgressViewModel.phpnuIwmgrStep = $this->tplData[self::FLD_MGR_STEP] = $mgrStep; $this->init(); } /** * * @throws LSCMException Thrown indirectly. */ protected function init() { $this->setTitle(); $this->setIconPath(); $this->grabSessionData(); } /** * * @param string $field * @return null|int|string */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } protected function setTitle() { if ( $this->mgrStep == self::OP_SCAN ) { $title = 'Scanning/Re-scanning For All WordPress Installations...'; } else { $title = 'Discovering New WordPress Installations...'; } $this->tplData[self::FLD_TITLE] = $title; } /** * * @throws LSCMException Thrown indirectly. */ protected function setIconPath() { $iconPath = ''; try { $iconDir = Context::getOption()->getIconDir(); $iconPath = "{$iconDir}/manageCacheInstallations.svg"; } catch ( LSCMException $e ) { Logger::debug($e->getMessage() . ' Could not get icon directory.'); } $this->tplData[self::FLD_ICON] = $iconPath; } protected function grabSessionData() { $info = isset($_SESSION['scanInfo']) && is_array($_SESSION['scanInfo']) ? $_SESSION['scanInfo'] : []; $homeDirs = (!empty($info['homeDirs']) && is_array($info['homeDirs'])) ? $info['homeDirs'] : []; $this->tplData[self::FLD_HOME_DIR_COUNT] = count($homeDirs); } /** * * @return string * @throws LSCMException Thrown indirectly. */ public function getTpl() { return Context::getOption()->getSharedTplDir() . '/ScanProgress.tpl'; } } PK!G=webcachemgr/src/View/Model/RefreshStatusProgressViewModel.phpnuIwinit(); } protected function init() { $this->setIconPath(); $this->grabSessionData(); } /** * * @param string $field * @return null|int|string */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } protected function setIconPath() { $iconPath = ''; try { $iconDir = Context::getOption()->getIconDir(); $iconPath = "{$iconDir}/manageCacheInstallations.svg"; } catch ( LSCMException $e ) { Logger::debug($e->getMessage() . ' Could not get icon directory.'); } $this->tplData[self::FLD_ICON] = $iconPath; } protected function grabSessionData() { $info = $_SESSION['refreshInfo']; $this->tplData[self::FLD_INSTALLS_COUNT] = count($info['installs']); } public function getTpl() { return Context::getOption()->getSharedTplDir() . '/RefreshStatusProgress.tpl'; } } PK!L553webcachemgr/src/View/Model/DataFileMsgViewModel.phpnuIwwpInstallStorage = $wpInstallStorage; $this->init(); } private function init() { $this->setTitleAndDiscover(); } /** * * @param string $field * @return null|string */ public function getTplData( $field ) { if ( !isset($this->tplData[$field]) ) { return null; } return $this->tplData[$field]; } private function setTitleAndDiscover() { switch ( $this->wpInstallStorage->getError() ) { case WPInstallStorage::ERR_NOT_EXIST: $title = 'No Scan Data Found'; $discover = 'discover'; break; case WPInstallStorage::ERR_CORRUPTED: $title = 'Scan Data Corrupted'; $discover = 're-discover'; break; default: $title = 'Scan Data Needs To Be Updated'; $discover = 're-discover'; } $this->tplData[self::FLD_TITLE] = $title; $this->tplData[self::FLD_DISCOVER] = $discover; } /** * * @return string * * @throws LSCMException Thrown indirectly by Context::getOption() call. */ public function getTpl() { return Context::getOption()->getSharedTplDir() . '/DataFileMsg.tpl'; } } PK!FC!webcachemgr/src/View/AjaxView.phpnuIwviewModel = $viewModel; } /** * * @param string $tplID * @return string * @throws LSCMException Thrown directly and indirectly. */ public function getAjaxContent( $tplID = '' ) { ob_start(); try { $this->loadAjaxTpl($this->viewModel->getTpl($tplID)); } catch ( LSCMException $e ) { ob_clean(); throw $e; } return ob_get_clean(); } /** * * @param string $tplPath * @throws LSCMException */ private function loadAjaxTpl( $tplPath ) { $tplFile = basename($tplPath); $custTpl = "{$this->sharedTplDir}/Cust/{$tplFile}"; if ( file_exists($custTpl) ) { include $custTpl; } elseif ( file_exists($tplPath) ) { include $tplPath; } else { throw new LSCMException("Could not load ajax template {$tplPath}."); } } } PK! Mtt(webcachemgr/src/View/Tpl/DataFileMsg.tplnuIwviewModel->getTplData(ViewModel::FLD_TITLE); $discover = $this->viewModel->getTplData(ViewModel::FLD_DISCOVER); $d = array( 'title' => $title ); $this->loadTplBlock('Title.tpl', $d); ?>

Please go to Manage Cache Installations and Scan to all active WordPress installations before continuing.

'Back' ); $this->loadTplBlock('ButtonPanelBackNext.tpl', $d); PK!O|2webcachemgr/src/View/Tpl/Blocks/InputSubmitBtn.tplnuIw PK!H}wnRR2webcachemgr/src/View/Tpl/FlagUnflagAllProgress.tplnuIwviewModel->getTplData(ViewModel::FLD_ACTION); $icon = $this->viewModel->getTplData(ViewModel::FLD_ICON); $installCount = $this->viewModel->getTplData(ViewModel::FLD_INSTALLS_COUNT); $ucAction = ucfirst($action); /** @noinspection SpellCheckingInspection */ $this->loadTplBlock( 'Title.tpl', [ 'title' => "{$ucAction}ging WordPress Installations...", 'icon' => $icon ] ); ?>
ging 0 out of ...
loadTplBlock( 'ButtonPanelBackNext.tpl', [ 'back' => 'Back', 'backDo' => 'lscwp_manage', 'visibility' => 'hidden' ] ); ?>
loadTplBlock( 'DivMsgBox.tpl', [ 'id' => 'errMsgs', 'class' => 'scrollable' ] ); ?>
loadTplBlock( 'DivMsgBox.tpl', [ 'id' => 'succMsgs', 'class' => 'scrollable' ] ); ?>
PK!pHU U 3webcachemgr/src/View/Tpl/MassDashNotifyProgress.tplnuIwviewModel->getTplData(ViewModel::FLD_ICON); $installsCount = $this->viewModel->getTplData(ViewModel::FLD_INSTALLS_COUNT); $d = array( 'title' => 'Mass Notifying All Discovered WordPress Installations...', 'icon' => $icon ); $this->loadTplBlock('Title.tpl', $d); ?>
Attempting to notify 0 out of ...
Currently attempting to notify all discovered WordPress installations. Installations detected with "Error" status or containing a '.dash_notifier_bypass' file will be bypassed. Please be patient.
0 WordPress installation(s) bypassed.", "Dash Notifier notified 0 WordPress installation(s).", "Dash Notifier failed to notify 0 WordPress " . "installation(s)." ); $d = array( 'msgs' => $msgs, 'class' => 'msg-info', /* Template-authored HTML — the span IDs let the progress-poll JS find * bypassedCount / succCount / failCount and update them in place. No * user data is interpolated. */ 'rawHtml' => true, ); $this->loadTplBlock('DivMsgBox.tpl', $d); $d = array( 'back' => 'OK', 'backDo' => 'dash_notifier', 'visibility' => 'hidden' ); $this->loadTplBlock('ButtonPanelBackNext.tpl', $d); ?>
'errMsgs', 'class' => 'scrollable', ); $this->loadTplBlock('DivMsgBox.tpl', $d); ?>
'succMsgs', 'class' => 'scrollable', 'title' => 'Success Messages:', ); $this->loadTplBlock('DivMsgBox.tpl', $d); ?>
PK!;p` ` 4webcachemgr/src/View/Tpl/MassDashDisableProgress.tplnuIwviewModel->getTplData(ViewModel::FLD_ICON); $installsCount = $this->viewModel->getTplData(ViewModel::FLD_INSTALLS_COUNT); $d = array( 'title' => 'Mass Notifying All Discovered WordPress Installations...', 'icon' => $icon ); $this->loadTplBlock('Title.tpl', $d); ?>
Attempting to disable Dash Notifier for 0 out of ...
Currently attempting to disable Dash Notifier for all discovered WordPress installations. Installations detected with "Error" status will be bypassed. Please be patient.
0 WordPress installation(s) bypassed.", "Dash Notifier disabled for 0 WordPress installation(s).", "Dash Notifier failed to disable for 0 WordPress " . "installation(s)." ); $d = array( 'msgs' => $msgs, 'class' => 'msg-info', /* Template-authored HTML — the span IDs let the progress-poll JS find * bypassedCount / succCount / failCount and update them in place. No * user data is interpolated. */ 'rawHtml' => true, ); $this->loadTplBlock('DivMsgBox.tpl', $d); $d = array( 'back' => 'OK', 'backDo' => 'dash_notifier', 'visibility' => 'hidden' ); $this->loadTplBlock('ButtonPanelBackNext.tpl', $d); ?>
'errMsgs', 'class' => 'scrollable', ); $this->loadTplBlock('DivMsgBox.tpl', $d); ?>
'succMsgs', 'class' => 'scrollable', 'title' => 'Success Messages:', ); $this->loadTplBlock('DivMsgBox.tpl', $d); ?>
PK!I==)webcachemgr/src/View/Tpl/ScanProgress.tplnuIwviewModel->getTplData(ViewModel::FLD_TITLE); $icon = $this->viewModel->getTplData(ViewModel::FLD_ICON); $homeDirCount = $this->viewModel->getTplData(ViewModel::FLD_HOME_DIR_COUNT); $mgrStep = $this->viewModel->getTplData(ViewModel::FLD_MGR_STEP); $d = array( 'title' => $title, 'icon' => $icon ); $this->loadTplBlock('Title.tpl', $d); ?>
Scanning 0 out of ...
Currently scanning for all WordPress Installations located under a /public_html/ directory.
If performing a Scan/Re-scan, all installations will be found and added to the Cache Manager list.
If Discovering New, only installations belonging to users not already in the Cache Manager list will be discovered.

'Back', 'backDo' => 'lscwp_manage', 'visibility' => 'hidden' ); $this->loadTplBlock('ButtonPanelBackNext.tpl', $d); ?>
'errMsgs', 'class' => 'scrollable', ); $this->loadTplBlock('DivMsgBox.tpl', $d); ?>
PK!GU.webcachemgr/src/View/Tpl/UnflagAllProgress.tplnuIwviewModel->getTplData(ViewModel::FLD_ICON); $installCount = $this->viewModel->getTplData(ViewModel::FLD_INSTALLS_COUNT); $d = array( 'title' => 'Unflagging WordPress Installations...', 'icon' => $icon ); $this->loadTplBlock('Title.tpl', $d); ?>
Unflagging 0 out of ...
'Back', 'backDo' => 'lscwp_manage', 'visibility' => 'hidden' ); $this->loadTplBlock('ButtonPanelBackNext.tpl', $d); ?>
'errMsgs', 'class' => 'scrollable', ); $this->loadTplBlock('DivMsgBox.tpl', $d); ?>
'succMsgs', 'class' => 'scrollable', ); $this->loadTplBlock('DivMsgBox.tpl', $d); ?>
PK!I|*webcachemgr/src/View/Tpl/VersionManage.tplnuIw viewModel->getTplData(ViewModel::FLD_ICON); $activeVer = $this->viewModel->getTplData(ViewModel::FLD_ACTIVE_VER); $verList = $this->viewModel->getTplData(ViewModel::FLD_VERSION_LIST); $allowedList = $this->viewModel->getTplData(ViewModel::FLD_ALLOWED_VER_LIST); $state = $this->viewModel->getTplData(ViewModel::FLD_STATE); $errMsgs = $this->viewModel->getTplData(ViewModel::FLD_ERR_MSGS); $d = array( 'title' => 'LiteSpeed Cache Plugin Version Manager', 'icon' => $icon ); $this->loadTplBlock('Title.tpl', $d); if ( !empty($errMsgs) ) { $d = array( 'msgs' => $errMsgs, 'class' => 'msg-error scrollable', ); $this->loadTplBlock('DivMsgBox.tpl', $d); } $d = array( 'title' => 'Set Active Version', 'bold' => true ); $this->loadTplBlock('SectionTitle.tpl', $d); ?>

[Feature Disabled] Unable to find/retrieve valid LSCWP version list.

Sets the LiteSpeed Cache plugin version to be used in all future "Enable" operations. (To ensure stability, there may be a delay before new LiteSpeed Cache plugin versions appear in this list)

Current Active Version:

'Force Version Change For All Existing Installations', 'bold' => true ); $this->loadTplBlock('SectionTitle.tpl', $d); if ( $state == ViewModel::ST_SCAN_NEEDED ): ?>

Cache Management list could not be read. Please go to Manage Cache Installations and Scan/Re-scan to discover active WordPress installations.

No WordPress installations with a non-error status discovered in the previous scan (Installations with a Cache Status of "Error" are not counted). If you have any newly installed WordPress installations, please go to Manage Cache Installations and Re-scan/Discover New.

[Feature Disabled] Unable to find/retrieve valid LSCWP version list.

Upgrades active LiteSpeed Cache plugins matching the selection in the "From Version" list to the version chosen under "Upgrade To".
Flagged installations will be skipped. (To ensure stability, there may be a delay before new LiteSpeed Cache plugin versions appear in this list)


From Version(s):
'Back', ); $this->loadTplBlock('ButtonPanelBackNext.tpl', $d); PK!]Z2webcachemgr/src/View/Tpl/RefreshStatusProgress.tplnuIwviewModel->getTplData(ViewModel::FLD_ICON); $installCount = $this->viewModel->getTplData(ViewModel::FLD_INSTALLS_COUNT); $d = array( 'title' => 'Refreshing Status of WordPress Installations...', 'icon' => $icon ); $this->loadTplBlock('Title.tpl', $d); ?>
Refreshing Status for 0 out of ...
'Back', 'backDo' => 'lscwp_manage', 'visibility' => 'hidden' ); $this->loadTplBlock('ButtonPanelBackNext.tpl', $d); ?>
'errMsgs', 'class' => 'scrollable', ); $this->loadTplBlock('DivMsgBox.tpl', $d); ?>
PK!6Yv v .webcachemgr/src/View/Tpl/MassEnableDisable.tplnuIw viewModel->getTplData(ViewModel::FLD_ICON); $activeVer = $this->viewModel->getTplData(ViewModel::FLD_ACTIVE_VER); $state = $this->viewModel->getTplData(ViewModel::FLD_STATE); $d = array( 'title' => 'Mass Enable/Disable LiteSpeed Cache', 'icon' => $icon ); $this->loadTplBlock('Title.tpl', $d); if ( $state == ViewModel::ST_INSTALLS_DISCOVERED ): ?>

The following operations will affect all WordPress installations not currently flagged.

To exclude a WordPress installation from mass operations, flag it in Manage Cache Installations .


Mass Enable
[Feature Disabled] No active LSCWP version set! Cannot Mass Enable.

LiteSpeed Cache will be enabled for all WordPress installations not currently flagged. For WordPress installations that do not already have the plugin, LiteSpeed Cache for WordPress will be installed. This can be changed anytime in the Version Manager.



Mass Disable
LiteSpeed Cache will be disabled for all WordPress installations not currently flagged.

No WordPress installations discovered in the previous scan. If you have any newly installed WordPress installations, please go to Manage Cache Installations and Re-scan/Discover New.

Please go to Manage Cache Installations and click Scan to discover all active WordPress installations before attempting to Mass Enable/Disable Cache.

'Back' ); $this->loadTplBlock('ButtonPanelBackNext.tpl', $d); PK!öfRR4webcachemgr/src/View/Tpl/Ajax/CacheMgrActionsCol.tplnuIwviewModel->getTplData(ViewModel::FLD_LIST_DATA); $classes = 'icon-btn'; foreach ( $listData as $path => $info ): $statusData = $info['statusData']; $safePath = htmlspecialchars($path); ?> viewModel->getTplData(ViewModel::FLD_LIST_DATA); foreach ( $listData as $path => $info ): $statusData = $info['statusData']; ?> viewModel->getTplData(ViewModel::FLD_LIST_DATA); $classes = 'icon-btn'; foreach ( $listData as $path => $info ): $flagData = $info['flagData']; $safePath = htmlspecialchars($path); ?> viewModel->getTplData(ViewModel::FLD_ICON); $installsCount = $this->viewModel->getTplData(ViewModel::FLD_INSTALLS_COUNT); $verNum = $this->viewModel->getTplData(ViewModel::FLD_VER_NUM); $d = array( 'title' => 'Updating LiteSpeed Cache Plugins...', 'icon' => $icon ); $this->loadTplBlock('Title.tpl', $d); ?>
Attempting to upgrade 0 out of ...
Currently upgrading all known LiteSpeed Cache plugin installations to version . Please be patient.

'Back', 'backDo' => 'lscwpVersionManager', 'visibility' => 'hidden' ); $this->loadTplBlock('ButtonPanelBackNext.tpl', $d); ?>
'errMsgs', 'class' => 'scrollable', ); $this->loadTplBlock('DivMsgBox.tpl', $d); ?>
PK!.webcachemgr/src/View/Tpl/ScanProgressStep2.tplnuIwviewModel->getTplData(ViewModel::FLD_TITLE); $icon = $this->viewModel->getTplData(ViewModel::FLD_ICON); $totalCount = $this->viewModel->getTplData(ViewModel::FLD_TOTAL_COUNT); $mgrStep = $this->viewModel->getTplData(ViewModel::FLD_MGR_STEP); $d = array( 'title' => $title, 'icon' => $icon ); $this->loadTplBlock('Title.tpl', $d); ?>
Scanning 0 out of ...
Currently attempting to refresh status for all WordPress installations found in the previous discovery step.
If performing a Scan/Re-scan, all installations will be found and added to the Cache Manager list.
If Discovering New, only installations belonging to users not already in the Cache Manager list will be discovered.

'Back', 'backDo' => 'lscwp_manage', 'visibility' => 'hidden' ); $this->loadTplBlock('ButtonPanelBackNext.tpl', $d); ?>
'errMsgs', 'class' => 'scrollable', ); $this->loadTplBlock('DivMsgBox.tpl', $d); ?>
PK!c۱'webcachemgr/src/View/Tpl/MissingTpl.tplnuIwviewModel->getTplData(ViewModel::FLD_MSG); ?>

PK!v; 6webcachemgr/src/View/Tpl/MassEnableDisableProgress.tplnuIwviewModel->getTplData(ViewModel::FLD_ICON); $action = $this->viewModel->getTplData(ViewModel::FLD_ACTION); $installsCount = $this->viewModel->getTplData(ViewModel::FLD_INSTALLS_COUNT); $activeVer = $this->viewModel->getTplData(ViewModel::FLD_ACTIVE_VER); $actionUpper = ucfirst($action); $d = array( 'title' => 'Mass ' . substr($actionUpper, 0, -1) . 'ing All LiteSpeed Cache Plugins...', 'icon' => $icon ); $this->loadTplBlock('Title.tpl', $d); if ( $action == 'enable' && $activeVer == false ): ?>
No active LSCWP version set! Mass Enable aborted.
'OK' ); $this->loadTplBlock('ButtonPanelBackNext.tpl', $d); else: ?>
Attempting to 0 out of ...
Currently attempting to all LiteSpeed Cache plugin installations. If the LiteSpeed Cache Plugin is not installed, version will be used. Please be patient.
0 flagged/error WordPress installation(s) bypassed.", "LSCWP newly {$action}d for 0 WordPress installation(s).", "LSCWP {$action} failed for 0 WordPress " . "installation(s)." ); $d = array( 'msgs' => $msgs, 'class' => 'msg-info', /* These msgs are template-authored HTML — the span IDs let the * progress-poll JS find bypassedCount / succCount / failCount and * update them in place. $action is clamped to 'enable'/'disable' by * MassEnableDisableProgressViewModel::__construct(), so no user data * is interpolated. */ 'rawHtml' => true, ); $this->loadTplBlock('DivMsgBox.tpl', $d); $d = array( 'back' => 'OK', 'visibility' => 'hidden' ); $this->loadTplBlock('ButtonPanelBackNext.tpl', $d); ?>
'errMsgs', 'class' => 'scrollable', ); $this->loadTplBlock('DivMsgBox.tpl', $d); ?>
'succMsgs', 'class' => 'scrollable', 'title' => 'Success Messages:', ); $this->loadTplBlock('DivMsgBox.tpl', $d); ?>
viewModel->getTplData(ViewModel::FLD_TITLE); $icon = $this->viewModel->getTplData(ViewModel::FLD_ICON); $totalCount = $this->viewModel->getTplData(ViewModel::FLD_TOTAL_COUNT); $mgrStep = $this->viewModel->getTplData(ViewModel::FLD_MGR_STEP); $d = array( 'title' => $title, 'icon' => $icon ); $this->loadTplBlock('Title.tpl', $d); ?>
Scanning 0 out of ...
Currently scanning known document roots for all WordPress Installations.
If performing a Scan/Re-scan, all installations will be found and added to the Cache Manager list.
If Discovering New, only installations belonging to users not already in the Cache Manager list will be discovered.

'Back', 'backDo' => 'lscwp_manage', 'visibility' => 'hidden' ); $this->loadTplBlock('ButtonPanelBackNext.tpl', $d); ?>
'errMsgs', 'class' => 'scrollable', ); $this->loadTplBlock('DivMsgBox.tpl', $d); ?>
PK!߭\\)webcachemgr/src/View/Tpl/DashNotifier.tplnuIwviewModel->getTplData(ViewModel::FLD_ICON_DIR); $discoveredCnt = $this->viewModel->getTplData(ViewModel::FLD_DISCOVERED_COUNT); $rapMsgIds = $this->viewModel->getTplData(ViewModel::FLD_RAP_MSG_IDS); $bamMsgIds = $this->viewModel->getTplData(ViewModel::FLD_BAM_MSG_IDS); /** * Close usual "lswsform" to allow the following page to have multiple forms * based on selected tab. */ echo ''; ?>

wp_dash_notifier_icon WordPress Dashboard Notification

This tool deploys and activates the WP Dash Notifier WordPress plugin on all of the server's WordPress installations.

'errMsgs', 'class' => 'scrollable', ); $this->loadTplBlock('DivMsgBox.tpl', $d); ?>
'succMsgs', 'class' => 'scrollable', ); $this->loadTplBlock('DivMsgBox.tpl', $d); ?>
  • Broadcast a notification message recommending a particular plugin, complete with an install/activate button for that plugin.

    On this page, a plugin can be recommended to all discovered WordPress installations by providing both the plugin's slug and a dashboard message. The following illustrates possible dashboard messages shown to WordPress users when recommending a plugin with plugin slug 'litespeed-cache' with a simple plain text message.

    1. User does not have the 'litespeed-cache' plugin installed
      recommend_new_plugin_img
    2. User has 'litespeed-cache' plugin installed, but deactivated
      recommend_disabled_plugin_img
    3. User has 'litespeed-cache' plugin installed and active
      * No message will be displayed

    Other Info

    • WordPress users who click the "Dismiss" button will not be re-notified if the provided dashboard message and plugin slug match those of the dismissed message.
    • WordPress users who click the "Never Notify Me Again" button will have the Dash Notifier plugin uninstalled and a '.dash_notifier_bypass' file created in their installation's root directory. These users will not be notified of any further messages while this file exists.
    • Plugin Slug
      WordPress Dashboard Message
    • Stored Messages
      Save As
    Use this option to test enabling/disabling notifications on a single WordPress installation by providing it's path.

    Specify a WordPress installation path
    Discovered WordPress installations ( Discovered )


  • Broadcast simple informational messages.

    On this page, a message can be sent to all discovered WordPress installations by providing a dashboard message. The following illustrates the dashboard messages shown to WordPress users when sending a simple plain text message.

    1. send_a_message_img

    Other Info

    • WordPress users who click the "Dismiss" button will not be re-notified if the provided dashboard message matches that of the last dismissed message.
    • WordPress users who click the "Never Notify Me Again" button will have the Dash Notifier plugin uninstalled and a '.dash_notifier_bypass' file created in their installation's root directory. These users will not be notified of any further messages while this file exists.
    • WordPress Dashboard Message
    • Stored Messages
      Save As
    Use this option to test enabling/disabling notifications on a single WordPress installation by providing it's path.

    Specify a WordPress installation path
    Discovered WordPress installations ( Discovered)



'Back' ); $this->loadTplBlock('ButtonPanelBackNext.tpl', $d); ?> PK!?ӛ,webcachemgr/src/View/Tpl/CacheRootNotSet.tplnuIw 'Cache Root Not Set', ); $this->loadTplBlock('Title.tpl', $d); ?>

Server and/or Virtual Host cache root has not yet been set. Please go to Cache Root Setup and set these first.

'Back' ); $this->loadTplBlock('ButtonPanelBackNext.tpl', $d); PK!@66#webcachemgr/src/View/Tpl/Manage.tplnuIwviewModel->getTplData(ViewModel::FLD_ICON_DIR); $scanBtnName = $this->viewModel->getTplData(ViewModel::FLD_SCAN_BTN_NAME); $btnState = $this->viewModel->getTplData(ViewModel::FLD_BTN_STATE); $activeVer = $this->viewModel->getTplData(ViewModel::FLD_ACTIVE_VER); $listData = $this->viewModel->getTplData(ViewModel::FLD_LIST_DATA); $countData = $this->viewModel->getTplData(ViewModel::FLD_COUNT_DATA); $showList = $this->viewModel->getTplData(ViewModel::FLD_SHOW_LIST); $warnMsgs = $this->viewModel->getTplData(ViewModel::FLD_WARN_MSGS); $infoMsgs = $this->viewModel->getTplData(ViewModel::FLD_INFO_MSGS); $errMsgs = $this->viewModel->getTplData(ViewModel::FLD_ERR_MSGS); $succMsgs = $this->viewModel->getTplData(ViewModel::FLD_SUCC_MSGS); ?>
loadTplBlock( 'Title.tpl', [ 'title' => 'Manage All LiteSpeed Cache for WordPress Installations', 'icon' => "$iconDir/manageCacheInstallations.svg" ] ); ?>
loadTplBlock( 'DivMsgBox.tpl', [ 'msgs' => $warnMsgs, 'class' => 'msg-warn' ] ); } if ( !empty($infoMsgs) ) { $this->loadTplBlock( 'DivMsgBox.tpl', [ 'msgs' => $infoMsgs, 'class' => 'msg-info' ] ); } $errMsgCnt = count($errMsgs); $succMsgCnt = count($succMsgs); ?>
loadTplBlock( 'DivMsgBox.tpl', [ 'id' => 'errMsgs', 'msgs' => $errMsgs, 'class' => 'scrollable' ] ); ?>
loadTplBlock( 'DivMsgBox.tpl', [ 'id' => 'succMsgs', 'msgs' => $succMsgs, 'class' => 'scrollable' ] ); ?>
loadTplBlock( 'InputSubmitBtn.tpl', [ 'name' => 're-scan', 'value' => $scanBtnName, 'title' => 'Scan filesystem for WordPress installations', 'confirm' => "$scanBtnName will scan your filesystem for WordPress " . 'installations. This may take up to a few minutes to complete. ' . "$scanBtnName now?", 'class' => "$classes $addClass" ], true ); if ( $btnState == 'disabled' ) { $addClass = 'disabled-btn'; } $this->loadTplBlock( 'InputSubmitBtn.tpl', [ 'name' => 'scan_more', 'value' => 'Discover New', 'title' => 'Discover new WordPress installations since the last scan', 'confirm' => 'Discover new WordPress installations since the last ' . 'scan. This will not update information for existing ' . 'installations. This may take up to a few minutes to complete. ' . 'Continue?', 'state' => $btnState, 'class' => "$classes $addClass", ], true ); $this->loadTplBlock( 'InputSubmitBtn.tpl', [ 'name' => 'refresh_status', 'value' => 'Refresh Status', 'title' => 'Check the cache status for all WordPress installations ' . 'currently listed', 'confirm' => 'Refresh Status will check the cache status for all ' . 'WordPress installations currently listed. If you have many ' . 'installations, this may take up to a few minutes to complete. ' . 'Refresh Status now?', 'state' => $btnState, 'class' => "$classes $addClass", ], true ); $this->loadTplBlock( 'InputSubmitBtn.tpl', [ 'name' => 'mass_flag', 'value' => 'Flag All', 'title' => 'Flag all currently discovered installations', 'confirm' => 'Flag all currently discovered installations?', 'state' => $btnState, 'class' => "$classes $addClass", ], true ); $this->loadTplBlock( 'InputSubmitBtn.tpl', [ 'name' => 'mass_unflag', 'value' => 'Unflag All', 'title' => 'Unflag all currently discovered installations', 'confirm' => 'Unflag all currently discovered installations?', 'state' => $btnState, 'class' => "$classes $addClass", ], true ); ?>
With Selected:
LiteSpeed Cache Plugin Version:

$info ): $statusData = $info['statusData']; $flagData = $info['flagData']; $siteUrl = $info['siteUrl']; $safePath = htmlspecialchars($path); ?>
Discovered WordPress Installations | Actions Cache Status Flag



*Flagging an installation will cause it to be excluded from Mass Enable/Disable operations.

PK!J}l0webcachemgr/src/Context/RootCLIContextOption.phpnuIwscanDepth = 2; $this->batchTimeout = 0; $this->batchSize = 0; } } PK!Q??0webcachemgr/src/Context/UserCLIContextOption.phpnuIwexpectedPermissions = self::IS_NOT_ROOT; $this->scanDepth = 2; $this->batchTimeout = 0; $this->batchSize = 0; $this->logFile = ''; } } PK!£v**#webcachemgr/src/Context/Context.phpnuIwoptions = $contextOption; $this->init(); } protected function init() { $this->dataDir = realpath(__DIR__ . '/../../../..') . '/admin/lscdata'; $this->dataFile = "$this->dataDir/lscm.data"; $this->customDataFile = "$this->dataDir/lscm.data.cust"; $this->isRoot = $this->options->isRoot(); } /** * * @since 1.9 * * @return void * * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by Logger::notice() call. * @throws LSCMException Thrown indirectly by Logger::notice() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. */ protected function checkLocalPluginDirInCageFS() { $mpFile = '/etc/cagefs/cagefs.mp'; $mountFile = '/proc/mounts'; $cagefsCtlFile = '/usr/sbin/cagefsctl'; if ( !file_exists($mpFile) || !file_exists($cagefsCtlFile) || !is_executable($cagefsCtlFile) ) { return; } Logger::debug('Detected cagefs.mp file.'); $localPluginDir = self::LOCAL_PLUGIN_DIR; $pattern = "=^((?!deleted).)*$localPluginDir((?!deleted).)*$=m"; $result = preg_grep($pattern, file($mountFile)); $procMountSet = !empty($result); if ( !$procMountSet ) { Logger::debug("Data dir not set in $mountFile."); $pattern = "=^.*$localPluginDir.*$=m"; $result = preg_grep($pattern, file($mpFile)); $setInMpFile = !empty($result); if ( !$setInMpFile ) { file_put_contents( $mpFile, "\n$localPluginDir", FILE_APPEND ); Logger::notice('Added data dir to cagefs.mp.'); } exec("$cagefsCtlFile --remount-all"); Logger::notice('Remounted CageFS.'); } else { Logger::debug('Data dir already added to CageFS.'); } } /** * * @throws LSCMException Thrown when unable to create data dir. */ protected function createDataDir() { if ( !file_exists($this->dataDir) && !mkdir($this->dataDir, 0755) ) { throw new LSCMException( "Fail to create data directory $this->dataDir.", LSCMException::E_PERMISSION ); } } /** * * @since 1.9 * * @throws LSCMException Thrown when unable to create local plugin dir. */ protected function createLocalPluginDir() { if ( !file_exists(Context::LOCAL_PLUGIN_DIR) && !mkdir(Context::LOCAL_PLUGIN_DIR, 0755) ) { throw new LSCMException( "Fail to create local plugin directory " . Context::LOCAL_PLUGIN_DIR . '.', LSCMException::E_PERMISSION ); } } /** * * @return ContextOption * * @throws LSCMException Thrown indirectly by self::me() call. */ public static function getOption() { return self::me(true)->options; } /** * * @since 1.9.1 Added optional parameter $loggerObj. * * @param ContextOption $contextOption * @param object $loggerObj Object implementing all public * Logger class functions. * * @throws LSCMException Thrown when Context is already initialized. * @throws LSCMException Thrown indirectly by Logger::setInstance() call. * @throws LSCMException Thrown indirectly by * self::$instance->createDataDir() call. * @throws LSCMException Thrown indirectly by * self::$instance->createLocalPluginDir() call. * @throws LSCMException Thrown indirectly by * self::$instance->checkLocalPluginDirInCageFS() call. */ public static function initialize( ContextOption $contextOption, $loggerObj = null ) { if ( self::$instance != null ) { /** * Do not allow, must initialize first. */ throw new LSCMException( 'Context cannot be initialized twice.', LSCMException::E_PROGRAM ); } self::$instance = new self($contextOption); if ( $loggerObj != null ) { Logger::setInstance($loggerObj); } else { $loggerClass = $contextOption->getLoggerClass(); $loggerClass::Initialize($contextOption); } if ( self::$instance->isRoot == ContextOption::IS_ROOT ) { self::$instance->createDataDir(); self::$instance->createLocalPluginDir(); self::$instance->checkLocalPluginDirInCageFS(); } } /** * Checks if the current instance is lacking the expected level of * permissions. * * @deprecated 1.17.8 * * @return bool * * @noinspection SpellCheckingInspection * @noinspection PhpUnused */ protected function hasInsufficentPermissions() { return $this->hasInsufficientPermissions(); } /** * Checks if the current instance is lacking the expected level of * permissions. * * @since 1.17.8 * * @return bool */ protected function hasInsufficientPermissions() { return ( self::$instance->isRoot < self::$instance->options->getExpectedPermissions() ); } /** * * @param bool $checkPerms * * @return Context * * @throws LSCMException Thrown when Context is not initialized. * @throws LSCMException Thrown when required permissions not met. */ protected static function me( $checkPerms = false ) { if ( self::$instance == null ) { /** * Do not allow, must initialize first. */ throw new LSCMException( 'Uninitialized context.', LSCMException::E_NON_FATAL ); } if ( $checkPerms && self::$instance->hasInsufficientPermissions() ) { throw new LSCMException( 'Access denied: Insufficient permissions.', LSCMException::E_NON_FATAL ); } return self::$instance; } /** * * @return string * * @throws LSCMException Thrown indirectly by self::me() call. */ public static function getLSCMDataDir() { return self::me()->dataDir; } /** * Deprecated 06/19/19. Shift to using getLSCMDataFiles() instead. * * @deprecated * * @return string * * @throws LSCMException Thrown indirectly by self::getLSCMDataFiles() * call. */ public static function getLSCMDataFile() { $dataFiles = self::getLSCMDataFiles(); return $dataFiles['dataFile']; } /** * * @return string[] * * @throws LSCMException Re-thrown when self::me() calls throw an * exception. * @throws LSCMException Thrown indirectly by Logger::debug() call. */ public static function getLSCMDataFiles() { try { $dataFile = self::me(true)->dataFile; $custDataFile = self::me(true)->customDataFile; } catch ( LSCMException $e ) { $msg = "{$e->getMessage()} Could not get data file paths."; Logger::debug($msg); throw new LSCMException($msg); } return array( 'dataFile' => $dataFile, 'custDataFile' => $custDataFile ); } /** * * @return int * * @throws LSCMException Thrown indirectly by self::me() call. */ public static function isRoot() { return self::me()->isRoot; } /** * * @return bool * * @throws LSCMException Thrown indirectly by self::me() call. */ public static function isPrivileged() { return (self::me()->isRoot > ContextOption::IS_NOT_ROOT); } /** * * @return int * * @throws LSCMException Thrown indirectly by self::me() call. */ public static function getScanDepth() { return self::me()->options->getScanDepth(); } /** * * @return int * * @throws LSCMException Thrown indirectly by self::me() call. */ public static function getActionTimeout() { $timeout = self::me()->options->getBatchTimeout(); if ( $timeout > 1 ) { return time() + $timeout; } /** * No timeout. */ return 0; } /** * * @return string * * @throws LSCMException Thrown indirectly by self::me() call. */ public static function getFlagFileContent() { $m = self::me(); if ( $m->flagContent == null ) { $m->flagContent = <<flagContent; } } PK!\$)webcachemgr/src/Context/ContextOption.phpnuIwinvokerName = $invokerName; $this->invokerType = $invokerType; $this->isRoot = $isRoot; $this->expectedPermissions = self::IS_ROOT; if ( $isRoot == self::IS_ROOT ) { $this->logFile = realpath(__DIR__ . '/../../../..') . '/logs/' . self::LOG_FILE_NAME; } $this->loggerClass = '\Lsc\Wp\Logger'; $this->lscwpVerClass ='\Lsc\Wp\PluginVersion'; $this->logFileLvl = $logFileLvl; $this->logEchoLvl = $logEchoLvl; $this->bufferedWrite = $bufferedWrite; $this->bufferedEcho = $bufferedEcho; } /** * * @return int */ public function isRoot() { return $this->isRoot; } /** * * @return int */ public function getExpectedPermissions() { return $this->expectedPermissions; } /** * * @return string */ public function getLoggerClass() { return $this->loggerClass; } /** * Returns the default log file path for this ContextOption. This can be * changed in the Logger class itself later on. * * @return string */ public function getDefaultLogFile() { return $this->logFile; } /** * * @return int */ public function getLogFileLvl() { return $this->logFileLvl; } /** * * @return int */ public function getLogEchoLvl() { return $this->logEchoLvl; } /** * * @return bool */ public function isBufferedWrite() { return $this->bufferedWrite; } /** * * @return bool */ public function isBufferedEcho() { return $this->bufferedEcho; } /** * * @return string */ public function getLscwpVerClass() { return $this->lscwpVerClass; } /** * * @return int */ public function getScanDepth() { return $this->scanDepth; } /** * * @return string */ public function getInvokerType() { return $this->invokerType; } /** * * @return string */ public function getInvokerName() { return $this->invokerName; } /** * * @return int */ public function getBatchSize() { return $this->batchSize; } /** * * @return int */ public function getBatchTimeout() { return $this->batchTimeout; } /** * * @param int $timeout * * @return int */ public function setBatchTimeout( $timeout ) { if ( is_int($timeout) ) { $this->batchTimeout = $timeout; } return $this->batchTimeout; } /** * * @param string $iconDir */ public function setIconDir( $iconDir ) { $this->iconDir = $iconDir; } /** * * @return string */ public function getIconDir() { return $this->iconDir; } /** * * @return string */ public function getSharedTplDir() { return $this->sharedTplDir; } } PK!vǒ2webcachemgr/src/Context/RootPanelContextOption.phpnuIwscanDepth = 2; $this->batchTimeout = 60; $this->batchSize = 10; $sharedTplDir = realpath(__DIR__ . '/../View/Tpl'); if ( !is_string($sharedTplDir) ) { $sharedTplDir = '/usr/local/lsws/add-ons/webcachemgr/src/View/Tpl'; } $this->sharedTplDir = $sharedTplDir; } } PK!Ď(( webcachemgr/src/DashNotifier.phpnuIw 86400 ) { try { $latestVer = self::getLatestVersion(); if ( Util::betterVersionCompare($latestVer, $localVer, '<') ) { self::downloadVersion($latestVer); } } catch ( LSCMException $e ) { Logger::error($e->getMessage()); } touch($dashVerFile); } } /** * * @since 1.9 * * @return string * * @throws LSCMException Thrown when unable to retrieve latest Dash * Notifier plugin version. */ public static function getLatestVersion() { $content = Util::get_url_contents( 'https://www.litespeedtech.com/packages/lswpcache/dash_latest' ); if ( empty($content) ) { throw new LSCMException( 'Could not retrieve latest Dash Notifier plugin version' ); } return trim($content); } /** * * @since 1.9 * * @param string $version * * @throws LSCMException Thrown indirectly by self::wgetPlugin() call. */ protected static function downloadVersion( $version ) { $pluginDir = Context::LOCAL_PLUGIN_DIR . '/' . self::PLUGIN_NAME; if ( file_exists($pluginDir) ) { exec('/bin/rm -rf ' . escapeshellarg($pluginDir)); } self::wgetPlugin($version, true); } /** * * @since 1.9 * * @param string $version * @param bool $saveMD5 * * @throws LSCMException Thrown when wget command fails to download * requested Dash Notifier plugin version. * @throws LSCMException Thrown when unable to unzip downloaded Dash * Notifier plugin package. * @throws LSCMException Thrown when downloaded Dash Notifier plugin * package is missing an expected file. * @throws LSCMException Thrown indirectly by Logger::info() call. * @throws LSCMException Thrown indirectly by Util::unzipFile() call. */ protected static function wgetPlugin( $version, $saveMD5 = false ) { Logger::info("Downloading Dash Notifier v$version..."); $zipFileName = self::PLUGIN_NAME . ".$version.zip"; $url = 'https://downloads.wordpress.org/plugin/' . $zipFileName; exec( "wget -q --tries=1 " . Util::getWgetCaArg() . escapeshellarg($url) . " -P " . escapeshellarg(Context::LOCAL_PLUGIN_DIR), $output, $return_var ); if ( $return_var !== 0 ) { throw new LSCMException( "Failed to download Dash Notifier v$version with wget exit " . "status $return_var.", LSCMException::E_NON_FATAL ); } $localZipFile = Context::LOCAL_PLUGIN_DIR . "/$zipFileName"; $extracted = Util::unzipFile($localZipFile, Context::LOCAL_PLUGIN_DIR); unlink($localZipFile); if ( ! $extracted ) { throw new LSCMException( "Unable to unzip $localZipFile", LSCMException::E_NON_FATAL ); } $pluginDir = Context::LOCAL_PLUGIN_DIR . '/' . self::PLUGIN_NAME; if ( ! file_exists("$pluginDir/" . self::PLUGIN_NAME . '.php') ) { throw new LSCMException( "Unable to download Dash Notifier v$version.", LSCMException::E_NON_FATAL ); } if ( $saveMD5 ) { file_put_contents( Context::LOCAL_PLUGIN_DIR . '/' . self::DASH_MD5, Util::DirectoryMd5($pluginDir) ); } file_put_contents( Context::LOCAL_PLUGIN_DIR . '/' . self::VER_FILE, $version ); } /** * Check if WordPress installation should be notified using the Dash * Notifier plugin. * * @param string $wpPath Root directory for WordPress installation. * * @return bool */ public static function canNotify( $wpPath ) { return !file_exists("$wpPath/" . self::BYPASS_FLAG); } /** * Checks the current installation for existing LSCWP plugin files and * copies them to the installation's plugins directory if not found. * This function should only be run as the user. * * @return bool True when new Dash Notifier plugin files are used. * * @throws LSCMException Thrown when unable to copy Dash Notifier plugin * files to WordPress plugin directory. * @throws LSCMException Thrown indirectly by Logger::debug() call. */ public static function prepareUserInstall() { $pluginDir = WpConstants::getWpConstant('WP_PLUGIN_DIR'); $dashNotifierPlugin = "$pluginDir/dash-notifier/dash-notifier.php"; if ( file_exists($dashNotifierPlugin) ) { /** * Existing installation detected. */ return false; } exec( '/bin/cp -rf ' . Context::LOCAL_PLUGIN_DIR . '/' . self::PLUGIN_NAME . ' ' . escapeshellarg($pluginDir) ); if ( !file_exists($dashNotifierPlugin) ) { throw new LSCMException( "Failed to copy Dash Notifier plugin files to $pluginDir.", LSCMException::E_NON_FATAL ); } Logger::debug( 'Copied Dash Notifier plugin files into plugins directory ' . $pluginDir ); return true; } /** * Activate Dash Notifier plugin if it is not already activated, and give * the plugin any notification data in the form of a JSON encoded array. * * @param string $jsonInfo Dash Notifier plugin info. * * @return bool * * @throws LSCMException Thrown when unable to find Dash Notifier plugin * files. */ public static function doNotify( $jsonInfo ) { if ( file_exists( WpConstants::getWpConstant('WP_PLUGIN_DIR') . '/' . self::DASH_PLUGIN ) ) { /** * Used to pass info to the Dash Notifier Plugin. */ Util::define_wrapper( 'DASH_NOTIFIER_MSG', $jsonInfo); if ( !WpFuncs::isPluginActive(self::DASH_PLUGIN) ) { /** * Should not check directly, can error on success due to object * cache. */ WpFuncs::activatePlugin(self::DASH_PLUGIN); if ( !WpFuncs::isPluginActive(self::DASH_PLUGIN) ) { return false; } } else { include WpConstants::getWpConstant('WP_PLUGIN_DIR') . '/' . self::DASH_PLUGIN; } } else { throw new LSCMException( 'Dash Notifier plugin files are missing. Cannot notify.', LSCMException::E_NON_FATAL ); } return true; } /** * * @param bool $uninstall */ public static function deactivate( $uninstall ) { WpFuncs::deactivatePlugins(self::DASH_PLUGIN); if ( $uninstall ) { //add some msg about having removed plugin files? WpFuncs::deletePlugins(array( self::DASH_PLUGIN )); } } } PK!ȥ#webcachemgr/src/PanelController.phpnuIwpanelEnv = $panelEnv; $this->wpInstallStorage = $wpInstallStorage; $this->mgrStep = $mgrStep; } /** * * @param string $type * * @return void|string[] */ protected function getCurrentAction( $type = 'cacheMgr' ) { switch ( $type ) { case 'dashNotifier': $all_actions = [ 'notify_single' => UserCommand::CMD_DASH_NOTIFY, 'disable_single' => UserCommand::CMD_DASH_DISABLE, 'get_msg' => WPDashMsgs::ACTION_GET_MSG, 'add_msg' => WPDashMsgs::ACTION_ADD_MSG, 'delete_msg' => WPDashMsgs::ACTION_DELETE_MSG ]; break; case 'cacheMgr': $all_actions = [ 'enable_single' => UserCommand::CMD_ENABLE, 'disable_single' => UserCommand::CMD_DISABLE, 'flag_single' => WPInstallStorage::CMD_FLAG, 'unflag_single' => WPInstallStorage::CMD_UNFLAG, 'refresh_status_single' => UserCommand::CMD_STATUS, 'enable_sel' => UserCommand::CMD_ENABLE, 'disable_sel' => UserCommand::CMD_DISABLE, 'flag_sel' => WPInstallStorage::CMD_FLAG, 'unflag_sel' => WPInstallStorage::CMD_UNFLAG ]; break; default: return; } foreach ( $all_actions as $act => $doAct ) { if ( Util::get_request_var($act) !== null ) { return [ 'act_key' => $act, 'action' => $doAct ]; } } } /** * * @deprecated * * @return int * * @throws LSCMException Thrown indirectly by * $this->manageCacheOperations() call. */ public function manageOperationsSubController() { return $this->manageCacheOperations(); } /** * SECURITY: Caller must have verified authentication and CSRF token before * invoking. See constructor docblock for full contract. * * @deprecated 1.13.3 Use $this->manageCacheOperations2() instead. * * @return int * * @throws LSCMException Thrown indirectly by $this->checkScanAction() * call. * @throws LSCMException Thrown indirectly by $this->checkRefreshAction() * call. * @throws LSCMException Thrown indirectly by $this->checkUnflagAction() * call. * @throws LSCMException Thrown indirectly by $this->doFormAction() call. * @throws LSCMException Thrown indirectly by $this->doSingleAction() call. */ public function manageCacheOperations() { if ( $this->checkScanAction() || $this->checkRefreshAction() || $this->checkFlagActions() || ($actionInfo = $this->getCurrentAction()) == NULL ) { return $this->mgrStep; } $actKey = $actionInfo['act_key']; $action = $actionInfo['action']; if ( strcmp(substr($actKey, -3), 'sel') == 0 ) { $this->doFormAction($action); } else { $this->doSingleAction($action, Util::get_request_var($actKey)); } return $this->mgrStep; } /** * SECURITY: Caller must have verified authentication and CSRF token before * invoking. See constructor docblock for full contract. * * @since 1.13.3 * * @return int * * @throws LSCMException Thrown indirectly by $this->checkScanAction2() * call. * @throws LSCMException Thrown indirectly by $this->checkRefreshAction() * call. * @throws LSCMException Thrown indirectly by $this->checkUnflagAction() * call. * @throws LSCMException Thrown indirectly by $this->doFormAction() call. * @throws LSCMException Thrown indirectly by $this->doSingleAction() call. */ public function manageCacheOperations2() { if ( $this->checkScanAction2() || $this->checkRefreshAction() || $this->checkFlagActions() || ($actionInfo = $this->getCurrentAction()) == NULL ) { return $this->mgrStep; } $actKey = $actionInfo['act_key']; $action = $actionInfo['action']; if ( strcmp(substr($actKey, -3), 'sel') == 0 ) { $this->doFormAction($action); } else { $path = Util::get_request_var($actKey); $this->doSingleAction($action, $path); } return $this->mgrStep; } /** * * @return string */ protected function getDashMsgInfoJSON() { $msgInfo = [ 'msg' => '', 'plugin' => '', 'plugin_name' => '' ]; if ( ($msg = Util::get_request_var('notify_msg')) !== NULL ) { $msgInfo['msg'] = trim($msg); } if ( ($slug = Util::get_request_var('notify_slug')) !== NULL ) { $msgInfo['plugin'] = trim($slug); } /** * plugin_name is not passed at this time. */ return json_encode($msgInfo); } /** * SECURITY: Caller must have verified authentication and CSRF token before * invoking. See constructor docblock for full contract. * * @param int $dashStep * @param WPDashMsgs $wpDashMsgs * * @return int * * @throws LSCMException Thrown indirectly by * $this->checkDashMassNotifyAction() call. * @throws LSCMException Thrown indirectly by * $this->checkDashMassDisableAction() call. * @throws LSCMException Thrown indirectly by $this->doWpDashMsgOperation() * call. * @throws LSCMException Thrown indirectly by $this->doSingleDashAction() * call. */ public function manageDashOperations( $dashStep, WPDashMsgs $wpDashMsgs ) { $this->dashStep = $dashStep; if ( $this->checkDashMassNotifyAction() || $this->checkDashMassDisableAction() || ($actionInfo = $this->getCurrentAction('dashNotifier')) == NULL ) { return $this->dashStep; } $actKey = $actionInfo['act_key']; $action = $actionInfo['action']; $msgInfoJSON = ''; if ( substr($action, 0, 3) == 'msg' ) { $this->doWpDashMsgOperation($wpDashMsgs, $action); } if ( $actKey == UserCommand::CMD_DASH_NOTIFY ) { $msgInfoJSON = base64_encode($this->getDashMsgInfoJSON()); } $this->doSingleDashAction( $action, Util::get_request_var($actKey), $msgInfoJSON ); return $this->dashStep; } /** * * @param array $array * * @return int * * @throws LSCMException Rethrown when Context::getOption() throws an * LSCMException exception. * @throws LSCMException Thrown indirectly by Logger::error() call. */ protected function getBatchSize( array $array ) { try { $batchSize = Context::getOption()->getBatchSize(); } catch ( LSCMException $e ) { $msg = "{$e->getMessage()} Could not get batch size."; Logger::error($msg); throw new LSCMException($msg); } if ( $batchSize > ($arrSize = count($array)) ) { return $arrSize; } return $batchSize; } /** * * @param object $viewModel * @param string $tplID * * @return string * * @throws LSCMException Thrown indirectly by Logger::error() call. */ protected function getAjaxViewContent( $viewModel, $tplID = '' ) { try { return (new AjaxView($viewModel))->getAjaxContent($tplID); } catch ( LSCMException $e ) { Logger::error($e->getMessage()); } return ''; } /** * * @deprecated 1.9 Moved to using AjaxResponse object for this. * * @param array $ajaxInfo */ protected function ajaxReturn( array $ajaxInfo ) { ob_clean(); echo json_encode($ajaxInfo); exit; } /** * * @deprecated 1.13.3 Use $this->checkScanAction2() instead. * * @return bool|void Function outputs ajax and exits without returning a * value when $init is evaluated to be false. * * @throws LSCMException Thrown indirectly by * $this->panelEnv->getDocroots() call. * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by $this->getBatchSize() call. * @throws LSCMException Thrown indirectly by * $this->wpInstallStorage->doAction() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by AjaxResponse::outputAndExit() * call. */ protected function checkScanAction() { $init = false; $action = ''; if ( $this->mgrStep == self::MGR_STEP_SCAN ) { $action = WPInstallStorage::CMD_SCAN; } elseif ( $this->mgrStep == self::MGR_STEP_DISCOVER_NEW ) { $action = WPInstallStorage::CMD_DISCOVER_NEW; } elseif ( Util::get_request_var('re-scan') ) { $this->mgrStep = self::MGR_STEP_SCAN; $init = true; } elseif ( Util::get_request_var('scan_more') ) { $this->mgrStep = self::MGR_STEP_DISCOVER_NEW; $init = true; } else { return false; } if ( session_status() !== PHP_SESSION_ACTIVE ) { session_start(); } $info = &$_SESSION['scanInfo']; if ( $init ) { $info = [ 'homeDirs' => $this->panelEnv->getDocroots() ]; return true; } $completedCount = -1; if ( !isset($info['homeDirs']) ) { Logger::uiError( 'Expected session data missing! Stopping mass operation.' ); } else { $batchSize = $this->getBatchSize($info['homeDirs']); $batch = array_splice($info['homeDirs'], 0, $batchSize); $completedCount = count( $this->wpInstallStorage->doAction( $action, $batch ) ); if ( $completedCount != $batchSize ) { $info['homeDirs'] = array_merge( array_slice($batch, $completedCount), $info['homeDirs'] ); } } if ( empty($info['homeDirs']) ) { unset($_SESSION['scanInfo']); } $msgs = $this->wpInstallStorage->getAllCmdMsgs(); AjaxResponse::setAjaxContent( json_encode( [ 'completed' => $completedCount, 'errMsgs' => array_merge( $msgs['fail'], $msgs['err'], Logger::getUiMsgs(Logger::UI_ERR) ) ] ) ); AjaxResponse::outputAndExit(); } /** * * @since 1.15 * * @param string[] $docroots * @param string[] $wpPaths Array of discovered WordPress installations * (passed by address). * * @return int Completed count. * * @throws LSCMException Thrown indirectly by WPInstallStorage->scan2() * call. */ protected function runScan2Logic( array $docroots, array &$wpPaths ) { foreach ( $docroots as $docroot ) { $wpPaths = array_merge( $wpPaths, WPInstallStorage::scan2($docroot) ); } return count($docroots); } /** * * @since 1.13.3 * * @return bool|void Function outputs ajax and exits without returning a * value when $init is evaluated to be false. * * @throws LSCMException Thrown indirectly by * $this->panelEnv->getDocroots() call. * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by $this->getBatchSize() call. * @throws LSCMException Thrown indirectly by $this->runScan2Logic() call. * @throws LSCMException Thrown indirectly by $this->getBatchSize() call. * @throws LSCMException Thrown indirectly by * $this->wpInstallStorage->doAction() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by AjaxResponse::outputAndExit() * call. */ protected function checkScanAction2() { $init = false; $action = ''; if ( $this->mgrStep == self::MGR_STEP_SCAN ) { $action = WPInstallStorage::CMD_SCAN2; } elseif ( $this->mgrStep == self::MGR_STEP_DISCOVER_NEW ) { $action = WPInstallStorage::CMD_DISCOVER_NEW2; } elseif ( Util::get_request_var('re-scan') ) { $this->mgrStep = self::MGR_STEP_SCAN; $init = true; } elseif ( Util::get_request_var('scan_more') ) { $this->mgrStep = self::MGR_STEP_DISCOVER_NEW; $init = true; } else { return false; } if ( session_status() !== PHP_SESSION_ACTIVE ) { session_start(); } if ( Util::get_request_var('go_to_next') == 1 ) { if ( isset($_SESSION['scanInfo']) && is_array($_SESSION['scanInfo']) && array_key_exists('homeDirs', $_SESSION['scanInfo']) && array_key_exists('installs', $_SESSION['scanInfo']) && ( is_array($_SESSION['scanInfo']['homeDirs']) || $_SESSION['scanInfo']['homeDirs'] === null ) && ( is_array($_SESSION['scanInfo']['installs']) || $_SESSION['scanInfo']['installs'] === null ) && !( $_SESSION['scanInfo']['homeDirs'] === null && $_SESSION['scanInfo']['installs'] === null ) ) { return true; } /* * Stale `go_to_next=1` request (e.g., browser Back / page Back * button replaying the URL after the scan-progress flow already * cleared $_SESSION['scanInfo']). Drop back to the regular * Manage view instead of constructing a scan-progress view with * no session data. */ return false; } $info = &$_SESSION['scanInfo']; if ( $init ) { $info = [ 'homeDirs' => $this->panelEnv->getDocroots(), 'installs' => [] ]; return true; } $scanStep = self::MGR_STEP_NONE; $errMsgs = []; $completedCount = -1; if ( !is_array($info) || !array_key_exists('homeDirs', $info) || !array_key_exists('installs', $info) ) { Logger::uiError( 'Expected session data missing! Stopping mass operation.' ); } else { if ( $info['homeDirs'] !== null ) { $scanStep = self::MGR_STEP_SCAN; $batchSize = $this->getBatchSize($info['homeDirs']); $batch = array_splice($info['homeDirs'], 0, $batchSize); $wpPaths = []; $completedCount = $this->runScan2Logic($batch, $wpPaths); if ( $completedCount != $batchSize ) { $info['homeDirs'] = array_merge( array_slice($batch, $completedCount), $info['homeDirs'] ); } if ( $action == WPInstallStorage::CMD_DISCOVER_NEW2 ) { foreach( $wpPaths as $wpPath ) { if ( $this->wpInstallStorage->getWPInstall($wpPath) == null) { $info['installs'][] = $wpPath; } } } else { $info['installs'] = array_merge($info['installs'], $wpPaths); } if ( empty($info['homeDirs']) ) { $info['homeDirs'] = null; if ( $action == WPInstallStorage::CMD_SCAN2 ) { $flippedInstalls = array_flip($info['installs']); $wpInstalls = $this->wpInstallStorage->getWPInstalls(); if ( $wpInstalls === null ) { $wpInstalls = []; } foreach ( $wpInstalls as $wpInstall ) { $wpInstallPath = $wpInstall->getPath(); if ( !isset($flippedInstalls[$wpInstallPath]) ) { $info['installs'][] = $wpInstallPath; } } } } } elseif ( $info['installs'] !== null ) { $scanStep = self::MGR_STEP_DISCOVER_NEW; $batchSize = $this->getBatchSize($info['installs']); $batch = array_splice($info['installs'], 0, $batchSize); $completedCount = count( $this->wpInstallStorage->doAction( WPInstallStorage::CMD_ADD_NEW_WPINSTALL, $batch ) ); if ( $completedCount != $batchSize ) { $info['installs'] = array_merge( array_slice($batch, $completedCount), $info['installs'] ); } $msgs = $this->wpInstallStorage->getAllCmdMsgs(); $errMsgs = array_merge($msgs['fail'], $msgs['err']); if ( empty($info['installs']) ) { $info['installs'] = null; } } if ( $info['homeDirs'] === null && $info['installs'] === null ) { unset($_SESSION['scanInfo']); } } AjaxResponse::setAjaxContent( json_encode( [ 'scanStep' => $scanStep, 'completed' => $completedCount, 'errMsgs' => array_merge( $errMsgs, Logger::getUiMsgs(Logger::UI_ERR) ) ] ) ); AjaxResponse::outputAndExit(); } /** * * @return bool|void Function outputs ajax and exits without returning a * value when $init is evaluated to be false. * * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by $this->getBatchSize() call. * @throws LSCMException Thrown indirectly by * $this->wpInstallStorage->doAction() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by AjaxResponse::outputAndExit() * call. */ protected function checkRefreshAction() { if ( $this->mgrStep == self::MGR_STEP_REFRESH_STATUS ) { $init = false; } elseif ( Util::get_request_var('refresh_status') ) { $init = true; $this->mgrStep = self::MGR_STEP_REFRESH_STATUS; } else { return false; } if ( session_status() !== PHP_SESSION_ACTIVE ) { session_start(); } $info = &$_SESSION['refreshInfo']; if ( $init ) { $info = [ 'installs' => $this->wpInstallStorage->getPaths() ]; return true; } $completedCount = -1; if ( !isset($info['installs']) ) { Logger::uiError( 'Expected session data missing! Stopping mass operation.' ); } else { $batchSize = $this->getBatchSize($info['installs']); $batch = array_splice($info['installs'], 0, $batchSize); $completedCount = count( $this->wpInstallStorage->doAction( UserCommand::CMD_STATUS, $batch ) ); if ( $completedCount != $batchSize ) { $info['installs'] = array_merge( array_slice($batch, $completedCount), $info['installs'] ); } } if ( empty($info['installs']) ) { unset($_SESSION['refreshInfo']); } $msgs = $this->wpInstallStorage->getAllCmdMsgs(); AjaxResponse::setAjaxContent( json_encode( [ 'completed' => $completedCount, 'errMsgs' => array_merge( $msgs['fail'], $msgs['err'], Logger::getUiMsgs(Logger::UI_ERR) ) ] ) ); AjaxResponse::outputAndExit(); } /** * * @return bool|void Function outputs ajax and exits without returning a * value when $init is evaluated to be false. * * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by $this->getBatchSize() call. * @throws LSCMException Thrown indirectly by * $this->wpInstallStorage->doAction() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by AjaxResponse::outputAndExit() * call. */ protected function checkUnflagAction() { if ( $this->mgrStep == self::MGR_STEP_MASS_UNFLAG ) { $init = false; } elseif ( Util::get_request_var('mass_unflag') ) { $init = true; $this->mgrStep = self::MGR_STEP_MASS_UNFLAG; } else { return false; } if ( session_status() !== PHP_SESSION_ACTIVE ) { session_start(); } $info = &$_SESSION['unflagInfo']; if ( $init ) { $info = [ 'installs' => $this->wpInstallStorage->getPaths() ]; return true; } $completedCount = -1; if ( !isset($info['installs']) ) { Logger::uiError( 'Expected session data missing! Stopping mass operation.' ); } else { $batchSize = $this->getBatchSize($info['installs']); $batch = array_splice($info['installs'], 0, $batchSize); $completedCount = count( $this->wpInstallStorage->doAction( WPInstallStorage::CMD_MASS_UNFLAG, $batch ) ); if ( $completedCount != $batchSize ) { $info['installs'] = array_merge( array_slice($batch, $completedCount), $info['installs'] ); } } if ( empty($info['installs']) ) { unset($_SESSION['unflagInfo']); } $msgs = $this->wpInstallStorage->getAllCmdMsgs(); AjaxResponse::setAjaxContent( json_encode( [ 'completed' => $completedCount, 'errMsgs' => array_merge( $msgs['fail'], $msgs['err'], Logger::getUiMsgs(Logger::UI_ERR) ), 'succMsgs' => array_merge( $msgs['succ'], Logger::getUiMsgs(Logger::UI_SUCC) ) ] ) ); AjaxResponse::outputAndExit(); } /** * * @return bool|void Function outputs ajax and exits without returning a * value when $init is evaluated to be false. * * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by $this->getBatchSize() call. * @throws LSCMException Thrown indirectly by * $this->wpInstallStorage->doAction() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by AjaxResponse::outputAndExit() * call. */ protected function checkFlagActions() { if ( $this->mgrStep == self::MGR_STEP_MASS_UNFLAG ) { $action = WPInstallStorage::CMD_MASS_UNFLAG; $init = false; } elseif ( $this->mgrStep == self::MGR_STEP_MASS_FLAG ) { $action = WPInstallStorage::CMD_MASS_FLAG; $init = false; } elseif ( Util::get_request_var('mass_unflag') ) { $action = WPInstallStorage::CMD_MASS_UNFLAG; $init = true; $this->mgrStep = self::MGR_STEP_MASS_UNFLAG; } elseif ( Util::get_request_var('mass_flag') ) { $action = WPInstallStorage::CMD_MASS_FLAG; $init = true; $this->mgrStep = self::MGR_STEP_MASS_FLAG; } else { return false; } if ( session_status() !== PHP_SESSION_ACTIVE ) { session_start(); } $info = &$_SESSION["{$action}_info"]; $doOld = false; if ( $action == WPInstallStorage::CMD_MASS_UNFLAG ) { /** * Set to maintain compatibility with old ViewModel + Tpl. * * @deprecated 1.17.4.2 */ $oldInfo = &$_SESSION['unflagInfo']; $doOld = true; } if ( $init ) { $info = [ 'installs' => $this->wpInstallStorage->getPaths() ]; if ( $doOld ) { $oldInfo = $info; } return true; } $completedCount = -1; if ( !isset($info['installs']) ) { Logger::uiError( 'Expected session data missing! Stopping mass operation.' ); } else { $batchSize = $this->getBatchSize($info['installs']); $batch = array_splice($info['installs'], 0, $batchSize); $completedCount = count( $this->wpInstallStorage->doAction($action, $batch) ); if ( $completedCount != $batchSize ) { $info['installs'] = array_merge( array_slice($batch, $completedCount), $info['installs'] ); } } if ( empty($info['installs']) ) { unset($_SESSION["{$action}_info"]); if ( $doOld ) { unset($_SESSION['unflagInfo']); } } elseif ( $doOld ) { $oldInfo = $info; } $msgs = $this->wpInstallStorage->getAllCmdMsgs(); AjaxResponse::setAjaxContent( json_encode( [ 'completed' => $completedCount, 'errMsgs' => array_merge( $msgs['fail'], $msgs['err'], Logger::getUiMsgs(Logger::UI_ERR) ), 'succMsgs' => array_merge( $msgs['succ'], Logger::getUiMsgs(Logger::UI_SUCC) ) ] ) ); AjaxResponse::outputAndExit(); } /** * * @param string $action * * @return void * * @throws LSCMException Rethrown when Context::getOption() throws an * LSCMException exception. * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by Logger::error() call. * @throws LSCMException Thrown indirectly by * $this->wpInstallStorage->doAction() call. */ protected function doFormAction( $action ) { $list = Util::get_request_list('installations'); /** * Empty list also checked earlier using JS. */ if ( $list == NULL ) { Logger::uiError('Please select at least one checkbox.'); return; } foreach ( $list as $wpPath ) { if ( $this->wpInstallStorage->getWPInstall($wpPath) === null ) { Logger::uiError( 'Invalid input value detected - No Action Taken' ); return; } } try { Context::getOption()->setBatchTimeout(0); } catch ( LSCMException $e ) { $msg = "{$e->getMessage()} Could not set batch timeout."; Logger::error($msg); throw new LSCMException($msg); } $this->wpInstallStorage->doAction($action, $list); } /** * Get simple string representations of current installation status. * * @param WPInstall $wpInstall * * @return string[] */ protected function getStatusStrings( WPInstall $wpInstall ) { $status = $wpInstall->getStatus(); if ( $status & WPInstall::ST_ERR_REMOVE ) { $statusString = 'removed'; } elseif ( $wpInstall->hasFatalError() ) { $statusString = 'error'; } elseif ( ($status & WPInstall::ST_PLUGIN_INACTIVE ) ) { $statusString = 'disabled'; } elseif ( !($status & WPInstall::ST_LSC_ADVCACHE_DEFINED) ) { $statusString = 'warning'; } else { $statusString = 'enabled'; } if ( $wpInstall->isFlagBitSet() ) { $flagString = 'flagged'; } else { $flagString = 'unflagged'; } return [ 'status' => $statusString, 'flag_status' => $flagString ]; } /** * * @param string $action * @param string $path * * @return void * * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by * $this->wpInstallStorage->doAction() call. * @throws LSCMException Thrown indirectly by $this->getAjaxViewContent() * call. * @throws LSCMException Thrown indirectly by $this->getAjaxViewContent() * call. * @throws LSCMException Thrown indirectly by $this->getAjaxViewContent() * call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by AjaxResponse::outputAndExit() * call. */ protected function doSingleAction( $action, $path ) { $wpInstall = $this->wpInstallStorage->getWPInstall($path); if ( $wpInstall === null ) { Logger::uiError('Invalid input value detected - No Action Taken'); return; } $preStatusInfo = $this->getStatusStrings($wpInstall); $this->wpInstallStorage->doAction($action, [ $path ]); $postStatusInfo = $this->getStatusStrings($wpInstall); $badgesDown = $badgesUp = []; $removed = false; if ( $postStatusInfo['status'] == 'removed' ) { $removed = true; $badgesDown[] = $preStatusInfo['status']; $badgesDown[] = 'flag'; } else { if ( $preStatusInfo['status'] != $postStatusInfo['status'] ) { $badgesDown[] = $preStatusInfo['status']; $badgesUp[] = $postStatusInfo['status']; } if ( $preStatusInfo['flag_status'] != $postStatusInfo['flag_status'] ) { if ( $postStatusInfo['flag_status'] == 'flagged' ) { $badgesUp[] = 'flag'; } else { $badgesDown[] = 'flag'; } } } $viewModel = new AjaxViewModel\CacheMgrRowViewModel($wpInstall); $statusSort = $viewModel->getsortVal('status'); $flagSort = $viewModel->getsortVal('flag'); switch ( $flagSort ) { case 'removed': $flagSearch = $flagSort; break; case 'flagged': $flagSearch = 'f'; break; default: $flagSearch = 'u'; } $msgs = $this->wpInstallStorage->getAllCmdMsgs(); AjaxResponse::setAjaxContent( json_encode( [ 'displayData' => [ 'actions_td' => $this->getAjaxViewContent($viewModel, 'actions_td'), 'status_search' => $statusSort, 'status_sort' => $statusSort, 'status_td' => $this->getAjaxViewContent($viewModel, 'status_td'), 'flag_search' => $flagSearch, 'flag_sort' => $flagSort, 'flag_td' => $this->getAjaxViewContent($viewModel, 'flag_td') ], 'badgesDown' => $badgesDown, 'badgesUp' => $badgesUp, 'removed' => $removed, 'errMsgs' => array_merge( $msgs['fail'], $msgs['err'], Logger::getUiMsgs(Logger::UI_ERR) ), 'succMsgs' => array_merge( $msgs['succ'], Logger::getUiMsgs(Logger::UI_SUCC) ) ] ) ); AjaxResponse::outputAndExit(); } /** * * @param WPDashMsgs $wpDashMsgs * @param string $action * * @throws LSCMException Thrown when parameter $action value is * unrecognized. * @throws LSCMException Thrown indirectly by AjaxResponse::outputAndExit() * call. */ protected function doWpDashMsgOperation( WPDashMsgs $wpDashMsgs, $action ) { if ( ($type = Util::get_request_var('msg_type')) !== NULL ) { $type = trim($type); } if ( ($msgId = Util::get_request_var('msg_id')) !== NULL ) { $msgId = trim($msgId); } switch ( $action ) { case WPDashMsgs::ACTION_GET_MSG: $msgs = $wpDashMsgs->getMsgData($type); $msgInfo = []; if ( $msgId !== '' && $msgId !== NULL && isset($msgs[$msgId]) ) { $msgInfo = $msgs[$msgId]; } $ajaxReturn = [ 'msgInfo' => $msgInfo ]; break; case WPDashMsgs::ACTION_ADD_MSG: if ( ($msg = Util::get_request_var('notify_msg')) !== NULL ) { $msg = trim($msg); } if ( ($slug = Util::get_request_var('notify_slug')) !== NULL ) { $slug = trim($slug); } $ret = 0; if ( $wpDashMsgs->addMsg($type, $msgId, $msg, $slug) ) { $ret = 1; } $ajaxReturn = [ 'ret' => $ret ]; break; case WPDashMsgs::ACTION_DELETE_MSG: $ajaxReturn = [ 'ret' => ($wpDashMsgs->deleteMsg($type, $msgId)) ? 1 : 0 ]; break; default: throw new LSCMException( 'PanelController->doWpDashMsgOperation(): Unrecognized ' . '$action value.' ); } AjaxResponse::setAjaxContent(json_encode($ajaxReturn)); AjaxResponse::outputAndExit(); } /** * * @param string $action * @param string $path * @param string $msgInfoJSON * * @throws LSCMException Thrown indirectly by AjaxResponse::outputAndExit() * call. * @throws LSCMException Thrown indirectly by * $this->wpInstallStorage->doAction() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by AjaxResponse::outputAndExit() * call. */ protected function doSingleDashAction( $action, $path, $msgInfoJSON = '' ) { if ( $this->wpInstallStorage->getWPInstall($path) === null ) { AjaxResponse::setAjaxContent( json_encode( [ 'errMsgs' => [ 'Invalid input value detected - Please use the ' . 'exact path displayed in the ' . '"Manage Cache Installations" list when ' . 'testing.' ], 'succMsgs' => [] ] ) ); AjaxResponse::outputAndExit(); } $this->wpInstallStorage->doAction($action, [ $path ], [ $msgInfoJSON ]); $msgs = $this->wpInstallStorage->getAllCmdMsgs(); AjaxResponse::setAjaxContent( json_encode( [ 'errMsgs' => array_merge( $msgs['fail'], $msgs['err'], Logger::getUiMsgs(Logger::UI_ERR) ), 'succMsgs' => array_merge( $msgs['succ'], Logger::getUiMsgs(Logger::UI_SUCC) ) ] ) ); AjaxResponse::outputAndExit(); } /** * * @param string $action * @param int $step * * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by $this->getBatchSize() call. * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by AjaxResponse::outputAndExit() * call. */ public function massEnableDisable( $action, $step ) { if ( session_status() !== PHP_SESSION_ACTIVE ) { session_start(); } $actionUpper = ucfirst($action); $info = &$_SESSION["mass{$actionUpper}Info"]; switch ( $step ) { case 1: $info = [ 'installs' => $this->wpInstallStorage->getPaths() ]; break; case 2: $completedCount = -1; $succCount = $failCount = $bypassedCount = 0; if ( !isset($info['installs']) ) { Logger::uiError( 'Expected session data missing! Stopping mass ' . 'operation.' ); } else { $batchSize = $this->getBatchSize($info['installs']); $batch = array_splice($info['installs'], 0, $batchSize); try { $finishedList = $this->wpInstallStorage->doAction( "mass_$action", $batch ); $completedCount = count($finishedList); if ( $completedCount != $batchSize ) { $info['installs'] = array_merge( array_slice($batch, $completedCount), $info['installs'] ); } } catch ( LSCMException $e ) { Logger::uiError( "{$e->getMessage()} Stopping mass operation." ); $finishedList = $info['installs'] = []; } $workingQueue = $this->wpInstallStorage->getWorkingQueue(); foreach ( $finishedList as $path ) { $wpInstall = $this->wpInstallStorage->getWPInstall($path); if ( isset($workingQueue[$path]) ) { $cmdStatus = $workingQueue[$path]->getCmdStatus(); } else { $cmdStatus = $wpInstall->getCmdStatus(); } if ( $cmdStatus & UserCommand::EXIT_INCR_SUCC ) { $succCount++; } elseif ( $cmdStatus & UserCommand::EXIT_INCR_FAIL ) { $failCount++; } elseif ( $cmdStatus & UserCommand::EXIT_INCR_BYPASS || $wpInstall->isFlagBitSet() ) { $bypassedCount++; } } } if ( empty($info['installs']) ) { unset($_SESSION["mass{$actionUpper}Info"]); } $msgs = $this->wpInstallStorage->getAllCmdMsgs(); AjaxResponse::setAjaxContent( json_encode( [ 'completed' => $completedCount, 'bypassedCount' => $bypassedCount, 'failCount' => $failCount, 'succCount' => $succCount, 'errMsgs' => array_merge( $msgs['fail'], $msgs['err'], Logger::getUiMsgs(Logger::UI_ERR) ), 'succMsgs' => array_merge( $msgs['succ'], Logger::getUiMsgs(Logger::UI_SUCC) ) ] ) ); AjaxResponse::outputAndExit(); break; // No default case } } /** * Force updates LiteSpeed Cache Plugins whose versions * match those in $verList and refreshes status as well. Flagged * installations are bypassed. * * @param int $step Value of 2 will prep session info, 3 will begin * changing installed LSCWP versions in batches. * * @return void * * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by $this->getBatchSize() call. * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by AjaxResponse::outputAndExit() * call. */ public function prepVersionChange( $step ) { if ( session_status() !== PHP_SESSION_ACTIVE ) { session_start(); } $info = &$_SESSION['verInfo']; switch ( $step ) { case 2: /** * init upgrade */ if ( empty( ($verList = Util::get_request_list('selectedVers')) ) ) { /** * Version list should not be empty */ return; } $info = [ 'installs' => $this->wpInstallStorage->getPaths(), 'verNum' => Util::get_request_var('version_num'), 'verList' => $verList ]; break; case 3: $completedCount = -1; if ( !isset($info['installs']) ) { Logger::uiError( 'Expected session data missing! Stopping mass ' . 'operation.' ); } else { $batchSize = $this->getBatchSize($info['installs']); $batch = array_splice($info['installs'], 0, $batchSize); try { $completedCount = count( $this->wpInstallStorage->doAction( UserCommand::CMD_MASS_UPGRADE, $batch, /** * 1 => "from versions" (comma seperated), * 2 => "to version" */ [ implode(',', $info['verList']), $info['verNum'] ] ) ); if ( $completedCount != $batchSize ) { $info['installs'] = array_merge( array_slice($batch, $completedCount), $info['installs'] ); } } catch ( LSCMException $e ) { Logger::uiError( "{$e->getMessage()} Stopping mass operation." ); $info['installs'] = []; } } if ( empty($info['installs']) || $completedCount == -1 ) { unset($_SESSION['verInfo']); } $msgs = $this->wpInstallStorage->getAllCmdMsgs(); AjaxResponse::setAjaxContent( json_encode( [ 'completed' => $completedCount, 'errMsgs' => array_merge( $msgs['fail'], $msgs['err'], Logger::getUiMsgs(Logger::UI_ERR) ) ] ) ); AjaxResponse::outputAndExit(); break; } } /** * * @return bool|void Function outputs ajax and exits without returning a * value when $init is evaluated to be false. * * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by $this->getBatchSize() call. * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by AjaxResponse::outputAndExit() * call. */ protected function checkDashMassNotifyAction() { if ( $this->dashStep == self::DASH_STEP_MASS_DASH_NOTIFY ) { $init = false; } elseif ( Util::get_request_var('mass-notify') ) { $init = true; $this->dashStep = self::DASH_STEP_MASS_DASH_NOTIFY; } else { return false; } if ( session_status() !== PHP_SESSION_ACTIVE ) { session_start(); } $info = &$_SESSION['massDashNotifyInfo']; if ( $init ) { $info = [ 'installs' => $this->wpInstallStorage->getPaths(), 'msgInfo' => base64_encode($this->getDashMsgInfoJSON()) ]; return true; } $completedCount = -1; $succCount = $failCount = $bypassedCount = 0; if ( !isset($info['installs']) ) { Logger::uiError( 'Expected session data missing! Stopping mass operation.' ); } else { $batchSize = $this->getBatchSize($info['installs']); $batch = array_splice($info['installs'], 0, $batchSize); try { $finishedList = $this->wpInstallStorage->doAction( UserCommand::CMD_MASS_DASH_NOTIFY, $batch, [ $info['msgInfo'] ] ); $completedCount = count($finishedList); if ( $completedCount != $batchSize ) { $info['installs'] = array_merge( array_slice($batch, $completedCount), $info['installs'] ); } } catch ( LSCMException $e ) { Logger::uiError("{$e->getMessage()} Stopping mass operation."); $finishedList = $info['installs'] = []; } $workingQueue = $this->wpInstallStorage->getWorkingQueue(); foreach ( $finishedList as $path ) { $wpInstall = $this->wpInstallStorage->getWPInstall($path); if ( isset($workingQueue[$path]) ) { $cmdStatus = $workingQueue[$path]->getCmdStatus(); } else { $cmdStatus = $wpInstall->getCmdStatus(); } if ( $cmdStatus & UserCommand::EXIT_INCR_SUCC ) { $succCount++; } elseif ( $cmdStatus & UserCommand::EXIT_INCR_FAIL ) { $failCount++; } elseif ( $cmdStatus & UserCommand::EXIT_INCR_BYPASS || $wpInstall->isFlagBitSet() ) { $bypassedCount++; } } } if ( empty($info['installs']) ) { unset($_SESSION['massDashNotifyInfo']); } $msgs = $this->wpInstallStorage->getAllCmdMsgs(); AjaxResponse::setAjaxContent( json_encode( [ 'completed' => $completedCount, 'bypassedCount' => $bypassedCount, 'failCount' => $failCount, 'succCount' => $succCount, 'errMsgs' => array_merge( $msgs['fail'], $msgs['err'], Logger::getUiMsgs(Logger::UI_ERR) ), 'succMsgs' => array_merge( $msgs['succ'], Logger::getUiMsgs(Logger::UI_SUCC) ) ] ) ); AjaxResponse::outputAndExit(); } /** * * @return bool|void Function outputs ajax and exits without returning a * value when $init is evaluated to be false. * * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by $this->getBatchSize() call. * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by Logger::getUiMsgs() call. * @throws LSCMException Thrown indirectly by AjaxResponse::outputAndExit() * call. */ protected function checkDashMassDisableAction() { if ( $this->dashStep == self::DASH_STEP_MASS_DASH_DISABLE ) { $init = false; } elseif ( Util::get_request_var('mass-disable-dash-notifier') ) { $init = true; $this->dashStep = self::DASH_STEP_MASS_DASH_DISABLE; } else { return false; } if ( session_status() !== PHP_SESSION_ACTIVE ) { session_start(); } $info = &$_SESSION['massDashDisableInfo']; if ( $init ) { $info = [ 'installs' => $this->wpInstallStorage->getPaths() ]; return true; } $completedCount = -1; $succCount = $failCount = $bypassedCount = 0; if ( !isset($info['installs']) ) { Logger::uiError( 'Expected session data missing! Stopping mass operation.' ); } else { $batchSize = $this->getBatchSize($info['installs']); $batch = array_splice($info['installs'], 0, $batchSize); try { $finishedList = $this->wpInstallStorage->doAction( UserCommand::CMD_MASS_DASH_DISABLE, $batch ); $completedCount = count($finishedList); if ( $completedCount != $batchSize ) { $info['installs'] = array_merge( array_slice($batch, $completedCount), $info['installs'] ); } } catch ( LSCMException $e ) { Logger::uiError("{$e->getMessage()} Stopping mass operation."); $finishedList = $info['installs'] = []; } $workingQueue = $this->wpInstallStorage->getWorkingQueue(); foreach ( $finishedList as $path ) { $wpInstall = $this->wpInstallStorage->getWPInstall($path); if ( isset($workingQueue[$path]) ) { $cmdStatus = $workingQueue[$path]->getCmdStatus(); } else { $cmdStatus = $wpInstall->getCmdStatus(); } if ( $cmdStatus & UserCommand::EXIT_INCR_SUCC ) { $succCount++; } elseif ( $cmdStatus & UserCommand::EXIT_INCR_FAIL ) { $failCount++; } elseif ( $cmdStatus & UserCommand::EXIT_INCR_BYPASS || $wpInstall->isFlagBitSet() ) { $bypassedCount++; } } } if ( empty($info['installs']) ) { unset($_SESSION['massDashDisableInfo']); } $msgs = $this->wpInstallStorage->getAllCmdMsgs(); AjaxResponse::setAjaxContent( json_encode( [ 'completed' => $completedCount, 'bypassedCount' => $bypassedCount, 'failCount' => $failCount, 'succCount' => $succCount, 'errMsgs' => array_merge( $msgs['fail'], $msgs['err'], Logger::getUiMsgs(Logger::UI_ERR) ), 'succMsgs' => array_merge( $msgs['succ'], Logger::getUiMsgs(Logger::UI_SUCC) ) ] ) ); AjaxResponse::outputAndExit(); } } PK!_webcachemgr/src/WPInstall.phpnuIwinit($path); } /** * * @param string $path */ protected function init( $path ) { if ( ($realPath = realpath($path)) === false ) { $this->path = $path; } else { $this->path = $realPath; } $this->data = array( self::FLD_STATUS => 0, self::FLD_DOCROOT => null, self::FLD_SERVERNAME => null, self::FLD_SITEURL => null, self::FLD_EXPECTED_OWNER_UID => null, self::FLD_EXPECTED_OWNER_GID => null, ); } /** * * @return string */ public function __toString() { if ( $this->data[self::FLD_SITEURL] ) { $siteUrl = Util::tryIdnToUtf8($this->data[self::FLD_SITEURL]); } else { $siteUrl = ''; } return sprintf( "%s (status=%d docroot=%s siteurl=%s)", $this->path, $this->data[self::FLD_STATUS], $this->data[self::FLD_DOCROOT], $siteUrl ); } /** * * @return string|null */ public function getDocRoot() { return $this->getData(self::FLD_DOCROOT); } /** * * @param string $docRoot * * @return bool */ public function setDocRoot( $docRoot ) { return $this->setData(self::FLD_DOCROOT, $docRoot); } /** * * @return string|null */ public function getServerName() { return $this->getData(self::FLD_SERVERNAME); } /** * * @param string $serverName * * @return bool */ public function setServerName( $serverName ) { return $this->setData( self::FLD_SERVERNAME, Util::tryIdnToAscii((string)$serverName) ); } /** * Note: Temporary function name until existing deprecated setSiteUrl() * function is removed. * * @param string $siteUrl * * @return bool */ public function setSiteUrlDirect( $siteUrl ) { return $this->setData( self::FLD_SITEURL, Util::tryIdnToAscii((string)$siteUrl) ); } /** * * @param int $status * * @return bool */ public function setStatus( $status ) { return $this->setData(self::FLD_STATUS, $status); } /** * * @return int */ public function getStatus() { return $this->getData(self::FLD_STATUS); } /** * * @param string $field * * @return mixed|null */ public function getData( $field = '' ) { if ( !$field ) { return $this->data; } if ( isset($this->data[$field]) ) { return $this->data[$field]; } /** * Error out */ return null; } /** * * @param string $field * @param mixed $value * * @return bool */ protected function setData( $field, $value ) { if ( $this->data[$field] !== $value ) { $this->changed = true; $this->data[$field] = $value; return true; } return false; } /** * Calling from unserialized data. * * @since 1.17.10 V9.1 — hydrate expectedOwnerUid/Gid from * FLD_EXPECTED_OWNER_UID/GID when present so Layer 2 (expected-owner * equality check) fires on data-file-loaded installs in the * root-context flag path. * * @param array $data */ public function initData( array $data ) { /** * V9.2 — initialize expected-owner keys that may be absent from * pre-V9.1 data-file records. setData() assumes every key in $field * exists in $this->data; without this guard, calling setExpectedOwner() * on a legacy-loaded install would trigger an undefined-index notice. */ if ( !array_key_exists(self::FLD_EXPECTED_OWNER_UID, $data) ) { $data[self::FLD_EXPECTED_OWNER_UID] = null; } if ( !array_key_exists(self::FLD_EXPECTED_OWNER_GID, $data) ) { $data[self::FLD_EXPECTED_OWNER_GID] = null; } $this->data = $data; if ( isset($data[self::FLD_EXPECTED_OWNER_UID]) ) { $this->expectedOwnerUid = (int) $data[self::FLD_EXPECTED_OWNER_UID]; } if ( isset($data[self::FLD_EXPECTED_OWNER_GID]) ) { $this->expectedOwnerGid = (int) $data[self::FLD_EXPECTED_OWNER_GID]; } } /** * * @return string */ public function getPath() { return $this->path; } /** * Bind the cPanel-assigned tenant uid/gid of the docroot ancestor that * canonically contained $this->path at scan time. Used by * addUserFlagFile() (root context) to fail-closed on cross-tenant * intermediate-directory symlink swaps: if the install-directory owner * at write time does not match the panel-assigned docroot owner captured * here, the privilege drop is refused. * * Called by WPInstallStorage::scan() after construction. The binding is * persisted via FLD_EXPECTED_OWNER_UID / FLD_EXPECTED_OWNER_GID so it * survives data-file serialization; initData() hydrates the in-memory * properties when the install is reloaded, making Layer 2 effective on * the data-file-loaded root-context flag path. * * Paths that were never run through scan() (bare new WPInstall() in * doWPInstallAction(), and the scan2/addNewWPInstall() path that loses * docroot context) still carry null and remain Layer-1/Layer-3 reliant. * * @since 1.17.10 * @since 1.17.10 V9.1 — now persisted via $data fields. * * @param int $uid lstat() uid of realpath(docroot). * @param int $gid lstat() gid of realpath(docroot). */ public function setExpectedOwner( $uid, $gid ) { $this->expectedOwnerUid = (int) $uid; $this->expectedOwnerGid = (int) $gid; $this->setData(self::FLD_EXPECTED_OWNER_UID, (int) $uid); $this->setData(self::FLD_EXPECTED_OWNER_GID, (int) $gid); } /** * * @return bool */ public function shouldRemove() { return (bool)(($this->getStatus() & self::ST_ERR_REMOVE)); } /** * * @return bool */ public function hasFlagFile() { return file_exists("$this->path/" . self::FLAG_FILE); } /** * * @return bool */ public function hasNewLscwpFlagFile() { return file_exists("$this->path/" . self::FLAG_NEW_LSCWP); } /** * * @return bool * * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by Logger::notice() call. * @throws LSCMException Thrown indirectly by $this->addUserFlagFile() * call. * @throws LSCMException Thrown indirectly by Logger::uiError() call. * @throws LSCMException Thrown indirectly by Logger::error() call. */ public function hasValidPath() { if ( !is_dir($this->path) || !is_dir("$this->path/wp-admin") ) { $this->setStatusBit(self::ST_ERR_REMOVE); $msg = "$this->path - Could not be found and has been removed from " . 'Cache Manager list.'; Logger::uiError($msg); Logger::notice($msg); return false; } if ( $this->getWpConfigFile() == null ) { $this->setStatusBit(self::ST_ERR_WPCONFIG); $this->addUserFlagFile(false); $msg = "$this->path - Could not find a valid wp-config.php file. " . 'Install has been flagged.'; Logger::uiError($msg); Logger::error($msg); return false; } return true; } /** * Set the provided status bit. * * @param int $bit */ public function setStatusBit( $bit ) { $this->setStatus(($this->getStatus() | $bit)); } /** * Unset the provided status bit. * * @param int $bit */ public function unsetStatusBit( $bit ) { $this->setStatus(($this->getStatus() & ~$bit )); } /** * * @deprecated 1.9.5 Deprecated to avoid confusion with $this->cmdStatus * and $this->cmdMsg related functions. Use $this->setStatus() instead. * * @param int $newStatus */ public function updateCommandStatus( $newStatus ) { $this->setData(self::FLD_STATUS, $newStatus); } /** * * @return null|string */ public function getWpConfigFile() { if ( $this->wpConfigFile === '' ) { $file = "$this->path/wp-config.php"; if ( !file_exists($file) ) { /** * check parent dir */ $parentDir = dirname($this->path); $file = "$parentDir/wp-config.php"; if ( !file_exists($file) || file_exists("$parentDir/wp-settings.php") ) { /** * If wp-config moved up, in same dir should NOT have * wp-settings */ $file = null; } } $this->wpConfigFile = $file; } return $this->wpConfigFile; } /** * Takes a WordPress site URL and uses it to populate serverName, siteUrl, * and docRoot data. If a matching docRoot cannot be found using the * serverName, the installation will be flagged and an ST_ERR_DOCROOT status * set. * * @param string $url * * @return bool * * @throws LSCMException Thrown indirectly by * ControlPanel::getClassInstance() call. * @throws LSCMException Thrown indirectly by * ControlPanel::getClassInstance()->mapDocRoot() call. * @throws LSCMException Thrown indirectly by $this->addUserFlagFile() * call. * @throws LSCMException Thrown indirectly by Logger::error() call. */ public function populateDataFromUrl( $url ) { /** @noinspection HttpUrlsUsage */ $parseSafeUrl = (preg_match('#^https?://#', $url)) ? $url : "http://$url"; $info = parse_url($parseSafeUrl); $serverName = isset($info['host']) ? Util::tryIdnToAscii($info['host']) : null; $this->setData(self::FLD_SERVERNAME, $serverName); $siteUrlTrim = $serverName; if ( isset($info['path']) ) { $siteUrlTrim .= $info['path']; } $this->setData(self::FLD_SITEURL, $siteUrlTrim); $docRoot = ControlPanel::getClassInstance()->mapDocRoot($serverName); $this->setData(self::FLD_DOCROOT, $docRoot); if ( $docRoot === null ) { $this->setStatus(self::ST_ERR_DOCROOT); $this->addUserFlagFile(false); $msg = "$this->path - Could not find matching document root for " . "WP siteurl/servername $serverName."; $this->setCmdStatusAndMsg(UserCommand::EXIT_ERROR, $msg); Logger::error($msg); return false; } return true; } /** * Deprecated 06/18/19. Renamed to populateDataFromUrl(). * * @deprecated * * @param string $siteUrl * * @return bool * * @throws LSCMException Thrown indirectly by $this->populateDataFromUrl() * call. */ public function setSiteUrl( $siteUrl ) { return $this->populateDataFromUrl($siteUrl); } /** * Adds the flag file to an installation. * * The flag file lives inside an installation directory that is owned and * writable by an untrusted account, yet this method may run as root (when * $runningAsUser is false). It is therefore hardened against symlink/TOCTOU * attacks (CWE-59 / CWE-367): * * When called as root ($runningAsUser === false): * Both the unlink and the fopen('xb') are performed after dropping * effective credentials to the install owner via dropPrivileges() (V8). * Writing as the filesystem owner of the directory closes the * intermediate-component TOCTOU: if a parent directory is swapped for a * symlink pointing at a root-owned location after the initial realpath(), * the tenant-credential write fails with EACCES because the tenant has * no write permission there. O_CREAT|O_EXCL ('xb') additionally protects * the final component. No lchown()/lchgrp() is required because the file * is created directly as the install owner. * * The uid/gid to drop to are read via lstat() (no final-symlink * following) so a tenant who replaces $this->path with a symlink * pointing at another tenant's directory gets that link's inode uid/gid, * not the target's uid/gid (cross-tenant impersonation). Additionally, * if lstat reveals the install path is now a symlink, execution fails * closed before any privilege manipulation. * * When called as the install owner ($runningAsUser === true): * Following an owner-planted symlink crosses no trust boundary (root is * not involved), so no privilege manipulation is needed. * * @since 1.17.10 — root-context path drops to install-owner * credentials (replaces path-based lchown/lchgrp, closes * intermediate-component TOCTOU that O_EXCL alone cannot address); * uid/gid read via lstat() to prevent cross-tenant impersonation via * a final-component symlink swap. * * @param bool $runningAsUser * * @return bool True when the flag file was created or already present; * false when the write failed or was refused (including Layer 2 * expected-owner mismatch, which logs and returns false without * aborting the batch). * * @throws LSCMException Thrown when unlink() call on preexisting flag file * fails. * @throws LSCMException Thrown when posix extension is unavailable in root * context (fail-closed; no acceptable fallback exists). * @throws LSCMException Thrown when any component of the install path is * a symlink (fail-closed; cross-tenant TOCTOU attack detected). * @throws LSCMException Thrown when the install path is no longer * accessible (fail-closed; possible TOCTOU attack). * @throws LSCMException Thrown when the install path has been replaced by * a symlink since the scan snapshot (fail-closed; TOCTOU attack * detected). * @throws LSCMException Thrown when the install path no longer * canonicalises to the same value as the scan-time snapshot * (fail-closed; TOCTOU attack detected). * @throws LSCMException Thrown when the install directory is owned by root * (fail-closed; privilege drop to root is not a privilege drop). * @throws LSCMException Thrown indirectly by * $this->restorePrivileges() call when credential restore fails * (process state is undefined; thrown from the finally block). * @throws LSCMException Thrown indirectly by Context::getFlagFileContent() * call. */ public function addUserFlagFile( $runningAsUser = true ) { $flagFile = "$this->path/" . self::FLAG_FILE; if ( !$runningAsUser ) { /** * V8 — root context: drop to install-owner credentials for both the * unlink and the create so that intermediate-directory symlink swaps * redirecting the path off-tree fail with EACCES rather than * succeeding silently. O_CREAT|O_EXCL ('xb') still guards the final * component. Privileges are restored in the finally block so an * exception cannot leave the process running as the tenant. * * V9 — three additional layers close the residual cross-tenant * intermediate-component swap gap: * 1. assertNoSymlinkComponents(): per-component lstat() walk that * refuses at the first symlink found in any directory component * of $this->path, closing the gap before any uid/gid read. * 2. realpath() re-verification: $this->path was set to the * canonical value at construct time; we re-canonicalise and * require equality. An intermediate swap that changes the * canonical resolution is caught here even if Layer 1 misses it. * 3. Expected-owner check: the uid/gid reported by lstat() at * write time is compared against the panel-assigned docroot * owner captured at scan time. A swap that redirects the path * to another tenant's tree produces a mismatched uid even if * Layers 1 and 2 fail to fire. * * V9.8 — validation logic extracted into resolveValidatedFlagOwnerUidGid() * so that the identical trust-boundary checks are shared with the * root-context removeFlagFile(false) path and cannot drift. */ $owner = $this->resolveValidatedFlagOwnerUidGid('flag-file write'); if ( $owner === false ) { return false; } list($uid, $gid) = $owner; $origEuid = posix_geteuid(); $origEgid = posix_getegid(); try { $this->dropPrivileges($uid, $gid); if ( !$this->writeFlagFileExclusive($flagFile) ) { return false; } } finally { $this->restorePrivileges($origEuid, $origEgid); } } else { /** * Running as the install owner — no privilege boundary to enforce. */ if ( !$this->writeFlagFileExclusive($flagFile) ) { return false; } } $this->setStatusBit(self::ST_FLAGGED); return true; } /** * Shared root-context path and owner validation for flag-file mutation. * * Performs, in order: * 1. POSIX availability check. * 2. Per-component lstat() walk (V9 Layer 1). * 3. Final lstat($this->path) with inaccessibility and symlink checks. * 4. realpath() re-verification (V9 Layer 3). * 5. Expected-owner comparison when bound (V9 Layer 2). * 6. Root-owner refusal. * * Three-way return contract (intentional — do not collapse into two): * - Hard failure (symlink component, inaccessible path, canonical drift, * root owner, posix unavailable) → throw LSCMException. The caller * must not catch and continue; the operation is aborted. * - Expected-owner mismatch (V9 Layer 2) → return false. The mismatch * is already logged via Logger::error() here so the caller just * propagates false without re-logging. This is a per-install soft * failure so a batch can continue to the next install. Do NOT turn * this into a throw without auditing every batch call site. * - Success → return array($uid, $gid) for caller to pass to * dropPrivileges(). * * @since 1.17.10 * * @param string $context Human-readable label (e.g. 'flag-file write') * used in exception and log messages. * * @return array|false array($uid, $gid) on success; false on expected- * owner mismatch (already logged). * * @throws LSCMException When posix functions are unavailable. * @throws LSCMException When any path component is a symlink. * @throws LSCMException When the install path is inaccessible. * @throws LSCMException When the install path is a symlink. * @throws LSCMException When realpath() diverges from the stored path. * @throws LSCMException When the install directory is root-owned. */ private function resolveValidatedFlagOwnerUidGid( $context ) { $this->checkPosixAvailability($context); $this->assertNoSymlinkComponents(); clearstatcache(true, $this->path); $lstat = lstat($this->path); if ( $lstat === false ) { throw new LSCMException( "Refusing $context: install path is no longer accessible " . '(possible TOCTOU attack).' ); } if ( is_link($this->path) ) { throw new LSCMException( "Refusing $context: install path has been replaced with a " . 'symlink since the scan snapshot (TOCTOU attack detected).' ); } $recanon = realpath($this->path); if ( $recanon === false || $recanon !== $this->path ) { throw new LSCMException( "Refusing $context: install path no longer canonicalises to " . 'the stored snapshot (TOCTOU attack detected).' ); } $uid = (int)$lstat['uid']; $gid = (int)$lstat['gid']; if ( $this->expectedOwnerUid !== null && ( $uid !== $this->expectedOwnerUid || $gid !== $this->expectedOwnerGid ) ) { /** * Soft fail-closed: log and return false so the batch can continue * to the next install. The security guarantee is identical to a * throw (the mutation is refused), but a throw would abort the * entire batch rather than just this install. */ Logger::error( "$this->path - Refusing $context: install directory owner " . "(uid=$uid gid=$gid) does not match the expected owner " . 'captured at scan time ' . "(uid={$this->expectedOwnerUid} " . "gid={$this->expectedOwnerGid}); " . 'possible cross-tenant TOCTOU attack.' ); return false; } if ( $uid === 0 || $gid === 0 ) { throw new LSCMException( "Refusing $context: install directory owner resolves to root " . '(uid=0 or gid=0); privilege drop would be a no-op.' ); } return array($uid, $gid); } /** * Walk every directory component of $this->path top-down using lstat() and * throw if any component is a symlink. Because the walk refuses at the * first symlink found, no later lstat() call in the walk can be misled by * an earlier swapped component (lstat() still resolves intermediate * components before the final stat). * * This is the closest emulation of openat(AT_SYMLINK_NOFOLLOW) available * in pure PHP: it catches intermediate-directory symlink swaps (e.g. * tenant replaces public_html with a symlink into another user's tree) * before any uid/gid read is performed. * * @since 1.17.10 * * @throws LSCMException When $this->path is not an absolute path. * @throws LSCMException When any path component cannot be stat'd. * @throws LSCMException When any path component is a symlink. */ private function assertNoSymlinkComponents() { if ( $this->path === '' || $this->path[0] !== '/' ) { throw new LSCMException( 'Refusing flag-file write: install path is not absolute ' . '(possible TOCTOU attack).' ); } $parts = explode('/', $this->path); $prefix = ''; foreach ( $parts as $part ) { if ( $part === '' ) { continue; } $prefix .= "/$part"; clearstatcache(true, $prefix); if ( lstat($prefix) === false ) { throw new LSCMException( "Refusing flag-file write: path component $prefix is no " . 'longer accessible (possible TOCTOU attack).' ); } if ( is_link($prefix) ) { throw new LSCMException( "Refusing flag-file write: path component $prefix is a " . 'symlink (cross-tenant TOCTOU attack detected).' ); } } } /** * Fail-closed guard: throw if any posix function required for privilege * drop/restore is not available in this PHP build. * * @since 1.17.10 * * @param string $context Human-readable label used in the exception message. * * @throws LSCMException */ private function checkPosixAvailability( $context ) { $required = array( 'posix_seteuid', 'posix_setegid', 'posix_geteuid', 'posix_getegid', 'posix_initgroups', 'posix_getpwuid', ); foreach ( $required as $fn ) { if ( !function_exists($fn) ) { throw new LSCMException( "posix extension (function $fn) required for " . "privilege-drop $context is not available." ); } } } /** * Remove any preexisting flag file node (symlink or regular), then create a * new one with O_CREAT|O_EXCL ('xb') semantics and write the flag content. * * Called under whatever effective credentials the caller has arranged. * is_link() catches dangling symlinks that file_exists() reports as absent. * * @since 1.17.10 * * @param string $flagFile Absolute path to the flag file. * * @return bool False when fopen or fwrite fails (caller should propagate). * * @throws LSCMException When unlink() of a preexisting node fails. * @throws LSCMException Thrown indirectly by Context::getFlagFileContent() * call. */ private function writeFlagFileExclusive( $flagFile ) { if ( is_link($flagFile) || file_exists($flagFile) ) { if ( !unlink($flagFile) ) { throw new LSCMException( 'Failed to remove preexisting untrusted flag file.' ); } } $flagFileContent = Context::getFlagFileContent(); $fh = @fopen($flagFile, 'xb'); if ( $fh === false ) { return false; } if ( fwrite($fh, $flagFileContent) === false ) { fclose($fh); @unlink($flagFile); return false; } fclose($fh); return true; } /** * Remove any flag file node (symlink or regular file) under whatever * effective credentials the caller has arranged. * * is_link() catches dangling symlinks that file_exists() reports as absent. * Mirrors the node-removal preamble of writeFlagFileExclusive() so that * the root-context removal path uses the same defensive node-type checks as * the creation path. * * @since 1.17.10 * * @param string $flagFile Absolute path to the flag file. * * @return bool False when unlink() fails; true when the node was absent or * successfully removed. */ private function removeFlagFileNode( $flagFile ) { if ( is_link($flagFile) || file_exists($flagFile) ) { if ( !unlink($flagFile) ) { return false; } } return true; } /** * Drop process credentials to ($uid, $gid) for a scoped root-context * operation inside an untrusted tenant directory. * * Order: posix_initgroups() → posix_setegid() → posix_seteuid(). * initgroups() must precede seteuid() because only root can replace * supplementary groups; setegid() must precede seteuid() because once * euid is non-root the process cannot change its gid. * Non-root callers skip the initgroups step (only root holds dangerous * supplementary groups, and only root has CAP_SETGID to call initgroups). * * @since 1.17.10 * * @param int $uid Tenant effective uid. * @param int $gid Tenant effective gid. * * @throws LSCMException Thrown when uid cannot be resolved to a username * for the supplementary-group reset (only in root context). * @throws LSCMException Thrown when posix_initgroups() fails to replace * the supplementary group set (only in root context). * @throws LSCMException Thrown when posix_setegid()/posix_seteuid() fail * to lower the effective gid/uid. */ private function dropPrivileges( $uid, $gid ) { if ( posix_geteuid() === 0 ) { $pw = posix_getpwuid($uid); if ( $pw === false ) { throw new LSCMException( "Failed to look up username for uid $uid during privilege drop." ); } if ( !posix_initgroups($pw['name'], $gid) ) { throw new LSCMException( 'Failed to replace supplementary groups during privilege drop.' ); } } if ( !posix_setegid($gid) || !posix_seteuid($uid) ) { throw new LSCMException( 'Failed to drop effective uid/gid during privilege drop.' ); } } /** * Restore process credentials to root after a dropPrivileges() scope. * Must always be called inside a finally block. * * Restore order: seteuid(root) → setegid(root) → initgroups('root'). * * posix_seteuid(0) can only fail if the real uid is not 0 — i.e., if this * method is called outside of a root process, which is a programming error. * Throwing here is correct: the calling process is in an undefined state * and must not continue operating as the tenant. * * @since 1.17.10 * * @param int $origEuid Saved euid from before dropPrivileges(). * @param int $origEgid Saved egid from before dropPrivileges(). * * @throws LSCMException Thrown when posix_seteuid()/posix_setegid() fail * to restore effective uid/gid (indicates process is in an undefined * state and must not continue). * @throws LSCMException Thrown when posix_initgroups() fails to restore * the supplementary group set (indicates process is in an undefined * state and must not continue). */ private function restorePrivileges( $origEuid, $origEgid ) { if ( !posix_seteuid($origEuid) || !posix_setegid($origEgid) ) { throw new LSCMException( 'Failed to restore effective uid/gid after privilege drop; ' . 'process state is undefined.' ); } if ( $origEuid === 0 ) { if ( !posix_initgroups('root', $origEgid) ) { throw new LSCMException( 'Failed to restore supplementary groups after privilege drop; ' . 'process state is undefined.' ); } } } /** * Remove the flag file from this install. * * When $runningAsUser is false (root context) the same V9 trust-boundary * checks as addUserFlagFile(false) are applied via * resolveValidatedFlagOwnerUidGid() before dropping privileges for the * removal: per-component lstat() walk, realpath() re-verification, * expected-owner comparison, and root-owner refusal. This closes the * cross-tenant TOCTOU gap for the deletion path that was present before * V9.8. * * @since 1.17.10 — root-context path ($runningAsUser=false) * applies the same V9 owner-binding and symlink-walk guards as * addUserFlagFile(false), then drops to install-owner credentials for * the unlink. * * @param bool $runningAsUser * * @return bool True when the flag file was absent or successfully removed; * false when the removal failed or was refused (including expected-owner * mismatch, which logs and returns false without aborting the batch). * * @throws LSCMException When posix extension is unavailable in root context. * @throws LSCMException When any component of the install path is a symlink. * @throws LSCMException When the install path is no longer accessible. * @throws LSCMException When the install path has been replaced by a symlink. * @throws LSCMException When realpath() diverges from the stored snapshot. * @throws LSCMException When the install directory is owned by root. * @throws LSCMException Thrown indirectly by restorePrivileges() when * credential restore fails (process state is undefined; thrown from * the finally block). */ public function removeFlagFile( $runningAsUser = true ) { $flagFile = "$this->path/" . self::FLAG_FILE; if ( !$runningAsUser ) { $owner = $this->resolveValidatedFlagOwnerUidGid('flag-file removal'); if ( $owner === false ) { return false; } list($uid, $gid) = $owner; $origEuid = posix_geteuid(); $origEgid = posix_getegid(); try { $this->dropPrivileges($uid, $gid); if ( !$this->removeFlagFileNode($flagFile) ) { return false; } } finally { $this->restorePrivileges($origEuid, $origEgid); } } else { if ( file_exists($flagFile) ) { if ( !unlink($flagFile) ) { return false; } } } $this->unsetStatusBit(self::ST_FLAGGED); return true; } /** * Add a flag file to indicate that a new LSCWP plugin was added to this * installation. * * This function should only be called by the installation owner to avoid * permission problems involving this file. * * @return bool */ public function addNewLscwpFlagFile() { $file = "$this->path/" . self::FLAG_NEW_LSCWP; if ( !file_exists($file) ) { if ( !file_put_contents($file, '') ) { return false; } } return true; } /** * Remove "In Progress" flag file to indicate that a WPInstall action has * been completed. * * @return bool */ public function removeNewLscwpFlagFile() { $file = "$this->path/" . self::FLAG_NEW_LSCWP; if ( file_exists($file) ) { if ( !unlink($file) ) { return false; } } return true; } /** * * @param bool $forced * * @return int * * @throws LSCMException Thrown indirectly by UserCommand::issue() call. */ public function refreshStatus( $forced = false ) { if ( !$this->refreshed || $forced ) { UserCommand::issue(UserCommand::CMD_STATUS, $this); $this->refreshed = true; } return $this->getData(self::FLD_STATUS); } /** * * @param string $pluginDir * * @throws LSCMException Thrown indirectly by Logger::debug() call. */ public function removePluginFiles( $pluginDir ) { if ( !is_string($pluginDir) || $pluginDir === '' || $pluginDir === '/' || $pluginDir[0] !== '/' || in_array('..', explode('/', $pluginDir), true) ) { Logger::debug( "$this->path - Refusing to remove plugin files: unsafe path." ); return; } if ( !file_exists($pluginDir) && !is_link($pluginDir) ) { return; } if ( is_link($pluginDir) ) { /** * Plugin directory is a symlink. Remove the symlink node only; do * NOT resolve it via realpath() + rm -rf, which would recursively * delete the target directory (potentially outside wp-content/). */ if ( @unlink($pluginDir) ) { Logger::debug( "$this->path - Removed LSCache for WordPress plugin " . 'symlink from plugins directory' ); } else { Logger::debug( "$this->path - Failed to remove LSCache for WordPress " . 'plugin symlink from plugins directory' ); } return; } exec('rm -rf ' . escapeshellarg($pluginDir)); Logger::debug( "$this->path - Removed LSCache for WordPress plugin files from " . 'plugins directory' ); } /** * * @return bool */ public function isFlagBitSet() { if ( ($this->getStatus() & self::ST_FLAGGED) ) { return true; } return false; } /** * * @param null|int $status * * @return bool */ public function hasFatalError( $status = null ) { if ( $status === null ) { $status = $this->getData(self::FLD_STATUS); } $errMask = ( self::ST_ERR_EXECMD | self::ST_ERR_EXECMD_DB | self::ST_ERR_TIMEOUT | self::ST_ERR_SITEURL | self::ST_ERR_DOCROOT | self::ST_ERR_WPCONFIG ); return (($status & $errMask) > 0); } /** * * @since 1.17.10 * * @return PhpBinaryParts * * @throws LSCMException Thrown indirectly by * ControlPanel::getClassInstance() call. * @throws LSCMException Thrown indirectly by * ControlPanel::getClassInstance()->getPhpBinaryParts() call. */ public function getPhpBinaryParts() { if ( $this->phpBinaryParts === null ) { $this->phpBinaryParts = ControlPanel::getClassInstance()->getPhpBinaryParts($this); } return $this->phpBinaryParts; } /** * @deprecated since 1.17.10 Call getPhpBinaryParts() instead. * * @return string * * @throws LSCMException Thrown indirectly by getPhpBinaryParts() call. */ public function getPhpBinary() { if ( $this->phpBinary === null ) { $parts = $this->getPhpBinaryParts(); $options = $parts->getOptionsString(); $this->phpBinary = $options === '' ? $parts->getBinPath() : $parts->getBinPath() . ' ' . $options; } return $this->phpBinary; } /** * Returns requested owner info. * * @param string $field Key ('user_id', 'user_name', or 'group_id') in the * $ownerInfo array. * * @return array|int|string|null */ public function getOwnerInfo( $field = '' ) { if ( $this->ownerInfo == null ) { $this->ownerInfo = Util::populateOwnerInfo($this->path); } if ( $field == '' ) { return $this->ownerInfo; } elseif ( isset($this->ownerInfo[$field]) ) { return $this->ownerInfo[$field]; } return null; } /** * * @return string */ public function getSuCmd() { if ( $this->suCmd == null ) { $userName = (string)$this->getOwnerInfo('user_name'); $this->suCmd = 'su ' . escapeshellarg($userName) . ' -s /bin/bash'; } return $this->suCmd; } /** * * @return int */ public function getCmdStatus() { return $this->cmdStatus; } /** * * @return string */ public function getCmdMsg() { return $this->cmdMsg; } public function setCmdStatusAndMsg( $status, $msg ) { $this->cmdStatus = $status; $this->cmdMsg = $msg; } } PK!ڻ__!webcachemgr/src/PluginVersion.phpnuIwshortVersions. * @var string[] */ protected $knownVersions = []; /** * @since 4.1.3 * @var string[] */ protected $shortVersions = []; /** * @var string[] */ protected $allowedVersions = array(); /** * @var string */ protected $currVersion = ''; /** * @var string */ protected $versionFile; /** * @var string */ protected $activeFile; /** * @var null|PluginVersion */ protected static $instance; /** * * @throws LSCMException Thrown indirectly by $this->init() call. */ protected function __construct() { $this->init(); } /** * * @throws LSCMException Thrown indirectly by Context::isPrivileged() call. * @throws LSCMException Thrown indirectly by $this->refreshVersionList() * call. */ protected function init() { $this->setVersionFiles(); if ( Context::isPrivileged() ) { $this->refreshVersionList(); } } /** * * @return PluginVersion * * @throws LSCMException Thrown indirectly by Context::getOption() call. */ public static function getInstance() { if ( self::$instance == null ) { $className = Context::getOption()->getLscwpVerClass(); self::$instance = new $className(); } return self::$instance; } /** * * @deprecated 4.1.3 Use "$formatted = true" equivalent function * $this->getShortVersions() instead. Un-formatted version of this list * will no longer be available once this function is removed. * * @param bool $formatted * * @return string[] * * @throws LSCMException Thrown indirectly by $this->setKnownVersions() * call. */ public function getKnownVersions( $formatted = false ) { if ( empty($this->knownVersions) ) { $this->setKnownVersions(); } if ( $formatted ) { $knownVers = $this->knownVersions; $prevVer = ''; foreach ( $knownVers as &$ver ) { if ( $prevVer !== '' ) { $ver1 = explode('.', $prevVer); $ver2 = explode('.', $ver); if ( $ver1[0] !== $ver2[0] || $ver1[1] !== $ver2[1] ) { $ver = "$ver2[0].$ver2[1].x"; } } $prevVer = $ver; } return $knownVers; } return $this->knownVersions; } /** * * @return string[] * * @throws LSCMException Thrown indirectly by $this->setAllowedVersions() * call. */ public function getAllowedVersions() { if ( empty($this->allowedVersions) ) { $this->setAllowedVersions(); } return $this->allowedVersions; } /** * * @since 4.1.3 * * @return string[] * * @throws LSCMException Thrown indirectly by $this->setShortVersions() * call. */ public function getShortVersions() { if ( empty($this->shortVersions) ) { $this->setShortVersions(); } return $this->shortVersions; } /** * * @return string * * @throws LSCMException Thrown indirectly by $this->getAllowedVersions() * call. */ public function getLatestVersion() { $allowedVers = $this->getAllowedVersions(); return (isset($allowedVers[0])) ? $allowedVers[0] : ''; } /** * * @return string * * @throws LSCMException Thrown indirectly by self::getInstance() call. * @throws LSCMException Thrown indirectly by * $instance->setCurrentVersion() call. */ public static function getCurrentVersion() { $instance = self::getInstance(); if ( $instance->currVersion == '' ) { $instance->setCurrentVersion(); } return $instance->currVersion; } /** * * @since 1.9 */ protected function createDownloadDir() { mkdir(Context::LOCAL_PLUGIN_DIR, 0755); } protected function setVersionFiles() { $this->versionFile = Context::LOCAL_PLUGIN_DIR . '/lscwp_versions_v2'; $this->activeFile = Context::LOCAL_PLUGIN_DIR . '/lscwp_active_version'; } /** * Temporary function for handling the active version file and versions * file move in the short term. * * @deprecated 1.9 * @since 1.9 * * @throws LSCMException Thrown indirectly by Context::getLSCMDataDir() * call. */ protected function checkOldVersionFiles() { $dataDir = Context::getLSCMDataDir(); $oldActiveFile = "$dataDir/lscwp_active_version"; if ( file_exists($oldActiveFile) ) { if ( !file_exists(Context::LOCAL_PLUGIN_DIR) ) { $this->createDownloadDir(); } rename($oldActiveFile, $this->activeFile); unlink("$dataDir/lscwp_versions"); } } /** * * @throws LSCMException Thrown indirectly by $this->checkOldVersionFiles() * call. * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. */ public function setCurrentVersion() { $this->checkOldVersionFiles(); if ( ($activeVersion = $this->getActiveVersion()) == '' ) { Logger::debug('Active LSCWP version not found.'); } elseif ( ! $this->hasDownloadedVersion($activeVersion) ) { $activeVersion = ''; unlink($this->activeFile); Logger::debug('Valid LSCWP download not found.'); } if ( $activeVersion == '' ) { try { $activeVersion = self::getLatestVersion(); } catch ( LSCMException $e ) { Logger::debug($e->getMessage()); } } $this->currVersion = $activeVersion; } /** * * @since 1.11 * * @return string */ private function getActiveVersion() { if ( file_exists($this->activeFile) && ($content = file_get_contents($this->activeFile)) ) { return trim($content); } return ''; } /** * * @deprecated 4.1.3 This function will be removed in favor of * pre-formatted $this->setShortVersions(). * * @throws LSCMException Thrown when LSCWP version list cannot be found. * @throws LSCMException Thrown when read LSCWP version list command fails. * @throws LSCMException Thrown when match against LSCWP version list * content fails. */ protected function setKnownVersions() { if ( !file_exists($this->versionFile) ) { throw new LSCMException( 'Cannot find LSCWP version list.', LSCMException::E_NON_FATAL ); } if ( ($content = file_get_contents($this->versionFile)) === false ) { throw new LSCMException( 'Failed to read LSCWP version list content.', LSCMException::E_NON_FATAL ); } if ( preg_match('/old\s{(.*)}/sU', trim($content), $m) != 1 ) { throw new LSCMException( 'Failed to get known versions from LSCWP version list content.', LSCMException::E_NON_FATAL ); } $this->knownVersions = explode("\n", trim($m[1])); } /** * * @throws LSCMException Thrown when LSCWP version list cannot be found. * @throws LSCMException Thrown when read LSCWP version list command fails. * @throws LSCMException Thrown when LSCWP version list content is empty. */ protected function setAllowedVersions() { if ( !file_exists($this->versionFile) ) { throw new LSCMException( 'Cannot find LSCWP version list.', LSCMException::E_NON_FATAL ); } if ( ($content = file_get_contents($this->versionFile)) === false ) { throw new LSCMException( 'Failed to read LSCWP version list content.', LSCMException::E_NON_FATAL ); } if ( !preg_match('/allowed\s{(.*)}/sU', trim($content), $m) || ($list = trim($m[1])) == '' ) { throw new LSCMException( 'LSCWP version list is empty.', LSCMException::E_NON_FATAL ); } $this->allowedVersions = explode("\n", $list); } /** * * @since 4.1.3 * * @throws LSCMException Thrown when LSCWP version list cannot be found. * @throws LSCMException Thrown when read LSCWP version list command fails. * @throws LSCMException Thrown when LSCWP version list content is empty. */ protected function setShortVersions() { if ( !file_exists($this->versionFile) ) { throw new LSCMException( 'Cannot find LSCWP version list.', LSCMException::E_NON_FATAL ); } if ( ($content = file_get_contents($this->versionFile)) === false ) { throw new LSCMException( 'Failed to read LSCWP version list content.', LSCMException::E_NON_FATAL ); } if ( !preg_match('/short\s{(.*)}/sU', trim($content), $m) || ($list = trim($m[1])) == '' ) { throw new LSCMException( 'LSCWP version list is empty.', LSCMException::E_NON_FATAL ); } $this->shortVersions = explode("\n", $list); } /** * * @param string $version Valid LSCWP version. * @param bool $init True when trying to set initial active version. * * @throws LSCMException Thrown indirectly by $this->getAllowedVersions() * call. * @throws LSCMException Thrown indirectly by Logger::error() call. * @throws LSCMException Thrown indirectly by $this->downloadVersion() * call. * @throws LSCMException Thrown indirectly by Logger::notice() call. */ public function setActiveVersion( $version, $init = false ) { $allowedVers = $this->getAllowedVersions(); if ( in_array($version, $allowedVers) ) { $activeVer = $version; } else { try { $currVer = ($init) ? '' : $this->getCurrentVersion(); } catch ( LSCMException $e ) { $currVer = ''; } if ( $currVer != '' ) { $activeVer = $currVer; } else { $activeVer = $allowedVers[0]; } Logger::error( "Version $version not in allowed list, reset active " . "version to $activeVer." ); } if ( $activeVer != $this->getActiveVersion() ) { if ( !$this->hasDownloadedVersion($activeVer) ) { $this->downloadVersion($activeVer); } $this->currVersion = $activeVer; file_put_contents($this->activeFile, $activeVer); Logger::notice("Current active LSCWP version is now $activeVer."); } } /** * * @param bool $isForced * * @throws LSCMException Thrown indirectly by Logger::info() call. */ protected function refreshVersionList( $isForced = false ) { clearstatcache(); if ( $isForced || !file_exists($this->versionFile) || (time() - filemtime($this->versionFile)) > 86400 ) { if ( !file_exists(Context::LOCAL_PLUGIN_DIR) ) { $this->createDownloadDir(); } $url = 'https://www.litespeedtech.com/packages/lswpcache' . '/version_list_v2'; $content = Util::get_url_contents($url); if ( empty($content) || substr($content, 0, 7) != 'allowed' ) { /** * Try again using cli curl directly to bypass potential * reCAPTCHA issues. */ $content = Util::getUrlContentsUsingExecCurl($url); if ( empty($content) || substr($content, 0, 7) != 'allowed' ) { touch($this->versionFile); return; } } file_put_contents($this->versionFile, $content); Logger::info('LSCache for WordPress version list updated'); } } /** * Filter out any versionList versions that do not meet specific criteria. * * @deprecated 4.1.3 No longer used. * * @param string $ver Version string. * * @return bool */ protected function filterVerList( $ver ) { return Util::betterVersionCompare($ver, '1.2.2', '>'); } /** * * @since 1.17.5 * * @param string $pluginDir The WordPress plugin directory. */ public static function tryCopyLscwpDefaultConf( $pluginDir ) { foreach ( [ self::LSCWP_DEFAULTS_INI_FILE_NAME, self::LSCWP_DEFAULTS_JSON_FILE_NAME ] as $customConfFileName ) { $customConfFilePath = Context::LOCAL_PLUGIN_DIR . "/$customConfFileName"; if ( file_exists($customConfFilePath) ) { copy( $customConfFilePath, "$pluginDir/litespeed-cache/data/$customConfFileName" ); } } } /** * Checks the current installation for existing LSCWP plugin files and * copies them to the installation's plugins directory if not found. * This function should only be run as the user. * * @param string $pluginDir The WordPress plugin directory. * @param string $version The version of LSCWP to be used when copying * over plugin files. * * @return bool True when new LSCWP plugin files are used. * * @throws LSCMException Thrown when LSCWP source package is not available * for the provided version. * @throws LSCMException Thrown when LSCWP plugin files could not be copied * to plugin directory. * @throws LSCMException Thrown indirectly by self::getInstance() call. * @throws LSCMException Thrown indirectly by * $instance->getCurrentVersion() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. */ public static function prepareUserInstall( $pluginDir, $version = '' ) { $lscwp_plugin = "$pluginDir/litespeed-cache/litespeed-cache.php"; if ( file_exists($lscwp_plugin) ) { /** * Existing installation detected. */ return false; } $instance = self::getInstance(); if ( $version == '' ) { $version = $instance->getCurrentVersion(); } if ( !$instance->hasDownloadedVersion($version) ) { throw new LSCMException( "Source Package not available for version $version.", LSCMException::E_NON_FATAL ); } exec( '/bin/cp --preserve=mode -rf ' . Context::LOCAL_PLUGIN_DIR . "/$version/" . self::PLUGIN_NAME . ' ' . escapeshellarg($pluginDir) ); if ( !file_exists($lscwp_plugin) ) { throw new LSCMException( "Failed to copy plugin files to $pluginDir.", LSCMException::E_NON_FATAL ); } self::tryCopyLscwpDefaultConf($pluginDir); Logger::debug( 'Copied LSCache for WordPress plugin files into plugins directory ' . $pluginDir ); return true; } /** * * @param string $version * * @return bool */ protected function hasDownloadedVersion( $version ) { $dir = Context::LOCAL_PLUGIN_DIR . "/$version"; $md5file = "$dir/" . self::VER_MD5; $plugin = "$dir/" . self::PLUGIN_NAME; if ( !file_exists($md5file) || !is_dir($plugin) ) { return false; } return (file_get_contents($md5file) == Util::DirectoryMd5($plugin)); } /** * * @param string $version * @param string $dir * @param bool $saveMD5 * * @throws LSCMException Thrown when wget command for downloaded LSCWP * version fails. * @throws LSCMException Thrown when unable to unzip LSCWP zip file. * @throws LSCMException Thrown when unzipped LSCWP files do not contain * expected test file. * @throws LSCMException Thrown indirectly by Logger::info() call. * @throws LSCMException Thrown indirectly by Util::unzipFile() call. */ protected function wgetPlugin( $version, $dir, $saveMD5 = false ) { if ( !self::isValidPluginVersion($version) ) { throw new LSCMException( "Invalid LSCWP version $version.", LSCMException::E_NON_FATAL ); } Logger::info("Downloading LSCache for WordPress v$version..."); $zipFile = self::PLUGIN_NAME . ".$version.zip"; $url = "https://downloads.wordpress.org/plugin/$zipFile"; exec( 'wget -q --tries=1 ' . escapeshellarg($url) . ' -P ' . escapeshellarg($dir), $output, $return_var ); if ( $return_var !== 0 ) { throw new LSCMException( "Failed to download LSCWP v$version with wget exit status " . "$return_var.", LSCMException::E_NON_FATAL ); } $localZipFile = "$dir/$zipFile"; $extractedZip = Util::unzipFile($localZipFile, $dir); unlink($localZipFile); if ( !$extractedZip ) { throw new LSCMException( "Unable to unzip $localZipFile", LSCMException::E_NON_FATAL ); } $plugin = "$dir/" . self::PLUGIN_NAME; if ( !file_exists("$plugin/" . self::PLUGIN_NAME . '.php') ) { throw new LSCMException( "Test file not found. Downloaded LSCWP v$version is invalid.", LSCMException::E_NON_FATAL ); } if ( $saveMD5 ) { file_put_contents( "$dir/" . self::VER_MD5, Util::DirectoryMd5($plugin) ); } } /** * * @param string $version * * @throws LSCMException Thrown when download dir could not be created. * @throws LSCMException Thrown indirectly by $this->wgetPlugin() call. */ protected function downloadVersion( $version ) { if ( !self::isValidPluginVersion($version) ) { throw new LSCMException( "Invalid LSCWP version $version.", LSCMException::E_NON_FATAL ); } $dir = Context::LOCAL_PLUGIN_DIR . "/$version"; if ( !file_exists($dir) ) { if ( !mkdir($dir, 0755, true) ) { throw new LSCMException( "Failed to create download dir $dir.", LSCMException::E_NON_FATAL ); } } else { exec('/bin/rm -rf ' . escapeshellarg($dir) . '/*'); } $this->wgetPlugin($version, $dir, true); } /** * * @param string $locale * @param string $pluginVer * * @return bool * * @throws LSCMException Thrown indirectly by Logger::info() call. * @throws LSCMException Thrown indirectly by Util::unzipFile() call. */ public static function retrieveTranslation( $locale, $pluginVer ) { if ( !self::isValidLocale($locale) || !self::isValidPluginVersion($pluginVer) ) { return false; } Logger::info( "Downloading LSCache for WordPress $locale translation..." ); $translationDir = Context::LOCAL_PLUGIN_DIR . "/$pluginVer/translations"; if ( !file_exists($translationDir) ) { mkdir($translationDir, 0755); } touch( "$translationDir/" . self::TRANSLATION_CHECK_FLAG_BASE . "_$locale" ); /** * downloads.wordpress.org looks to always return a '200 OK' status, * even when serving a 404 page. As such invalid downloads can only be * checked through user failure to unzip through WP func unzip_file() * as we do not assume that root has the ability to unzip. */ $url = 'https://downloads.wordpress.org/translation/plugin/' . "litespeed-cache/$pluginVer/$locale.zip"; exec( 'wget -q --tries=1 ' . escapeshellarg($url) . ' -P ' . escapeshellarg($translationDir), $output, $return_var ); if ( $return_var !== 0 ) { return false; } /** * The WordPress user can unzip for us if this call fails. */ Util::unzipFile("$translationDir/$locale.zip", $translationDir); return true; } /** * * @param string $locale * @param string $pluginVer * * @throws LSCMException Thrown indirectly by Logger::info() call. */ public static function removeTranslationZip( $locale, $pluginVer ) { if ( !self::isValidLocale($locale) || !self::isValidPluginVersion($pluginVer) ) { return; } Logger::info("Removing LSCache for WordPress $locale translation..."); $zipFile = realpath( Context::LOCAL_PLUGIN_DIR . "/$pluginVer/translations/$locale.zip" ); if ( substr($zipFile, 0, strlen(Context::LOCAL_PLUGIN_DIR)) === Context::LOCAL_PLUGIN_DIR ) { unlink($zipFile); } } /** * @param string $locale * @return bool */ private static function isValidLocale( $locale ) { return is_string($locale) && preg_match('/\A[A-Za-z0-9_]{1,32}\z/', $locale); } /** * @param string $version * @return bool */ private static function isValidPluginVersion( $version ) { return is_string($version) && preg_match('/\A[0-9]+(?:\.[0-9]+){0,5}\z/', $version); } } PK!YV0w0wwebcachemgr/src/UserCommand.phpnuIwasUser = $asUser) ) { require_once __DIR__ . '/../autoloader.php'; date_default_timezone_set('UTC'); Context::initialize(new UserCLIContextOption('userCommand')); } } /** * Handles logging unexpected error output (or not if too long) and returns * a crafted message to be displayed instead. * * @param WPInstall $wpInstall WordPress Installation object. * @param string $err Compiled error message. * @param int $lines Number of $output lines read into the error * msg. * * @return string Message to be displayed instead. * * @throws LSCMException Thrown indirectly by Logger::error() call. * @throws LSCMException Thrown indirectly by Logger::error() call. */ private static function handleUnexpectedError( WPInstall $wpInstall, $err, $lines ) { $msg = 'Unexpected Error Encountered!'; $path = $wpInstall->getPath(); /** * $lines > 500 are likely some custom code triggering a page render. * Throw out actual message in this case. */ if ( $lines < 500 ) { $match = false; $commonErrs = array( WPInstall::ST_ERR_EXECMD_DB => 'Error establishing a database connection' ); foreach ( $commonErrs as $statusBit => $commonErr ) { if ( strpos($err, $commonErr) !== false ) { $wpInstall->unsetStatusBit(WPInstall::ST_ERR_EXECMD); $wpInstall->setStatusBit($statusBit); $msg .= " $commonErr."; $match = true; break; } } if ( !$match ) { Logger::error("$path - $err"); return "$msg See " . ContextOption::LOG_FILE_NAME . " for more information."; } } Logger::error("$path - $msg"); return $msg; } /** * Parse out locale and plugin version information from issue() result * output GET_TRANSLATION or BAD_TRANSLATION line. * * @since 1.14 * * @param string $line * * @return string[] */ private static function parseTranslationLocaleAndPluginVer( $line ) { list($locale, $pluginVer) = explode(' ', $line); return array( 'locale' => $locale, 'pluginVer' => $pluginVer ); } /** * * @since 1.9 * * @param WPInstall $wpInstall * @param string $output * * @throws LSCMException Thrown indirectly by * PluginVersion::retrieveTranslation() call. * @throws LSCMException Thrown indirectly by self::subCommandIssue() call. * @throws LSCMException Thrown indirectly by * PluginVersion::removeTranslationZip() call. */ private static function handleGetTranslationOutput( WPInstall $wpInstall, $output ) { $translationInfo = self::parseTranslationLocaleAndPluginVer($output); $translationRetrieved = PluginVersion::retrieveTranslation( $translationInfo['locale'], $translationInfo['pluginVer'] ); if ( $translationRetrieved ) { $subOutput = self::subCommandIssue(self::CMD_UPDATE_TRANSLATION, $wpInstall); foreach ( $subOutput as $subLine ) { if ( preg_match('/BAD_TRANSLATION=(.+)/', $subLine, $m) ) { $badTranslationInfo = self::parseTranslationLocaleAndPluginVer($m[1]); PluginVersion::removeTranslationZip( $badTranslationInfo['locale'], $badTranslationInfo['pluginVer'] ); } } } } /** * * @since 1.9 * * @param WPInstall $wpInstall * @param string $line * @param int $retStatus * @param int $cmdStatus * @param string $err * * @return bool * * @throws LSCMException Thrown indirectly by * $wpInstall->populateDataFromUrl() call. * @throws LSCMException Thrown indirectly by * self::handleGetTranslationOutput() call. */ private static function handleResultOutput( WPInstall $wpInstall, $line, &$retStatus, &$cmdStatus, &$err ) { if ( preg_match('/SITEURL=(.+)/', $line, $m) ) { if ( !$wpInstall->populateDataFromUrl($m[1]) ) { /** * Matching docroot could not be found, ignore other * output. setCmdStatusAndMsg() etc already handled in * setSiteUrl(). */ return false; } } elseif ( preg_match('/STATUS=(.+)/', $line, $m) ) { $retStatus = (int)$m[1]; } elseif ( preg_match('/MASS_INCR=(.+)/', $line, $m) ) { if ( $m[1] == 'SUCC' ) { $cmdStatus |= UserCommand::EXIT_INCR_SUCC; } elseif ( $m[1] == 'FAIL' ) { $cmdStatus |= UserCommand::EXIT_INCR_FAIL; } elseif ( $m[1] === 'BYPASS' ) { $cmdStatus |= UserCommand::EXIT_INCR_BYPASS; } } elseif ( preg_match('/GET_TRANSLATION=(.+)/', $line, $m) ) { self::handleGetTranslationOutput($wpInstall, $m[1]); } else { $err .= "Unexpected result line: $line\n"; } return true; } /** * * @since 1.9 * * @param WPInstall $wpInstall * * @throws LSCMException Thrown indirectly by self::subCommandIssue() call. */ private static function removeLeftoverLscwpFiles( WPInstall $wpInstall ) { self::subCommandIssue(self::CMD_REMOVE_LSCWP_PLUGIN_FILES, $wpInstall); $wpInstall->removeNewLscwpFlagFile(); } /** * * @param string $action * @param WPInstall $wpInstall * @param array $extraArgs * * @return string * * @throws LSCMException Thrown indirectly by $wpInstall->getPhpBinary() * call. * @throws LSCMException Thrown indirectly by Context::getOption() call. */ protected static function getIssueCmd( $action, WPInstall $wpInstall, array $extraArgs = array() ) { $su = $wpInstall->getSuCmd(); $timeout = ControlPanel::PHP_TIMEOUT; $parts = $wpInstall->getPhpBinaryParts(); $phpBinPath = $parts->getBinPath(); $phpOptions = $parts->getOptionsString(); $path = $wpInstall->getPath(); $serverName = $wpInstall->getData(WPInstall::FLD_SERVERNAME); $env = Context::getOption()->getInvokerName(); $docRoot = $wpInstall->getData(WPInstall::FLD_DOCROOT); if ( $docRoot === null || trim((string)$docRoot) === '' ) { $docRoot = 'x'; } if ( $serverName === null || trim((string)$serverName) === '' ) { $serverName = 'x'; } $escapedExtraArgs = array_map('escapeshellarg', $extraArgs); $modifier = implode(' ', $escapedExtraArgs); $file = __FILE__; $innerCmd = 'cd ' . escapeshellarg("$path/wp-admin") . ' && timeout ' . (int)$timeout . ' ' . escapeshellarg($phpBinPath) . ($phpOptions !== '' ? ' ' . $phpOptions : '') . ' ' . escapeshellarg($file) . ' ' . escapeshellarg($action) . ' ' . escapeshellarg($path) . ' ' . escapeshellarg($docRoot) . ' ' . escapeshellarg($serverName) . ' ' . escapeshellarg($env) . ($modifier !== '' ? ' ' . $modifier : ''); return "$su -c " . escapeshellarg($innerCmd); } /** * * @since 1.12 * * @param string $action * @param WPInstall $wpInstall * @param string[] $extraArgs * * @return null|string * * @throws LSCMException Thrown indirectly by self::preIssueValidation() * call. * @throws LSCMException Thrown indirectly by self::getIssueCmd() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by Logger::logMsg() call. * @throws LSCMException Thrown indirectly by Logger::logMsg() call. */ public static function getValueFromWordPress( $action, WPInstall $wpInstall, array $extraArgs = array() ) { if ( !self::preIssueValidation($action, $wpInstall, $extraArgs) ) { return null; } $cmd = self::getIssueCmd($action, $wpInstall, $extraArgs); exec($cmd, $output, $return_var); Logger::debug( "getValueFromWordPress command $action=$return_var $wpInstall\n$cmd" ); Logger::debug('output = ' . var_export($output, true)); $ret = null; $debug = $upgrade = $err = ''; $curr = &$err; foreach ( $output as $line ) { /** * If this line is not present in output, did not return normally. * This line will appear after any [UPGRADE] output. */ if ( strpos($line, 'LS UserCommand Output Start') !== false ) { continue; } elseif ( strpos($line, '[RESULT]') !== false ) { if ( preg_match('/API_KEY=(.+)/', $line, $m) ) { $ret = $m[1]; } else { $err .= "Unexpected result line $line\n"; } } elseif ( ($pos = strpos($line, '[DEBUG]')) !== false ) { $debug .= substr($line, $pos + 7) . "\n"; $curr = &$debug; } elseif ( strpos($line, '[UPGRADE]') !== false ) { //Ignore this output $curr = &$upgrade; } else { $curr .= "$line\n"; } } $path = $wpInstall->getPath(); if ( $debug ) { Logger::logMsg("$path - $debug", Logger::L_DEBUG); } if ( $err ) { Logger::logMsg("$path - $err", Logger::L_ERROR); } return $ret; } /** * * @since 1.14 * * @param string $subAction * @param WPInstall $wpInstall * * @return string[] * * @throws LSCMException Thrown indirectly by self::getIssueCmd() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. */ private static function subCommandIssue( $subAction, WPInstall $wpInstall ) { $subCmd = self::getIssueCmd($subAction, $wpInstall); exec($subCmd, $subOutput, $subReturn_var); Logger::debug( "Issue sub command $subAction=$subReturn_var $wpInstall\n$subCmd" ); Logger::debug('sub output = ' . var_export($subOutput, true)); return $subOutput; } /** * * @param string $action * @param WPInstall $wpInstall * @param string[] $extraArgs * * @return bool * * @throws LSCMException Thrown indirectly by self::preIssueValidation() * call. * @throws LSCMException Thrown indirectly by self::getIssueCmd() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by * self::removeLeftoverLscwpFiles() call. * @throws LSCMException Thrown indirectly by self::handleResultOutput() * call. * @throws LSCMException Thrown indirectly by Logger::logMsg() call. * @throws LSCMException Thrown indirectly by Logger::logMsg() call. * @throws LSCMException Thrown indirectly by $wpInstall->addUserFlagFile() * call. * @throws LSCMException Thrown indirectly by Logger::error() call. * @throws LSCMException Thrown indirectly by self::handleUnexpectedError() * call. */ public static function issue( $action, WPInstall $wpInstall, array $extraArgs = array() ) { if ( !self::preIssueValidation($action, $wpInstall, $extraArgs) ) { return false; } $cmd = self::getIssueCmd($action, $wpInstall, $extraArgs); exec($cmd, $output, $return_var); Logger::debug( "Issue command $action=$return_var $wpInstall\n$cmd" ); Logger::debug('output = ' . var_export($output, true)); if ( $wpInstall->hasNewLscwpFlagFile() ) { self::removeLeftoverLscwpFiles($wpInstall); } $errorStatus = $retStatus = $cmdStatus = 0; switch ( $return_var ) { case UserCommand::RETURN_CODE_TIMEOUT: $errorStatus |= WPInstall::ST_ERR_TIMEOUT; break; case UserCommand::EXIT_ERROR: case 255: $errorStatus |= WPInstall::ST_ERR_EXECMD; break; //no default } $isExpectedOutput = false; $unexpectedLines = 0; $succ = $upgrade = $err = $msg = $logMsg = ''; $logLvl = -1; $curr = &$err; foreach ( $output as $line ) { /** * If this line is not present in output, did not return normally. * This line will appear after any [UPGRADE] output. */ if ( strpos($line, 'LS UserCommand Output Start') !== false ) { $isExpectedOutput = true; } elseif ( strpos($line, '[RESULT]') !== false ) { $ret = self::handleResultOutput( $wpInstall, $line, $retStatus, $cmdStatus, $err ); if ( !$ret ) { /** * Problem handling RESULT output, ignore other output. */ return false; } } elseif ( ($pos = strpos($line, '[SUCCESS]')) !== false ) { $succ .= substr($line, $pos + 9) . "\n"; $curr = &$succ; } elseif ( ($pos = strpos($line, '[ERROR]')) !== false ) { $err .= substr($line, $pos + 7) . "\n"; $curr = &$err; } elseif ( strpos($line, '[LOG]') !== false ) { if ( $logMsg != '' ) { Logger::logMsg(trim($logMsg), $logLvl); $logMsg = ''; } if ( preg_match('/\[(\d+)] (.+)/', $line, $m) ) { $logLvl = $m[1]; $logMsg = "{$wpInstall->getPath()} - $m[2]\n"; } $curr = &$logMsg; } elseif ( strpos($line, '[UPGRADE]') !== false ) { /** * Ignore this output */ $curr = &$upgrade; } else { if ( !$isExpectedOutput ) { $line = htmlentities($line); $unexpectedLines++; } $curr .= "$line\n"; } } if ( $logMsg != '' ) { Logger::logMsg(trim($logMsg), $logLvl); } if ( !$isExpectedOutput && !$errorStatus ) { $errorStatus |= WPInstall::ST_ERR_EXECMD; } if ( $errorStatus ) { $wpInstall->addUserFlagFile(false); $errorStatus |= WPInstall::ST_FLAGGED; $cmdStatus |= UserCommand::EXIT_INCR_FAIL; } $newStatus = ($errorStatus | $retStatus); if ( $newStatus != 0 ) { $wpInstall->setStatus($newStatus); } if ( $succ ) { $cmdStatus |= UserCommand::EXIT_SUCC; $msg = $succ; } if ( $err ) { if ( $return_var == UserCommand::EXIT_FAIL ) { $cmdStatus |= UserCommand::EXIT_FAIL; } else { $cmdStatus |= UserCommand::EXIT_ERROR; } if ( $isExpectedOutput ) { $msg = $err; Logger::error("{$wpInstall->getPath()} - $err"); } else { $msg = self::handleUnexpectedError( $wpInstall, $err, $unexpectedLines ); } } $wpInstall->setCmdStatusAndMsg($cmdStatus, $msg); return true; } /** * * @param string[] $args * * @return null|WPInstall */ public static function newFromCmdArgs( array &$args ) { if ( count($args) < 3 ) { return null; } $wpPath = array_shift($args); $docRoot = array_shift($args); $serverName = array_shift($args); if ( $wpPath === null || $wpPath === '' ) { return null; } if ( !is_dir($wpPath) ) { return null; } if ( ($serverName === null || $serverName === '') && !empty($args) ) { $serverName = 'x'; } /** * LSCWP_REF used by LSCWP plugin. */ Util::define_wrapper('LSCWP_REF', array_shift($args)); $install = new WPInstall($wpPath); if ( $docRoot !== null && $docRoot !== '' && $docRoot !== 'x' ) { $install->setDocRoot($docRoot); } if ( $serverName !== null && $serverName !== '' && $serverName !== 'x' ) { $install->setServerName($serverName); } return $install; } /** * * @param string $action * @param WPInstall $wpInstall * @param string[] $extraArgs Not used at the moment. * * @return bool * * @throws LSCMException Thrown when $action value is unsupported. * @throws LSCMException Thrown indirectly by $wpInstall->hasValidPath() * call. * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by $wpInstall->refreshStatus() * call. * @throws LSCMException Thrown indirectly by $wpInstall->addUserFlagFile() * call. * @throws LSCMException Thrown indirectly by Logger::debug() call. * @throws LSCMException Thrown indirectly by * DashNotifier::prepLocalDashPluginFiles() call. * * @noinspection PhpUnusedParameterInspection */ private static function preIssueValidation( $action, WPInstall $wpInstall, array $extraArgs ) { if ( !self::isSupportedIssueCmd($action) ) { throw new LSCMException( "Illegal action $action.", LSCMException::E_PROGRAM ); } if ( !$wpInstall->hasValidPath() ) { return false; } switch ( $action ) { case self::CMD_MASS_ENABLE: case self::CMD_MASS_DISABLE: case self::CMD_MASS_UPGRADE: if ( $wpInstall->hasFlagFile() ) { Logger::debug( "Bypass mass operation for flagged install $wpInstall" ); return false; } //fallthrough case self::CMD_MASS_DASH_NOTIFY: case self::CMD_MASS_DASH_DISABLE: if ( $wpInstall->hasFatalError() ) { $wpInstall->refreshStatus(); if ( $wpInstall->hasFatalError() ) { $wpInstall->addUserFlagFile(false); Logger::debug( 'Bypassed mass operation for error install and ' . "flagged $wpInstall" ); return false; } } //no default } if ( $action == self::CMD_DASH_NOTIFY || $action == self::CMD_MASS_DASH_NOTIFY ) { DashNotifier::prepLocalDashPluginFiles(); } return true; } /** * * @since 1.9 Changed echoed output format to include "[LOG][$lvl] $msg". * Stopped echoing "[DEBUG] $msg" output. * * @return int */ private function runAsUser() { try { $ret = 0; if ( $this->action == self::CMD_REMOVE_LSCWP_PLUGIN_FILES ) { $proc = WPCaller::getInstance($this->currInstall, false); $proc->removeLscwpPluginFiles(); $ret = self::EXIT_SUCC; } else { $proc = WPCaller::getInstance($this->currInstall); switch ( $this->action ) { case self::CMD_STATUS: $ret = $proc->updateStatus(true); break; case self::CMD_ENABLE: $ret = $proc->enable($this->extraArgs); $this->currInstall->removeNewLscwpFlagFile(); break; case self::CMD_DIRECT_ENABLE: $ret = $proc->directEnable(); $this->currInstall->removeNewLscwpFlagFile(); break; case self::CMD_MASS_ENABLE: $ret = $proc->massEnable($this->extraArgs); $this->currInstall->removeNewLscwpFlagFile(); break; case self::CMD_DISABLE: $ret = $proc->disable($this->extraArgs); break; case self::CMD_MASS_DISABLE: $ret = $proc->massDisable($this->extraArgs); break; case self::CMD_UPGRADE: $ret = $proc->upgrade($this->extraArgs); break; case self::CMD_MASS_UPGRADE: $ret = $proc->massUpgrade($this->extraArgs); break; case self::CMD_UPDATE_TRANSLATION: $proc->updateTranslationFiles(); $ret = self::EXIT_SUCC; break; case self::CMD_DASH_NOTIFY: $ret = $proc->dashNotify($this->extraArgs); break; case self::CMD_MASS_DASH_NOTIFY: $ret = $proc->massDashNotify($this->extraArgs); break; case self::CMD_DASH_DISABLE: $ret = $proc->dashDisable($this->extraArgs); break; case self::CMD_MASS_DASH_DISABLE: $ret = $proc->massDashDisable($this->extraArgs); break; case self::CMD_GET_QUICCLOUD_API_KEY: $proc->getQuicCloudAPIKey(true); $ret = self::EXIT_SUCC; break; //no default } } echo "LS UserCommand Output Start\n"; foreach ( $proc->getOutputResult() as $key => $value ) { echo "[RESULT] $key=$value\n"; } foreach ( Logger::getUiMsgs(Logger::UI_SUCC) as $msg ) { echo "[SUCCESS] $msg\n"; } foreach ( Logger::getUiMsgs(Logger::UI_ERR) as $msg ) { echo "[ERROR] $msg\n"; } foreach ( Logger::getLogMsgQueue() as $logEntry ) { $lvl = $logEntry->getLvl(); $msg = $logEntry->getMsg(); echo "[LOG][$lvl] $msg\n"; } } catch ( Exception $e ) { $ret = UserCommand::EXIT_ERROR; if ( $e instanceof LSCMException && $e->getCode() == LSCMException::E_NON_FATAL ) { $ret = UserCommand::EXIT_FAIL; } echo "LS UserCommand Output Start\n"; echo "[ERROR] {$e->getMessage()}\n"; } return $ret; } /** * * @since 1.17.10 Changed function visibility from 'private' * to 'public static' so WPInstallStorage::doWPInstallAction() can call * it as part of the fail-closed dispatcher guard. * * @param string $action * * @return bool */ public static function isSupportedIssueCmd( $action ) { $supported = array( self::CMD_STATUS, self::CMD_ENABLE, self::CMD_DIRECT_ENABLE, self::CMD_MASS_ENABLE, self::CMD_DISABLE, self::CMD_MASS_DISABLE, self::CMD_UPGRADE, self::CMD_MASS_UPGRADE, self::CMD_UPDATE_TRANSLATION, self::CMD_REMOVE_LSCWP_PLUGIN_FILES, self::CMD_DASH_NOTIFY, self::CMD_MASS_DASH_NOTIFY, self::CMD_DASH_DISABLE, self::CMD_MASS_DASH_DISABLE, self::CMD_GET_QUICCLOUD_API_KEY ); return in_array($action, $supported); } /** * * @param string[] $args * * @return bool */ private function initArgs( $args ) { $action = array_shift($args); if ( self::isSupportedIssueCmd($action) ) { $this->action = $action; if ( $install = self::newFromCmdArgs($args) ) { $this->currInstall = $install; $this->extraArgs = $args; return true; } } return false; } /** * * @return UserCommand * * @throws LSCMException Thrown indirectly by "new self()" call. * * @noinspection PhpDocRedundantThrowsInspection */ private static function getUserCommand() { /** * Check if invoked from shell. */ if ( empty($_SERVER['argv']) ) { return null; } $args = $_SERVER['argv']; if ( array_shift($args) != __FILE__ ) { return null; } $instance = new self(true); if ( !$instance->initArgs($args) ) { echo 'illegal input ' . implode(' ', $_SERVER['argv']); exit(self::EXIT_ERROR); } return $instance; } /** * * @throws LSCMException Thrown indirectly by self::getUserCommand() call. */ public static function run() { if ( $cmd = self::getUserCommand() ) { if ( !defined('LSCM_RUN_AS_USER') ) { Util::define_wrapper('LSCM_RUN_AS_USER', 1); } $ret = $cmd->runAsUser(); exit($ret); } } } /** * This should only be invoked from command line. * * @noinspection PhpUnhandledExceptionInspection */ UserCommand::run(); PK!e,webcachemgr/bootstrap.phpnuIw $HOSTNAME apache apache 0 / 0 60M /tmp/lshttpd/swap 1 0 1 1 /usr/sbin/httpd /etc/httpd/conf/httpd.conf %AP_PORT_OFFSET% 0 %PHP_SUEXEC% 10 $SERVER_ROOT/conf/mime.properties 0 2 86400 1 %ADMIN_EMAIL% $SERVER_ROOT/admin/ $SERVER_ROOT/logs/error.log DEBUG 0 2000M 1 $SERVER_ROOT/logs/access.log 10M 30 0 index.html, index.php, index.htm 31 .htaccess 1 image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800 10000 10000 120 10000 0 10 0 0 best 4096 20M 256K 40M 1 1 4 1 null 8192 16380 500M 4K 500M 1 1 default 1 1 0 000 000 0 0 0 0 10000 10000 15 300 20 11 10 0 60 120 1250M 1300M 400 450 0 0 deny,log,status:403 1 / /etc/* /dev/* $SERVER_ROOT/conf/* $SERVER_ROOT/admin/conf/* ALL 35 PHP_LSAPI_CHILDREN=35 60 0 1 0 60 1400 1500 1 5 LSAPI_MAX_IDLE=60 60 0 60 0 50 1 300 3 400 500 PK!Mrccinterworx/httpd_config.xmlnu[ $HOSTNAME apache apache 0 / 0 60M /tmp/lshttpd/swap 1 0 1 1 /etc/httpd/conf/httpd.conf %AP_PORT_OFFSET% 0 %PHP_SUEXEC% 10 $SERVER_ROOT/conf/mime.properties 0 2 86400 1 %ADMIN_EMAIL% $SERVER_ROOT/admin/ $SERVER_ROOT/logs/error.log DEBUG 0 10M 1 $SERVER_ROOT/logs/access.log 10M 30 0 index.html, index.php, index.htm 31 .htaccess 1 image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800 10000 10000 120 10000 0 10 0 0 best 4096 20M 256K 40M 1 1 4 1 null 8192 16380 500M 4K 500M 1 1 default 1 1 0 1 000 000 002 002 0 0 0 0 10000 10000 15 300 20 11 10 0 60 120 1250M 1300M 400 450 0 0 deny,log,status:403 1 / /etc/* /dev/* $SERVER_ROOT/conf/* $SERVER_ROOT/admin/conf/* ALL 35 PHP_LSAPI_CHILDREN=35 60 0 1 0 60 1400 1500 1 5 LSAPI_MAX_IDLE=60 60 0 60 0 50 1 300 3 200 300 PK!jQ$snmp_monitoring/litespeed_extapp.xmlnu[ Get LiteSpeed External Applications .1.3.6.1.4.1.22253.300 ExtApp:Type:Vhost:Index numeric |chosen_order_field| Index walk value input .1.3.6.1.4.1.22253.300 Vhost Name walk value input .1.3.6.1.4.1.22253.301 Type walk value input .1.3.6.1.4.1.22253.302 Ext App walk value input .1.3.6.1.4.1.22253.303 Config Max Conn walk value output .1.3.6.1.4.1.22253.304 Effective Max Conn walk value output .1.3.6.1.4.1.22253.305 Pool Size walk value output .1.3.6.1.4.1.22253.306 InUse Conn walk value output .1.3.6.1.4.1.22253.307 Idle Conn walk value output .1.3.6.1.4.1.22253.308 Wait-Queue Depth walk value output .1.3.6.1.4.1.22253.309 Requests Per Second walk value output .1.3.6.1.4.1.22253.310 Requests Total walk value output .1.3.6.1.4.1.22253.311 PK!f/snmp_monitoring/class.litespeed_snmp_bridge.phpnu[= 2.1.18 2)PHP 5+ ----------------------------------------*/ require_once("class.litespeed_stats.php"); class litespeed_snmp_bridge { public $processes = 1; public $report_path = "/tmp/lshttpd/"; public $cache_time = 0; public $cache_file = null; public $stats = null; public function litespeed_snmp_bridge($processes = 1, $report_path = "/tmp/lshttpd/", $cache_time = 0, $cache_file = null) { $this->processes = (int) $processes; $this->report_path = trim($report_path); //prepare parser if($this->cache_time > 0 && strlen($this->cache_file) > 0) { if(file_exists($this->cache_file) && time() - filemtime($this->cache_file) <= $this->cache_time) { $unserial = unserialize(file_get_contents($this->cache_file)); if(is_a($unserial,"litespeed_stats")) { $this->stats = $unserial; } else { $this->stats = new litespeed_stats($this->processes,$this->report_path); $this->stats->parse(); $this->save_cache($this->cache_file, $this->stats); } } else { $this->stats = new litespeed_stats($this->processes,$this->report_path); $this->stats->parse(); $this->save_cache($this->cache_file, $this->stats); } } else { $this->stats = new litespeed_stats($this->processes,$this->report_path); $this->stats->parse(); } } //generate snmp compatible response public function format_response($oid, $type, $data) { return "{$oid}\n{$type}\n{$data}\n"; } //aggregate oid info from 1 to 7 sector public function oid_part($tarray = null) { $str = ""; for($i=1; $i <= 7; $i++) { $str .= "." . $tarray[$i]; } return $str; } //retrieve single oid data public function oid_get($super, $oid) { $parsed = explode(".",$oid); //error..invalid oid parse if(count($parsed) < 9) { return; } $major = (int) $parsed[8]; if(count($parsed) < 10) { $minor = 1; } else { $minor = (int) $parsed[9]; } foreach($super as $key => $value) { $sanitized_major = (int) substr($major,0,1) . "00"; //index only if( $major == (int) $key ) { return $this->format_response($this->oid_part($parsed) . "." . $major . "." . $minor,"integer",$minor); } //non-index value if( $sanitized_major == (int) $key) { $size = count($value[0]); $map = $value[1]; if($size <= 0) { return null; } if(count($parsed) == 10) { if($minor > 0 && $minor <= $size) { $tempkeys = array_keys($value[0]); $temp = $value[0][$tempkeys[$minor-1]]; list($format,$itemkey) = explode(",",$value[1][$major]); return $this->format_response($oid, $format, $temp->$itemkey); } } } } } public function save_cache($file, $data) { file_put_contents($file, serialize($data)); } public function process($type, $oid) { //setup oid to var maps $vh_map = array( "201" => "string,vhost", "202" => "gauge,req_processing", "203" => "gauge,req_per_sec", "204" => "counter,req_total" ); $ext_map = array( "301" => "string,vhost", "302" => "string,type", "303" => "string,extapp", "304" => "gauge,config_max_conn", "305" => "gauge,effect_max_conn", "306" => "gauge,pool_size", "307" => "gauge,inuse_conn", "308" => "gauge,idle_conn", "309" => "gauge,waitqueue_depth", "310" => "gauge,req_per_sec", "311" => "counter,req_total" ); $gen_map = array( "101" => "string,product", "102" => "string,edition", "103" => "string,version", "104" => "string,uptime", "105" => "gauge,bps_in", "106" => "gauge,bps_out", "107" => "gauge,ssl_bps_in", "108" => "gauge,ssl_bps_out", "109" => "gauge,max_conn", "110" => "gauge,max_ssl_conn", "111" => "gauge,plain_conn", "112" => "gauge,avail_conn", "113" => "gauge,idle_conn", "114" => "gauge,ssl_conn", "115" => "gauge,avail_ssl_conn" ); //setup pointers $super = array(); $super["100"] = array(array($this->stats), $gen_map); $super["200"] = array($this->stats->vhosts, $vh_map); //put alll extapps to single array $extapps = array(); foreach($this->stats->vhosts as $value) { foreach($value->extapps as $vextapp) { $extapps[] = $vextapp; } } $super["300"] = array($extapps, $ext_map); //get single method if($type == "-g") { echo $this->oid_get($super, $oid); return; } //snmp walk traversal else if($type == "-n") { //build traversal nodes/oids $parsed = explode(".",$oid); $major = $parsed[8]; foreach($super as $key => $value) { //form index walk if($major == $key) { $size = count($value[0]); if($size <= 0) { return; } if(count($parsed) == 10) { $minor = (int) $parsed[9]; if($minor > 0 && $minor < $size) { echo $this->format_response($this->oid_part($parsed).".{$key}.".($minor+1),"integer",$minor+1); } } else if(count($parsed) == 9){ echo $this->format_response("{$oid}.1","integer",1); } } //data walk else if(array_key_exists($major,$value[1])) { $size = count($value[0]); if($size <= 0) { return; } if(count($parsed) == 10) { $minor = (int) $parsed[9]; if($minor > 0 && $minor < $size) { echo $this->oid_get($super, $this->oid_part($parsed).".{$major}.".($minor+1)); } } else if(count($parsed) == 9){ echo $this->oid_get($super, $this->oid_part($parsed).".{$major}.".(1)); } } } } } } ?> PK!p#snmp_monitoring/litespeed_vhost.xmlnu[ Get LiteSpeed Vhosts list litespeed virtual hosts .1.3.6.1.4.1.22253.200 Vhost:Index numeric |chosen_order_field| Index walk value input .1.3.6.1.4.1.22253.200 Vhost Name walk value input .1.3.6.1.4.1.22253.201 Requests Processing walk value output .1.3.6.1.4.1.22253.202 Requests Per Second walk value output .1.3.6.1.4.1.22253.203 Requests Total walk value output .1.3.6.1.4.1.22253.204 PK!n$PCCsnmp_monitoring/READMEnu[LiteSpeed SNMPD Bridge + Cacti Templates ---------------------------------------- For the most up-to-date installation documentation, please refer to our online "SNMP Monitoring" wiki: http://www.litespeedtech.com/support/wiki/doku.php?id=litespeed_wiki:snmp_cacti_monitoring Release Log: ----------- 1.0 08-23-2006 PK!P%snmp_monitoring/litespeed_general.xmlnu[ Get LiteSpeed General list litespeed general .1.3.6.1.4.1.22253.100 Index numeric |chosen_order_field| Index walk value input .1.3.6.1.4.1.22253.100 Product walk value input .1.3.6.1.4.1.22253.101 Edition walk value input .1.3.6.1.4.1.22253.102 Version walk value input .1.3.6.1.4.1.22253.103 UpTime walk value input .1.3.6.1.4.1.22253.104 Bps (In) walk value output .1.3.6.1.4.1.22253.105 Bps (Out) walk value output .1.3.6.1.4.1.22253.106 SSL Bps (In) walk value output .1.3.6.1.4.1.22253.107 SSL Bps (Out) walk value output .1.3.6.1.4.1.22253.108 Max Connections walk value output .1.3.6.1.4.1.22253.109 Max SSL Connections walk value output .1.3.6.1.4.1.22253.110 Plain Connections walk value output .1.3.6.1.4.1.22253.111 Available Plain Connections walk value output .1.3.6.1.4.1.22253.112 Idle Connections walk value output .1.3.6.1.4.1.22253.113 SSL Connections walk value output .1.3.6.1.4.1.22253.114 Available SSL Connections walk value output .1.3.6.1.4.1.22253.115 PK!}Aff)snmp_monitoring/class.litespeed_stats.phpnu[= 2.1.18 2)PHP 5+ ----------------------------------------*/ class litespeed_stats { public $product = null; public $edition = null; public $version = null; public $uptime = null; public $load_avg = NULL; public $bps_in = 0; public $bps_out = 0; public $ssl_bps_in = 0; public $ssl_bps_out = 0; public $max_conn = 0; public $max_ssl_conn = 0; public $plain_conn = 0; public $avail_conn = 0; public $idle_conn = 0; public $ssl_conn = 0; public $avail_ssl_conn = 0; public $blocked_ip; public $vhosts = array(); public $serv = NULL; //misc settings //full path to .rtreports files. different products have different paths public $report_path = "/tmp/lshttpd/"; //processes..enterprise version can spawn proccess = cpu cores public $processes = 1; public function litespeed_stats($processes = 1, $report_path = "/tmp/lshttpd/") { $this->processes = (int) $processes; $this->report_path = trim($report_path); } public function parse() { for ( $i = 1 ; $i <= $this->processes ; $i++ ) { if ( $i > 1 ) { $content = file_get_contents("{$this->report_path}.rtreport.{$i}"); } else { $content = file_get_contents("{$this->report_path}.rtreport"); } } $result = array(); $this->blocked_ip = array(); $found = 0; $found = preg_match_all("/VERSION: ([a-zA-Z0-9\ ]+)\/([a-zA-Z]*)\/([a-zA-Z0-9\.]+)\nUPTIME: ([0-9A-Za-z\ \:]+)\nBPS_IN:([0-9\ ]+), BPS_OUT:([0-9\ ]+), SSL_BPS_IN:([0-9\ ]+), SSL_BPS_OUT:([0-9\ ]+)\nMAXCONN:([0-9\ ]+), MAXSSL_CONN:([0-9\ ]+), PLAINCONN:([0-9\ ]+), AVAILCONN:([0-9\ ]+), IDLECONN:([0-9\ ]+), SSLCONN:([0-9\ ]+), AVAILSSL:([0-9\ ]+)/i", $content, $result); for($f = 0; $f < $found; $f++) { $this->product = trim($result[1][$f]); $this->edition = trim($result[2][$f]); $this->version = trim($result[3][$f]); $this->uptime = trim($result[4][$f]); $this->bps_in += (int) $result[5][$f]; $this->bps_out += (int) $result[6][$f]; $this->ssl_bps_in += (int) $result[7][$f]; $this->ssl_bps_out += (int) $result[8][$f]; $this->max_conn += (int) $result[9][$f]; $this->max_ssl_conn += (int) $result[10][$f]; $this->plain_conn += (int) $result[11][$f]; $this->avail_conn += (int) $result[12][$f]; $this->idle_conn += (int) $result[13][$f]; $this->ssl_conn += (int) $result[14][$f]; $this->avail_ssl_conn += (int) $result[15][$f]; } $result = array(); $found = 0; $found = preg_match_all("/BLOCKED_IP: ([0-9 \[\]\.,]*)/", $content, $result); for($f = 0; $f < $found; $f++) { $ips = trim($result[1][$f]); if ($ips != "") { $iplist = preg_split("/[\s,]+/", $ips, -1, PREG_SPLIT_NO_EMPTY); $this->blocked_ip = array_merge($this->blocked_ip, $iplist); } } $result = array(); $found = 0; $found = preg_match_all("/REQ_RATE \[(.*)\]: REQ_PROCESSING: ([0-9]+), REQ_PER_SEC: ([0-9\.]+), TOT_REQS: ([0-9]+), PUB_CACHE_HITS_PER_SEC: ([0-9\.]+), TOTAL_PUB_CACHE_HITS: ([0-9]+), PRIVATE_CACHE_HITS_PER_SEC: ([0-9\.]+), TOTAL_PRIVATE_CACHE_HITS: ([0-9]+), STATIC_HITS_PER_SEC: ([0-9\.]+), TOTAL_STATIC_HITS: ([0-9]+)/i",$content,$result); for($f = 0; $f < $found; $f++) { $vhost = trim($result[1][$f]); if($vhost == "") { $vhost = "_Server"; } if(!array_key_exists($vhost,$this->vhosts)) { $this->vhosts[$vhost] = new litespeed_stats_vhost($vhost); } $temp = $this->vhosts[$vhost]; $temp->req_processing += (int) $result[2][$f]; $temp->req_per_sec += doubleval($result[3][$f]); $temp->req_total += doubleval($result[4][$f]); $temp->cache_hits_per_sec += doubleval($result[5][$f]); $temp->total_cache_hits += doubleval($result[6][$f]); $temp->private_cache_hits_per_sec += doubleval($result[7][$f]); $temp->total_private_cache_hits += (int) $result[8][$f]; $temp->static_hits_per_sec += doubleval($result[9][$f]); $temp->total_static_hits += doubleval($result[10][$f]); } $result = array(); $found = 0; $found = preg_match_all("/EXTAPP \[([^\]]*)\] \[(.*)\] \[([^\]]*)\]: CMAXCONN: ([0-9]+), EMAXCONN: ([0-9]+), POOL_SIZE: ([0-9]+), INUSE_CONN: ([0-9]+), IDLE_CONN: ([0-9]+), WAITQUE_DEPTH: ([0-9]+), REQ_PER_SEC: ([0-9\.]+), TOT_REQS: ([0-9]+)/i",$content,$result); for($f = 0; $f < $found; $f++) { $vhost = trim($result[2][$f]); $extapp = trim($result[3][$f]); if($vhost == "") { $vhost = "_Server"; } if(!array_key_exists($vhost,$this->vhosts)) { $this->vhosts[$vhost] = new litespeed_stats_vhost($vhost); } if(!array_key_exists($extapp,$this->vhosts[$vhost]->extapps)) { $this->vhosts[$vhost]->extapps[$extapp] = new litespeed_stats_vhost_extapp($extapp, $vhost); $this->vhosts[$vhost]->eap_count ++; $this->vhosts[$vhost]->eap_process ++; } $temp = $this->vhosts[$vhost]->extapps[$extapp]; $temp->type = trim($result[1][$f]); $temp->config_max_conn += (int) $result[4][$f]; $temp->effect_max_conn += (int) $result[5][$f]; $temp->pool_size += (int) $result[6][$f]; $temp->inuse_conn += (int) $result[7][$f]; $temp->idle_conn += (int) $result[8][$f]; $temp->waitqueue_depth += (int) $result[9][$f]; $temp->req_per_sec += (int) $result[10][$f]; $temp->req_total += (int) $result[11][$f]; $this->vhosts[$vhost]->eap_inuse += (int) $result[7][$f]; $this->vhosts[$vhost]->eap_idle += (int) $result[8][$f]; $this->vhosts[$vhost]->eap_waitQ += (int) $result[9][$f]; $this->vhosts[$vhost]->eap_req_per_sec += doubleval($result[10][$f]); $this->vhosts[$vhost]->eap_req_total += doubleval($result[11][$f]); } if (count($this->blocked_ip) > 2) { sort($this->blocked_ip); } $this->serv = $this->vhosts['_Server']; } } class liteSpeed_stats_vhost { public $req_processing = 0; public $req_per_sec = 0.0; public $req_total = 0; public $cache_hits_per_sec = 0.0; public $total_cache_hits = 0; public $private_cache_hits_per_sec = 0.0; public $total_private_cache_hits = 0; public $static_hits_per_sec = 0.0; public $total_static_hits = 0; public $eap_count = 0; public $eap_process = 0; public $eap_inuse = 0; public $eap_idle = 0; public $eap_waitQ = 0; public $eap_req_per_sec = 0.0; public $eap_req_total = 0; public $extapps = array(); public function litespeed_stats_vhost($vhost = null) { $this->vhost = trim($vhost); } } class litespeed_stats_vhost_extapp { public function litespeed_stats_vhost_extApp($extapp = null, $vhost = null) { $this->extapp = trim($extapp); $this->vhost = trim($vhost); } public $vhost = null; public $type = null; public $extapp = null; public $config_max_conn = 0; public $effect_max_conn = 0; public $pool_size = 0; public $inuse_conn = 0; public $idle_conn = 0; public $waitqueue_depth = 0; public $req_per_sec = 0; public $req_total = 0; } ?> PK!( fMfM,snmp_monitoring/litespeed_cacti_template.xmlnu[ LiteSpeed hash_00001616ed2d0aa716489be372dd598afe0b9e|hash_000016022aa61c315e6588a6acd2c013fcf5c5|hash_000016974ad3f65464268b1e61142e1d377048|hash_000016bac5833ec4bd88e46603947c40f163dd|hash_0000164740ee10c62708a97452e64c39918381|hash_0000160ec40ca42977e0f88770a13629862650|hash_000016a85d4e176d782c3bef5da7ed00cce513 hash_040016e423847310ebee7dc22eaf3938d709f9|hash_04001676d81d4e3c52dab62afa5205a9c517a2|hash_040016c6bc8ced2a4d8fac0fde1c0cead29779 LiteSpeed: Vhost on 1 120 500 0 on on 2 0 on on on 100 0 1000 requests hash_08001676fbeb01ef35493c81578394cdc9f453 96E78A FF 7 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 ReqInProcess 1 hash_08001676fbeb01ef35493c81578394cdc9f453 0 FF 9 4 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Now: 2 hash_08001676fbeb01ef35493c81578394cdc9f453 0 FF 9 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Avg: 3 hash_08001676fbeb01ef35493c81578394cdc9f453 0 FF 9 3 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Max: on 4 hash_080016e5084b9e07fdcc5535637f75b8af3222 0D006A FF 4 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 ReqPerSecond 5 hash_080016e5084b9e07fdcc5535637f75b8af3222 0 FF 9 4 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Now: 6 hash_080016e5084b9e07fdcc5535637f75b8af3222 0 FF 9 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Avg: 7 hash_080016e5084b9e07fdcc5535637f75b8af3222 0 FF 9 3 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Max: on 8 Data Source [Req_Second] task_item_id hash_000016ca50796bc2609bcc2aa3617ab23196ae|hash_00001649e23d20228afc3ce8f4687a6e5498ce|hash_000016eb44c7ac124e6b165c878cbbc0f7d073|hash_000016c44b1ad8a111114b67eb73349e680b24 Data Source [Req_InProcess] task_item_id hash_0000168bfdc71ae071c75aae9c3149d293f31c|hash_00001660a88c66c7825785f62cbf9862ea1a79|hash_00001640f32c86f322d1449574cbf972a360c3|hash_000016385c598ee928ce0a6438d491777d8cfa LiteSpeed: ExtApp: Connections on 1 120 500 0 on on 2 0 on on 100 0 1000 connections hash_08001624140062cfa9de88c593a71be9a40e0f 96E78A FF 7 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 PoolSize 5 hash_08001624140062cfa9de88c593a71be9a40e0f 0 FF 9 4 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Now: 6 hash_08001624140062cfa9de88c593a71be9a40e0f 0 FF 9 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Avg: 7 hash_08001624140062cfa9de88c593a71be9a40e0f 0 FF 9 3 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Max: on 8 hash_080016dca7bbae358416c8a86fd74cc83104d8 FFF200 FF 7 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 InuseConn 9 hash_080016dca7bbae358416c8a86fd74cc83104d8 0 FF 9 4 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Now: 10 hash_080016dca7bbae358416c8a86fd74cc83104d8 0 FF 9 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Avg: 11 hash_080016dca7bbae358416c8a86fd74cc83104d8 0 FF 9 3 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Max: on 12 hash_080016dd80f6a8dac8166b110503ac3cdbe991 FF0000 FF 4 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 WaitQDepth: 17 hash_080016dd80f6a8dac8166b110503ac3cdbe991 0 FF 9 4 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Now: 18 hash_080016dd80f6a8dac8166b110503ac3cdbe991 0 FF 9 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Avg: 19 hash_080016dd80f6a8dac8166b110503ac3cdbe991 0 FF 9 3 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Max: on 20 Data Source [InuseConn] task_item_id hash_000016862bfd905333aaf128e3554b0f6fccf1|hash_000016474c6967780fa055ea1978443030158b|hash_0000169c9b88c77904394b6f986e4c1d7c550f|hash_000016d1bf02c6483524d7c49f5a42f7a140bf Data Source [PoolSize] task_item_id hash_0000162847edc56a65520b49fb4502906b87fc|hash_000016c6e41c42776fc4f991e184accb66a94d|hash_0000160698540d26180f8b9cfcbd8fb4e4d777|hash_000016799d4a164aa6bfe721c97520a2f659d6 Data Source [WaitQueueDepth] task_item_id hash_0000168d7dc073783d9d1ca3792a691a9f1990|hash_00001695799553d57884eb493946e45f6765f5|hash_000016d1cbd5717a1716c1bed5cf8eeca4e377|hash_0000164daa3e9aaf8c673f50536ba33fda11c3 LiteSpeed: ExtApp: Requests on 1 120 500 0 on on 2 0 on on on 100 0 1000 requests per second hash_0800165d24f91f2b8d9e5598d1abd567b076f9 96E78A FF 7 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 ReqSecond 1 hash_0800165d24f91f2b8d9e5598d1abd567b076f9 0 FF 9 4 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Now: 2 hash_0800165d24f91f2b8d9e5598d1abd567b076f9 0 FF 9 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Avg: 3 hash_0800165d24f91f2b8d9e5598d1abd567b076f9 0 FF 9 3 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Max: on 4 Data Source [Req_Second] task_item_id hash_000016e408d575f6fefa0f3ebb86bb1c421023|hash_0000167c06b950dc598b91af0b80857ff3e0ce|hash_00001672dd1f9361d79335392ab947a23a8672|hash_000016899845f77b8725ff772c41dc619208bf LiteSpeed: Plain Traffic (bits/sec) on 1 120 500 0 on on 2 0 on on 100 0 1000 bits per second hash_0800164a9cc0ba440529238c3bb8606e5991bd 96E78A FF 7 1 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 Out 1 hash_0800164a9cc0ba440529238c3bb8606e5991bd 0 FF 9 4 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 Now: 2 hash_0800164a9cc0ba440529238c3bb8606e5991bd 0 FF 9 1 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 Avg: 3 hash_0800164a9cc0ba440529238c3bb8606e5991bd 0 FF 9 3 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 Max: on 4 hash_080016f9bc5dd109ed4ab674746e66a49df3d8 0D006A FF 4 1 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 In 5 hash_080016f9bc5dd109ed4ab674746e66a49df3d8 0 FF 9 4 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 Now: 6 hash_080016f9bc5dd109ed4ab674746e66a49df3d8 0 FF 9 1 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 Avg: 7 hash_080016f9bc5dd109ed4ab674746e66a49df3d8 0 FF 9 3 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 Max: 8 Data Source [bps_in] task_item_id hash_000016fa7923d3e4a1d9b81714804672ef56bf|hash_0000160194e34b5b8d59128e6d33d7da5c006d|hash_000016c522a9937e83fc55b48741b243053fb7|hash_000016253c17724a2ac0292de235d1a466009f Data Source [bps_out] task_item_id hash_0000163a41a41ce3be052d2de210ad8664c53c|hash_000016591fb1dbdf84593b88aee5d817a10313|hash_0000162e863f0b0e6929b59647fd12739ffb41|hash_0000169e8d8db2a7c27fadac4c2493fd16b4a9 LiteSpeed: SSL Traffic (bits/sec) on 1 120 500 0 on on 2 0 on on 100 0 1000 bits per second hash_0800164d9b25cf1a27c98599313c1000f001b0 0D006A FF 4 1 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 In 1 hash_0800164d9b25cf1a27c98599313c1000f001b0 0 FF 9 3 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 Now: 2 hash_0800164d9b25cf1a27c98599313c1000f001b0 0 FF 9 1 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 Avg: 3 hash_0800164d9b25cf1a27c98599313c1000f001b0 0 FF 9 3 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 Max: on 4 hash_080016b874ed68ddc80a0ea28275a7ebfd1c3e 96E78A FF 4 1 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 Out 7 hash_080016b874ed68ddc80a0ea28275a7ebfd1c3e 0 FF 9 4 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 Now: 8 hash_080016b874ed68ddc80a0ea28275a7ebfd1c3e 0 FF 9 1 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 Avg: 9 hash_080016b874ed68ddc80a0ea28275a7ebfd1c3e 0 FF 9 3 hash_05001662a7a53922548f4f6eac05cad69fbd2d hash_060016e9c43831e54eca8069317a2ce8c6f751 Max: 10 Data Source [ssl_bps_in] task_item_id hash_000016f1d69f8e4c7b29f8fdea1d5ba158d9b6|hash_000016f3d829549cfc1473ac7b989ee539feab|hash_00001651eed8925c9aa32fd36e435fb09fa2b7|hash_000016abb20b0792470c07e2d81fc4ceac2a9e Data Source [ssl_bps_out] task_item_id hash_000016c0ae1387b30b828537acf3d20f700738|hash_000016f6485279a541756d622d84d348073dd9|hash_000016d3ddbd4cceed4745c66d884a31549a02|hash_0000165fe98a5a8583b543d87976388c20d129 LiteSpeed: Plain Connections on 1 120 500 on on 1 on on 100 0 1000 connections hash_0800160c86937c02cb9d97697e1c811f428cb8 FFF200 FF 7 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Used 1 hash_0800160c86937c02cb9d97697e1c811f428cb8 0 FF 9 4 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Now: 2 hash_0800160c86937c02cb9d97697e1c811f428cb8 0 FF 9 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Avg: 3 hash_0800160c86937c02cb9d97697e1c811f428cb8 0 FF 9 3 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Max: on 4 hash_080016614e73da69c6fa3034c159dfeb0b0362 96E78A FF 8 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Available 5 hash_080016614e73da69c6fa3034c159dfeb0b0362 0 FF 9 4 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Now: 6 hash_080016614e73da69c6fa3034c159dfeb0b0362 0 FF 9 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Avg: 7 hash_080016614e73da69c6fa3034c159dfeb0b0362 0 FF 9 3 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Max: 8 Data Source [plain_conn] task_item_id hash_000016785326a40ea378166fa83335d2f40972|hash_000016456cf906b1d321f2965e0cd393fd01be|hash_00001612ab61fa60ac33785eed66153f7d3d19|hash_00001621760afe12d7a229bcacc84034c0c142 Data Source [avail_conn] task_item_id hash_000016c83277ba4420abf66568df10dbd12baa|hash_000016b619d77e1ace0793b79219819ce45c2b|hash_000016c872db52d4083a6a2a01ecda02e4ed7d|hash_00001623c51b3457e37c971a7cb465a5bc898f LiteSpeed: SSL Connections on 1 120 500 0 on on 2 0 on on 100 0 1000 connections hash_08001667c11e9d5c8ee24343108fa839c89ac6 FFF200 FF 7 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Used 1 hash_08001667c11e9d5c8ee24343108fa839c89ac6 0 FF 9 4 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Now: 2 hash_08001667c11e9d5c8ee24343108fa839c89ac6 0 FF 9 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Avg: 3 hash_08001667c11e9d5c8ee24343108fa839c89ac6 0 FF 9 3 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Max: on 4 hash_0800164cb690fe79ffeb845634b5e64bcedba7 96E78A FF 8 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Available 5 hash_0800164cb690fe79ffeb845634b5e64bcedba7 0 FF 9 4 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Now: 6 hash_0800164cb690fe79ffeb845634b5e64bcedba7 0 FF 9 1 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Avg: 7 hash_0800164cb690fe79ffeb845634b5e64bcedba7 0 FF 9 3 0 hash_060016e9c43831e54eca8069317a2ce8c6f751 Max: 8 Data Source [ssl_conn] task_item_id hash_000016d5ffb9ffd21b1998560ae7f528b745f2|hash_0000168cb463086e6bfc9d15de0d60698a73d1|hash_00001614eeede9629ac14185deb07358ca4046|hash_00001660d821aa4ddebf92ed43ca743e50fa53 Data Source [avail_ssl_conn] task_item_id hash_000016be5ac8af8f5cb499b5d3e63d6739e40d|hash_0000161ad1fcdcf047dc89bb140662335f4b8a|hash_000016af2a2a40063ef8da8b09a408f1e40d66|hash_000016596a4c338a17ef4db5873a61470048ea LiteSpeed Vhost on |host_description| - ls vhost hash_030016bf566c869ac6443b0c75d1c32b5a350e 300 on hash_150016c21df5178e5c955013591239eb0afd46|hash_1500160d9c0af8b8acdc7807943937b3208e29|hash_1500166fc2d038fb42950138b0ce3e9874cc60|hash_150016e36f3adb9f152adfa5dc50fd2b23337e|hash_150016283ea2bf1634d92ce081ec82a634f513 Req_Second 0 100000000 1 600 0 Req_InProcess 0 100000000 1 600 0 Req_Total 0 100000000 2 600 0 hash_070016e6deda7be0f391399c5130e7c4a48b28 on hash_070016cbbe5c1ddfb264a6e5d509ce1c78c95f on hash_0700166027a919c7c7731fbe095b6f53ab127b on hash_070016b5c23f246559df38662c255f4aa21d6b hash_0700161cc1493a6781af2c478fa4de971531cf hash_070016f4facc5e2ca7ebee621f09bc6d9fc792 hash_070016acb449d1451e8a2a655c2c99d31142c7 hash_070016617cdc8a230615e59f06f361ef6e7728 LiteSpeed ExtApp on hash_030016bf566c869ac6443b0c75d1c32b5a350e 300 on hash_150016c21df5178e5c955013591239eb0afd46|hash_1500160d9c0af8b8acdc7807943937b3208e29|hash_1500166fc2d038fb42950138b0ce3e9874cc60|hash_150016e36f3adb9f152adfa5dc50fd2b23337e|hash_150016283ea2bf1634d92ce081ec82a634f513 WaitQueueDepth 0 100000000 1 600 0 ConfMaxConn 0 100000000 1 600 0 PoolSize 0 100000000 1 600 0 InuseConn 0 100000000 1 600 0 IdleConn 0 100000000 1 600 0 EffMaxConn 0 100000000 1 600 0 Req_Second 0 100000000 1 600 0 Req_Total 0 100000000 2 600 0 hash_070016e6deda7be0f391399c5130e7c4a48b28 on hash_070016cbbe5c1ddfb264a6e5d509ce1c78c95f on hash_0700166027a919c7c7731fbe095b6f53ab127b on hash_070016b5c23f246559df38662c255f4aa21d6b hash_0700161cc1493a6781af2c478fa4de971531cf hash_070016f4facc5e2ca7ebee621f09bc6d9fc792 hash_070016acb449d1451e8a2a655c2c99d31142c7 hash_070016617cdc8a230615e59f06f361ef6e7728 LiteSpeed General on hash_030016bf566c869ac6443b0c75d1c32b5a350e 300 on hash_150016c21df5178e5c955013591239eb0afd46|hash_1500160d9c0af8b8acdc7807943937b3208e29|hash_1500166fc2d038fb42950138b0ce3e9874cc60|hash_150016e36f3adb9f152adfa5dc50fd2b23337e|hash_150016283ea2bf1634d92ce081ec82a634f513 bps_in 0 100000000 1 600 0 bps_out 0 100000000 1 600 0 ssl_bps_in 0 100000000 1 600 0 ssl_bps_out 0 100000000 1 600 0 max_conn 0 100000000 1 600 0 max_ssl_conn 0 100000000 1 600 0 plain_conn 0 100000000 1 600 0 avail_conn 0 100000000 1 600 0 idle_conn 0 100000000 1 600 0 ssl_conn 0 100000000 1 600 0 avail_ssl_conn 0 100000000 1 600 0 hash_070016e6deda7be0f391399c5130e7c4a48b28 on hash_070016cbbe5c1ddfb264a6e5d509ce1c78c95f on hash_0700166027a919c7c7731fbe095b6f53ab127b on hash_070016b5c23f246559df38662c255f4aa21d6b hash_0700161cc1493a6781af2c478fa4de971531cf hash_070016f4facc5e2ca7ebee621f09bc6d9fc792 hash_070016acb449d1451e8a2a655c2c99d31142c7 hash_070016617cdc8a230615e59f06f361ef6e7728 Get SNMP Data (Indexed) 3 SNMP IP Address hostname in management_ip SNMP Community snmp_community in snmp_community SNMP Username (v3) on snmp_username in snmp_username SNMP Password (v3) on snmp_password in snmp_password SNMP Version (1, 2, or 3) snmp_version in snmp_version Index Type index_type in index_type Index Value index_value in index_value Output Type ID output_type in output_type SNMP Port snmp_port in snmp_port SNMP Authenticaion Protocol (v3) snmp_auth_protocol in snmp_auth_protocol SNMP Privacy Passphrase (v3) snmp_priv_passphrase in snmp_priv_passphrase SNMP Privacy Protocol (v3) snmp_priv_protocol in snmp_priv_protocol Daily (5 Minute Average) 0.5 1 600 86400 1|3 Weekly (30 Minute Average) 0.5 6 700 604800 1|3 Monthly (2 Hour Average) 0.5 24 775 2678400 1|3 Yearly (1 Day Average) 0.5 288 797 33053184 1|3 Hourly (1 Minute Average) 0.5 1 500 14400 1|3 Normal %8.2lf %s Turn KBytes into Bits 1 4 CURRENT_DATA_SOURCE 2 6 8000 3 2 3 LiteSpeed Vhost LiteSpeed Vhost <path_cacti>/resource/snmp_queries/litespeed_vhost.xml hash_030016bf566c869ac6443b0c75d1c32b5a350e Requests hash_00001616ed2d0aa716489be372dd598afe0b9e ReqProcessing hash_0100164fa3bc9138bd7459ed6ed6e1eccd6d32 hash_08001676fbeb01ef35493c81578394cdc9f453 ReqSecond hash_0100164fa3bc9138bd7459ed6ed6e1eccd6d32 hash_080016e5084b9e07fdcc5535637f75b8af3222 title 8 |host_description|: |query_Vhost|: Requests name hash_0100164fa3bc9138bd7459ed6ed6e1eccd6d32 9 |host_description|: |query_Vhost|: Requests LiteSpeed ExtApp LiteSpeed ExtApp <path_cacti>/resource/snmp_queries/litespeed_extapp.xml hash_030016bf566c869ac6443b0c75d1c32b5a350e Requests hash_000016974ad3f65464268b1e61142e1d377048 Req_Second hash_01001626652071e652e251bc9f2cb68a65ce0f hash_0800165d24f91f2b8d9e5598d1abd567b076f9 title 1 |host_description|: |query_Vhost|: |query_Type|: |query_ExtApp|: Reqs name hash_01001626652071e652e251bc9f2cb68a65ce0f 1 |host_description|: |query_Vhost|: |query_Type|: |query_ExtApp|: Reqs Connections hash_000016022aa61c315e6588a6acd2c013fcf5c5 EffMaxConn hash_01001626652071e652e251bc9f2cb68a65ce0f hash_080016761fd20a96d97f909f6b4ec0241344ab IdleConn hash_01001626652071e652e251bc9f2cb68a65ce0f hash_080016ca1f6af4ad148a9f858b9f9a4a3ab010 InuseConn hash_01001626652071e652e251bc9f2cb68a65ce0f hash_080016dca7bbae358416c8a86fd74cc83104d8 PoolSize hash_01001626652071e652e251bc9f2cb68a65ce0f hash_08001624140062cfa9de88c593a71be9a40e0f ConfMaxConn hash_01001626652071e652e251bc9f2cb68a65ce0f hash_080016a972198dd76a78359072a49e7b6d295e WaitQueueDepth hash_01001626652071e652e251bc9f2cb68a65ce0f hash_080016dd80f6a8dac8166b110503ac3cdbe991 title 6 |host_description|: |query_Vhost|: |query_Type|: |query_ExtApp|: Conn name hash_01001626652071e652e251bc9f2cb68a65ce0f 6 |host_description|: |query_Vhost|: |query_Type|: |query_ExtApp|: Conn LiteSpeed General LiteSpeed General <path_cacti>/resource/snmp_queries/litespeed_general.xml hash_030016bf566c869ac6443b0c75d1c32b5a350e Plain Traffic hash_000016bac5833ec4bd88e46603947c40f163dd BpsIn hash_01001664f653d42cc6cf8398fa5d55e76c1387 hash_080016f9bc5dd109ed4ab674746e66a49df3d8 BpsOut hash_01001664f653d42cc6cf8398fa5d55e76c1387 hash_0800164a9cc0ba440529238c3bb8606e5991bd title 7 |host_description|: Plain Traffic (bits/sec) name hash_01001664f653d42cc6cf8398fa5d55e76c1387 6 |host_description|: Plain Traffic (bits/sec) SSL Traffic hash_0000164740ee10c62708a97452e64c39918381 SSLBpsIn hash_01001664f653d42cc6cf8398fa5d55e76c1387 hash_0800164d9b25cf1a27c98599313c1000f001b0 SSLBpsOut hash_01001664f653d42cc6cf8398fa5d55e76c1387 hash_080016b874ed68ddc80a0ea28275a7ebfd1c3e title 7 |host_description|: SSL Traffic (bits/sec) name hash_01001664f653d42cc6cf8398fa5d55e76c1387 7 |host_description|: SSL Traffic Plain Connections hash_0000160ec40ca42977e0f88770a13629862650 PlainConn hash_01001664f653d42cc6cf8398fa5d55e76c1387 hash_0800160c86937c02cb9d97697e1c811f428cb8 AvailConn hash_01001664f653d42cc6cf8398fa5d55e76c1387 hash_080016614e73da69c6fa3034c159dfeb0b0362 title 1 |host_description|: Plain Connections name hash_01001664f653d42cc6cf8398fa5d55e76c1387 1 |host_description|: Plain Connections SSL Connections hash_000016a85d4e176d782c3bef5da7ed00cce513 SSLConn hash_01001664f653d42cc6cf8398fa5d55e76c1387 hash_08001667c11e9d5c8ee24343108fa839c89ac6 AvailSSLConn hash_01001664f653d42cc6cf8398fa5d55e76c1387 hash_0800164cb690fe79ffeb845634b5e64bcedba7 title 1 |host_description|: SSL Connections name hash_01001664f653d42cc6cf8398fa5d55e76c1387 1 |host_description|: SSL Connections PK!|snmp_monitoring/sample.phpnu[ 1 only valid LiteSpeed Enterprise (num of cpus licensed) $report_path = "/tmp/lshttpd/"; //<-- path to .rtreport folder. Default is /tmp/lshttpd/ $cache_time = 0; //<-- seconds to cache parsed data $cache_file = "/tmp/_lsws_sampe_cache.txt"; //<-- cache file..full path. //get params from snmpd pass mechanism if(array_key_exists(1,$_SERVER["argv"]) && array_key_exists(2,$_SERVER["argv"])) { $type = trim($_SERVER["argv"][1]); $oid = trim($_SERVER["argv"][2]); $bridge = new litespeed_snmp_bridge($processes, $report_path, $cache_time, $cache_file); $bridge->process($type, $oid); } ?> PK!.xcpanel/httpd_config.xmlnu[ $HOSTNAME nobody nobody 0 / 0 60M /tmp/lshttpd/swap 1 0 1 2 /usr/local/apache/bin/httpd /usr/local/apache/conf/httpd.conf %AP_PORT_OFFSET% 0 %PHP_SUEXEC% 10 $SERVER_ROOT/conf/mime.properties 1 0 2 86400 1 %ADMIN_EMAIL% $SERVER_ROOT/admin/ /usr/local/apache/logs/error_log DEBUG 0 2000M 1 1 $SERVER_ROOT/logs/access.log 2000M 30 0 index.html, index.php, index.htm 31 .htaccess 1 image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800 10000 10000 120 10000 0 10 0 0 best 4096 20M 256K 40M 1 1 4 1 null 8192 16380 500M 8K 500M 1 1 default 1 1 0 1 000 000 000 000 0 0 0 0 10000 10000 15 300 200 11 10 0 60 120 1450M 1500M 400 450 0 0 deny,log,status:403 1 / /etc/* /dev/* $SERVER_ROOT/conf/* $SERVER_ROOT/admin/conf/* ALL 35 PHP_LSAPI_CHILDREN=35 60 0 1 0 60 1400 1500 1 5 LSAPI_MAX_IDLE=60 60 0 60 0 50 1 300 3 400 500 PK!P??cpanel/httpd_config.xml.ea4nu[ $HOSTNAME nobody nobody 0 / 0 60M /tmp/lshttpd/swap 1 0 1 2 /usr/sbin/httpd /etc/apache2/conf/httpd.conf %AP_PORT_OFFSET% 0 %PHP_SUEXEC% 10 $SERVER_ROOT/conf/mime.properties 1 0 2 86400 1 %ADMIN_EMAIL% $SERVER_ROOT/admin/ /var/log/apache2/error_log DEBUG 0 2000M 1 1 $SERVER_ROOT/logs/access.log 2000M 30 0 index.html, index.php, index.htm 31 .htaccess 1 image/*=A604800,text/css=A604800,application/x-javascript=A604800,application/javascript=A604800,font/*=A604800,application/x-font-ttf=A604800 10000 10000 120 10000 0 10 0 0 best 4096 20M 256K 40M 1 1 4 1 null 8192 16380 500M 8K 500M 1 1 default 1 1 0 1 000 000 000 000 0 0 0 0 10000 10000 15 300 200 11 10 0 60 120 1450M 1500M 1400 1450 0 0 deny,log,status:403 1 / /etc/* /dev/* $SERVER_ROOT/conf/* $SERVER_ROOT/admin/conf/* ALL 35 PHP_LSAPI_CHILDREN=35 60 0 1 0 60 1400 1500 /usr/local/lsws/fcgi-bin/ea-ruby27 1 5 LSAPI_MAX_IDLE=60 60 0 60 0 50 0 300 3 400 500 PK!1pE1E11cpanel/lsws_whm_plugin/lsws_whm_plugin_install.shnuȯ#!/bin/sh # /******************************************** # LiteSpeed Web Server Plugin for WHM # # @author LiteSpeed Technologies, Inc. (https://www.litespeedtech.com) # @copyright (c) 2008-2021 # *********************************************/ # # If from lsws install, 3 params # WHM_PLUGIN_SRCDIR=$1 # LSWS_HOME=$2 # CPANEL_PLUGIN_AUTOINSTALL=$3 # WHM_PLUGIN_TEMPDIR="/usr/src/lsws_whm" WHM_DOCROOT="/usr/local/cpanel/whostmgr/docroot" WHM_PLUGIN_CGIDIR="${WHM_DOCROOT}/cgi" WHM_PLUGIN_ICONDIR="${WHM_DOCROOT}/addon_plugins" WHM_PLUGIN_INSDIR="${WHM_PLUGIN_CGIDIR}/lsws" WHM_PLUGIN_TMPL_INSDIR="${WHM_DOCROOT}/templates/lsws" WHM_PLUGIN_LSCWP_SRC_DIR="/usr/src/litespeed-wp-plugin" WHM_PLUGIN_HTTPDIR="http://www.litespeedtech.com/packages/cpanel" THEME_JUPITER_PLUGIN_DIR="/usr/local/cpanel/base/frontend/jupiter/ls_web_cache_manager" THEME_PAPER_LANTERN_PLUGIN_DIR="/usr/local/cpanel/base/frontend/paper_lantern/ls_web_cache_manager" CPANEL_PLUGIN_CAPABLE=0 if [ ! -d "${WHM_PLUGIN_CGIDIR}" ] ; then exit fi WHM_PLUGIN_INST_USER=$(id) WHM_PLUGIN_INST_USER=$(expr "${WHM_PLUGIN_INST_USER}" : 'uid=.*(\(.*\)) gid=.*') if [ "${WHM_PLUGIN_INST_USER}" != "root" ] ; then echo "Require root permission to install this plugin. Abort!" exit fi if [ "x${2}" = "x" ] ; then LSWS_HOME="/usr/local/lsws" else LSWS_HOME="${2}" fi WEBCACHE_MGR_DATA_DIR="${LSWS_HOME}/admin/lscdata" CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG="${WHM_PLUGIN_INSDIR}/cpanel_autoinstall_off" TMP_CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG="/tmp/cpanel_autoinstall_off" WHM_PLUGIN_DATA_DIR="${WHM_PLUGIN_INSDIR}/data" TMP_WHM_PLUGIN_DATA_DIR="/tmp/lsws_whm_plugin_data_tmp" WHM_PLUGIN_LSWS_HOME_FILE="${WHM_PLUGIN_INSDIR}/LSWS_HOME.config" TMP_WHM_PLUGIN_LSWS_HOME_FILE="/tmp/LSWS_HOME.config" whmPluginNeedsUpdate() { CURR_WHM_VER="${1}" if ! LATEST_WHM_VER=$(wget -qO- "${WHM_PLUGIN_HTTPDIR}/WHM_LATEST_VER"); then echo "Failed to query latest WHM plugin version. Abort!" exit; fi CURR_MAJOR=$(echo "${CURR_WHM_VER}" | awk -F"." '{print $1}') LATEST_MAJOR=$(echo "${LATEST_WHM_VER}" | awk -F"." '{print $1}') if [ "${CURR_MAJOR}" -lt "${LATEST_MAJOR}" ] ; then return 0 elif [ "${CURR_MAJOR}" -gt "${LATEST_MAJOR}" ] ; then return 1 fi CURR_MINOR=$(echo "${CURR_WHM_VER}" | awk -F"." '{print $2}') LATEST_MINOR=$(echo "${LATEST_WHM_VER}" | awk -F"." '{print $2}') if [ "${CURR_MINOR}" -lt "${LATEST_MINOR}" ] ; then return 0 elif [ "${CURR_MINOR}" -gt "${LATEST_MINOR}" ] ; then return 1 fi CURR_IMPROVEMENT=$(echo "${CURR_WHM_VER}" | awk -F"." '{print match($3, /[^ ]/) ? $3 : 0}') LATEST_IMPROVEMENT=$(echo "${LATEST_WHM_VER}" | awk -F"." '{print match($3, /[^ ]/) ? $3 : 0}') if [ "${CURR_IMPROVEMENT}" -lt "${LATEST_IMPROVEMENT}" ] ; then return 0 elif [ "${CURR_IMPROVEMENT}" -gt "${LATEST_IMPROVEMENT}" ] ; then return 1 fi CURR_PATCH=$(echo "${CURR_WHM_VER}" | awk -F"." '{print match($4, /[^ ]/) ? $4 : 0}') LATEST_PATCH=$(echo "${LATEST_WHM_VER}" | awk -F"." '{print match($4, /[^ ]/) ? $4 : 0}') if [ "${CURR_PATCH}" -lt "${LATEST_PATCH}" ] ; then return 0 elif [ "${CURR_PATCH}" -gt "${LATEST_PATCH}" ] ; then return 1 fi return 1 } echo "" echo " Install LiteSpeed Web Server Plugin for WHM" echo "==============================================" echo "" CURR_WHM_VER_FILE="${WHM_PLUGIN_INSDIR}/VERSION" if [ -e "${CURR_WHM_VER_FILE}" ] ; then CURR_WHM_VER=$(cat "${CURR_WHM_VER_FILE}") if ! whmPluginNeedsUpdate "${CURR_WHM_VER}" ; then echo "Installed WHM Plugin version already up-to-date. Abort!" exit; fi fi if [ "x${1}" = "x" ] ; then echo "... creating directories ..." # Create temp directory to install if [ ! -e "${WHM_PLUGIN_TEMPDIR}" ] ; then mkdir -v -p "${WHM_PLUGIN_TEMPDIR}" echo " Temp directory created" fi cd "${WHM_PLUGIN_TEMPDIR}" echo "... downloading latest version of the plugin ..." if ! wget \ "--output-document=${WHM_PLUGIN_TEMPDIR}/lsws_whm_plugin.tar.gz" \ "${WHM_PLUGIN_HTTPDIR}/lsws_whm_plugin.tar.gz" then /bin/rm -rf "${WHM_PLUGIN_TEMPDIR}" echo "" echo "Failed to download lsws_whm_plugin.tar.gz. Abort!" exit; fi echo "Done downloading." echo "" echo "... extracting ..." if ! tar -zxf lsws_whm_plugin.tar.gz; then /bin/rm -rf "${WHM_PLUGIN_TEMPDIR}" echo "" echo "Failed to to extract lsws_whm_plugin.tar.gz. Abort!" exit; fi echo "" fi # Create working directories for WHM PHP files and backup any existing data if [ -e "${WHM_PLUGIN_INSDIR}" ] ; then if [ -e "${WHM_PLUGIN_CGIDIR}/addon_lsws.cgi" ] ; then echo " Removing old entry script addon_lsws.cgi" /bin/rm -f "${WHM_PLUGIN_CGIDIR}/addon_lsws.cgi" fi if [ ! -e "${WEBCACHE_MGR_DATA_DIR}" ] ; then if [ -e "${LSWS_HOME}/admin" ] ; then mkdir "${WEBCACHE_MGR_DATA_DIR}" fi fi if [ -e "${CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" ] ; then /bin/mv "${CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" "${TMP_CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" fi if [ -e "${WHM_PLUGIN_DATA_DIR}" ] ; then /bin/mv "${WHM_PLUGIN_DATA_DIR}" "${TMP_WHM_PLUGIN_DATA_DIR}" fi if [ -e "${WHM_PLUGIN_LSWS_HOME_FILE}" ] ; then /bin/mv "${WHM_PLUGIN_LSWS_HOME_FILE}" "${TMP_WHM_PLUGIN_LSWS_HOME_FILE}" fi echo " Removing old working directory ${WHM_PLUGIN_INSDIR}" /bin/rm -rf "${WHM_PLUGIN_INSDIR}" fi if [ -e "${WHM_PLUGIN_TMPL_INSDIR}" ] ; then echo " Removing old template directory ${WHM_PLUGIN_TMPL_INSDIR}" /bin/rm -rf "${WHM_PLUGIN_TMPL_INSDIR}" fi #Cleanup old lsc data from installs < 2.1.12 if [ -e "${LSWS_HOME}/add-ons/webcachemgr/shared/lsc_versions_data" ] ; then /bin/rm -f "${LSWS_HOME}/add-ons/webcachemgr/shared/lsc_versions_data" fi if [ -e "${LSWS_HOME}/add-ons/webcachemgr/shared/lsc_manager_data" ] ; then /bin/rm -f "${LSWS_HOME}/add-ons/webcachemgr/shared/lsc_manager_data" fi #cleanup old lsc data/files from installs < 3.0.0 if [ -e "${WEBCACHE_MGR_DATA_DIR}/lsc_manager_data" ] ; then /bin/rm -f "${WEBCACHE_MGR_DATA_DIR}/lsc_manager_data" fi if [ -e "${WEBCACHE_MGR_DATA_DIR}/lsc_versions_data" ] ; then /bin/rm -f "${WEBCACHE_MGR_DATA_DIR}/lsc_versions_data" fi #force new data files permissions if [ -e "${WEBCACHE_MGR_DATA_DIR}/lscm.data" ] ; then chmod 600 "${WEBCACHE_MGR_DATA_DIR}/lscm.data" fi if [ -e "${WEBCACHE_MGR_DATA_DIR}/lscm.data.cust" ] ; then chmod 600 "${WEBCACHE_MGR_DATA_DIR}/lscm.data.cust" fi mkdir -v "${WHM_PLUGIN_INSDIR}" mkdir -v "${WHM_PLUGIN_TMPL_INSDIR}" if [ -e "${TMP_CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" ] ; then /bin/mv "${TMP_CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" "${CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" echo " Retained disable cPanel plugin auto install flag file" fi if [ -e "${TMP_WHM_PLUGIN_DATA_DIR}" ] ; then /bin/mv "${TMP_WHM_PLUGIN_DATA_DIR}" "${WHM_PLUGIN_DATA_DIR}" echo " Retained WHM plugin data dir files" fi if [ -e "${TMP_WHM_PLUGIN_LSWS_HOME_FILE}" ] ; then /bin/mv "${TMP_WHM_PLUGIN_LSWS_HOME_FILE}" "${WHM_PLUGIN_LSWS_HOME_FILE}" echo " Retained LSWS_HOME.config file" fi echo "" if [ "x${1}" = "x" ] ; then WHM_PLUGIN_SRCDIR="${WHM_PLUGIN_TEMPDIR}/lsws_whm_plugin" /bin/cp -r "${WHM_PLUGIN_SRCDIR}"/* "${WHM_PLUGIN_INSDIR}/" cd "${WHM_PLUGIN_INSDIR}" # # Removes install files /bin/rm -rf "${WHM_PLUGIN_TEMPDIR}" else # install from lsws addon WHM_PLUGIN_SRCDIR="${1}" /bin/cp -r "${WHM_PLUGIN_SRCDIR}"/* "${WHM_PLUGIN_INSDIR}/" echo "LSWS_HOME=${LSWS_HOME}" > "${WHM_PLUGIN_LSWS_HOME_FILE}" fi echo "... moving files ..." if [ ! -e "${WHM_PLUGIN_ICONDIR}" ] ; then mkdir -v "${WHM_PLUGIN_ICONDIR}" fi /bin/cp -f "${WHM_PLUGIN_INSDIR}/lsws_icon.png" "${WHM_PLUGIN_ICONDIR}/" /bin/mv -f "${WHM_PLUGIN_INSDIR}/lsws.html.tt" "${WHM_PLUGIN_TMPL_INSDIR}/" echo "... setting permission to files ..." chmod -R 600 "${WHM_PLUGIN_INSDIR}" chmod 700 "${WHM_PLUGIN_INSDIR}"/*.cgi chmod 700 "${WHM_PLUGIN_INSDIR}"/*.sh chmod 700 "${WHM_PLUGIN_INSDIR}/bin" chmod 700 "${WHM_PLUGIN_INSDIR}"/bin/*.sh if [ -e "${WHM_PLUGIN_INSDIR}/res/ls_web_cache_mgr" ] ; then chmod 700 "${WHM_PLUGIN_INSDIR}"/res/ls_web_cache_mgr/*.sh CPANEL_PLUGIN_CAPABLE=1; fi # update easyapache hooks "${WHM_PLUGIN_INSDIR}/bin/whm_eahook.sh" REFRESH sed -i 's/target=mainFrame/target=_self/' "${WHM_PLUGIN_INSDIR}/lsws.conf" if [ -e "/usr/local/cpanel/bin/register_appconfig" ] ; then REGISTERED=$(/usr/local/cpanel/bin/is_registered_with_appconfig whostmgr lsws) if [ "x${REGISTERED}" != "x1" ] ; then echo "Register LSWS Plugin ..." if [ ! -e "/var/cpanel/apps" ] ; then mkdir -v "/var/cpanel/apps" echo " apps registration directory created" fi else # check if config changed CHANGED=$(diff /var/cpanel/apps/lsws.conf "${WHM_PLUGIN_INSDIR}/lsws.conf") if [ "${CHANGED}" != "" ] ; then REGISTERED=0 fi fi if [ "x${REGISTERED}" != "x1" ] ; then /usr/local/cpanel/bin/register_appconfig "${WHM_PLUGIN_INSDIR}/lsws.conf" fi /bin/rm -f "${WHM_PLUGIN_INSDIR}/addon_lsws.cgi" else echo "old version no AppConfig, place entry at parent dir" /bin/mv -f "${WHM_PLUGIN_INSDIR}/addon_lsws.cgi" "${WHM_PLUGIN_CGIDIR}/" /bin/rm -f "${WHM_PLUGIN_INSDIR}/lsws.cgi" fi #Create and add needed LSCWP source directory if [ ! -e "${WHM_PLUGIN_LSCWP_SRC_DIR}" ] ; then mkdir -m 755 "${WHM_PLUGIN_LSCWP_SRC_DIR}" fi #CageFs remount for $WHM_PLUGIN_LSCWP_SRC_DIR handled in fix_cagefs.sh if [ -f "/etc/cagefs/cagefs.mp" ] ; then FORCE_REMOUNT=0 if ! grep -v 'deleted' /proc/mounts | grep -q 'litespeed-wp-plugin' ; then FORCE_REMOUNT=1 if ! grep -Eq "^${WHM_PLUGIN_LSCWP_SRC_DIR}$" /etc/cagefs/cagefs.mp; then # shellcheck disable=SC1003 sed -i -e '$a\' /etc/cagefs/cagefs.mp echo "${WHM_PLUGIN_LSCWP_SRC_DIR}" >> /etc/cagefs/cagefs.mp fi fi THIS_DIR=$( cd "$( dirname "${0}" )" && pwd ) if [ -f "${LSWS_HOME}/admin/misc/fix_cagefs.sh" ] ; then #If CageFS, add LSWS to cage if missing. "${LSWS_HOME}/admin/misc/fix_cagefs.sh" "${FORCE_REMOUNT}" elif [ -f "${THIS_DIR}/../../../admin/misc/fix_cagefs.sh" ] ; then #LSWS not installed yet, run package relative script. "${THIS_DIR}/../../../admin/misc/fix_cagefs.sh" "${FORCE_REMOUNT}" else echo "Could not find fix_cagefs.sh! Script was not executed." fi fi #Exclude LSCache files from backup CP_BACKUP_EXCLUDE_MASTER=/usr/local/cpanel/etc/cpbackup-exclude.conf CP_BACKUP_EXCLUDE_GLOBAL=/etc/cpbackup-exclude.conf if [ ! -f "${CP_BACKUP_EXCLUDE_GLOBAL}" ] && [ -f "${CP_BACKUP_EXCLUDE_MASTER}" ] ; then cp "${CP_BACKUP_EXCLUDE_MASTER}" "${CP_BACKUP_EXCLUDE_GLOBAL}" fi if [ -f "${CP_BACKUP_EXCLUDE_GLOBAL}" ] ; then grep -Fxq "lscache/" "${CP_BACKUP_EXCLUDE_GLOBAL}" FOUND="${?}" fi if [ ! -f "${CP_BACKUP_EXCLUDE_GLOBAL}" ] || [ "${FOUND}" -ne 0 ] ; then echo "lscache/" >> "${CP_BACKUP_EXCLUDE_GLOBAL}" fi ## # Install/Update cPanel Plugin if found ## if [ "${CPANEL_PLUGIN_CAPABLE}" -eq 1 ] ; then CPANEL_PLUGIN_AUTOINSTALL=1 if [ "x${3}" = "x" ] ; then if [ -e "${CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" ] ; then CPANEL_PLUGIN_AUTOINSTALL=0 fi else CPANEL_PLUGIN_AUTOINSTALL="${3}" if [ "${CPANEL_PLUGIN_AUTOINSTALL}" -eq 1 ] ; then if [ -e "${CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" ] ; then /bin/rm -f "${CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" fi else touch "${CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" fi fi LSCMCTL_SCRIPT="${LSWS_HOME}/admin/misc/lscmctl" if [ -e "${LSCMCTL_SCRIPT}" ] ; then if "${LSCMCTL_SCRIPT}" --help | grep -q 'cpanelplugin' \ && [ "${CPANEL_PLUGIN_AUTOINSTALL}" -eq 1 ] \ || [ -e "${THEME_JUPITER_PLUGIN_DIR}" ] \ || [ -e "${THEME_PAPER_LANTERN_PLUGIN_DIR}" ] then "${LSCMCTL_SCRIPT}" cpanelplugin --install fi fi fi echo "" echo " LiteSpeed WHM Plugin Installed Successfully." echo "==============================================" PK!\ׅ% rrdgraph/rrdgraph_install.shnuȯ#!/bin/sh #1. specify destination dir #2. specify lsphp5 location #3. download from litespeedtech web server(like lsapi) cat < $HOSTNAME apache apache 0 / 0 60M /tmp/lshttpd/swap 1 0 1 1 /etc/httpd/conf/httpd.conf %AP_PORT_OFFSET% 0 %PHP_SUEXEC% 10 $SERVER_ROOT/conf/mime.properties 0 2 86400 1 %ADMIN_EMAIL% $SERVER_ROOT/admin/ $SERVER_ROOT/logs/error.log DEBUG 0 2000M 1 1 $SERVER_ROOT/logs/access.log 10M 30 0 index.html, index.php, index.htm 31 .htaccess 1 image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800,font/*=A604800,application/x-font-ttf=A604800 10000 10000 120 10000 0 10 0 0 best 4096 20M 256K 40M 1 1 4 1 null 8192 16380 500M 4K 500M 1 1 default 1 1 0 1 000 000 000 000 0 0 0 0 10000 10000 15 300 200 11 10 0 60 120 1450M 1500M 1400 1450 0 0 deny,log,status:403 1 / /etc/* /dev/* $SERVER_ROOT/conf/* $SERVER_ROOT/admin/conf/* ALL php /usr/local/bin/lsphp 35 PHP_LSAPI_CHILDREN=35 60 0 1 0 60 1400 1500 1 5 LSAPI_MAX_REQS=1000 LSAPI_MAX_IDLE=60 60 0 60 0 50 1 300 3 400 500 PK!*جdirectadmin/php.ininu[[PHP] ;;;;;;;;;;; ; WARNING ; ;;;;;;;;;;; ; This is the default settings file for new PHP installations. ; By default, PHP installs itself with a configuration suitable for ; development purposes, and *NOT* for production purposes. ; For several security-oriented considerations that should be taken ; before going online with your site, please consult php.ini-recommended ; and http://php.net/manual/en/security.php. ;;;;;;;;;;;;;;;;;;; ; About this file ; ;;;;;;;;;;;;;;;;;;; ; This file controls many aspects of PHP's behavior. In order for PHP to ; read it, it must be named 'php.ini'. PHP looks for it in the current ; working directory, in the path designated by the environment variable ; PHPRC, and in the path that was defined in compile time (in that order). ; Under Windows, the compile-time path is the Windows directory. The ; path in which the php.ini file is looked for can be overridden using ; the -c argument in command line mode. ; ; The syntax of the file is extremely simple. Whitespace and Lines ; beginning with a semicolon are silently ignored (as you probably guessed). ; Section headers (e.g. [Foo]) are also silently ignored, even though ; they might mean something in the future. ; ; Directives are specified using the following syntax: ; directive = value ; Directive names are *case sensitive* - foo=bar is different from FOO=bar. ; ; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one ; of the INI constants (On, Off, True, False, Yes, No and None) or an expression ; (e.g. E_ALL & ~E_NOTICE), or a quoted string ("foo"). ; ; Expressions in the INI file are limited to bitwise operators and parentheses: ; | bitwise OR ; & bitwise AND ; ~ bitwise NOT ; ! boolean NOT ; ; Boolean flags can be turned on using the values 1, On, True or Yes. ; They can be turned off using the values 0, Off, False or No. ; ; An empty string can be denoted by simply not writing anything after the equal ; sign, or by using the None keyword: ; ; foo = ; sets foo to an empty string ; foo = none ; sets foo to an empty string ; foo = "none" ; sets foo to the string 'none' ; ; If you use constants in your value, and these constants belong to a ; dynamically loaded extension (either a PHP extension or a Zend extension), ; you may only use these constants *after* the line that loads the extension. ; ; All the values in the php.ini-dist file correspond to the builtin ; defaults (that is, if no php.ini is used, or if you delete these lines, ; the builtin defaults will be identical). ;;;;;;;;;;;;;;;;;;;; ; Language Options ; ;;;;;;;;;;;;;;;;;;;; ; Enable the PHP scripting language engine under Apache. engine = On ; Allow the tags are recognized. ; NOTE: Using short tags should be avoided when developing applications or ; libraries that are meant for redistribution, or deployment on PHP ; servers which are not under your control, because short tags may not ; be supported on the target server. For portable, redistributable code, ; be sure not to use short tags. short_open_tag = On ; Allow ASP-style <% %> tags. asp_tags = Off ; The number of significant digits displayed in floating point numbers. precision = 12 ; Enforce year 2000 compliance (will cause problems with non-compliant browsers) y2k_compliance = On ; Output buffering allows you to send header lines (including cookies) even ; after you send body content, at the price of slowing PHP's output layer a ; bit. You can enable output buffering during runtime by calling the output ; buffering functions. You can also enable output buffering for all files by ; setting this directive to On. If you wish to limit the size of the buffer ; to a certain size - you can use a maximum number of bytes instead of 'On', as ; a value for this directive (e.g., output_buffering=4096). output_buffering = Off ; You can redirect all of the output of your scripts to a function. For ; example, if you set output_handler to "mb_output_handler", character ; encoding will be transparently converted to the specified encoding. ; Setting any output handler automatically turns on output buffering. ; Note: People who wrote portable scripts should not depend on this ini ; directive. Instead, explicitly set the output handler using ob_start(). ; Using this ini directive may cause problems unless you know what script ; is doing. ; Note: You cannot use both "mb_output_handler" with "ob_iconv_handler" ; and you cannot use both "ob_gzhandler" and "zlib.output_compression". ;output_handler = ; Transparent output compression using the zlib library ; Valid values for this option are 'off', 'on', or a specific buffer size ; to be used for compression (default is 4KB) ; Note: Resulting chunk size may vary due to nature of compression. PHP ; outputs chunks that are few hundreds bytes each as a result of ; compression. If you prefer a larger chunk size for better ; performance, enable output_buffering in addition. ; Note: You need to use zlib.output_handler instead of the standard ; output_handler, or otherwise the output will be corrupted. zlib.output_compression = Off ; You cannot specify additional output handlers if zlib.output_compression ; is activated here. This setting does the same as output_handler but in ; a different order. ;zlib.output_handler = ; Implicit flush tells PHP to tell the output layer to flush itself ; automatically after every output block. This is equivalent to calling the ; PHP function flush() after each and every call to print() or echo() and each ; and every HTML block. Turning this option on has serious performance ; implications and is generally recommended for debugging purposes only. implicit_flush = Off ; The unserialize callback function will be called (with the undefined class' ; name as parameter), if the unserializer finds an undefined class ; which should be instantiated. ; A warning appears if the specified function is not defined, or if the ; function doesn't include/implement the missing class. ; So only set this entry, if you really want to implement such a ; callback-function. unserialize_callback_func= ; When floats & doubles are serialized store serialize_precision significant ; digits after the floating point. The default value ensures that when floats ; are decoded with unserialize, the data will remain the same. serialize_precision = 100 ; Whether to enable the ability to force arguments to be passed by reference ; at function call time. This method is deprecated and is likely to be ; unsupported in future versions of PHP/Zend. The encouraged method of ; specifying which arguments should be passed by reference is in the function ; declaration. You're encouraged to try and turn this option Off and make ; sure your scripts work properly with it in order to ensure they will work ; with future versions of the language (you will receive a warning each time ; you use this feature, and the argument will be passed by value instead of by ; reference). allow_call_time_pass_reference = On ; Safe Mode ; safe_mode = Off ; By default, Safe Mode does a UID compare check when ; opening files. If you want to relax this to a GID compare, ; then turn on safe_mode_gid. safe_mode_gid = Off ; When safe_mode is on, UID/GID checks are bypassed when ; including files from this directory and its subdirectories. ; (directory must also be in include_path or full path must ; be used when including) safe_mode_include_dir = ; When safe_mode is on, only executables located in the safe_mode_exec_dir ; will be allowed to be executed via the exec family of functions. safe_mode_exec_dir = ; Setting certain environment variables may be a potential security breach. ; This directive contains a comma-delimited list of prefixes. In Safe Mode, ; the user may only alter environment variables whose names begin with the ; prefixes supplied here. By default, users will only be able to set ; environment variables that begin with PHP_ (e.g. PHP_FOO=BAR). ; ; Note: If this directive is empty, PHP will let the user modify ANY ; environment variable! safe_mode_allowed_env_vars = PHP_ ; This directive contains a comma-delimited list of environment variables that ; the end user won't be able to change using putenv(). These variables will be ; protected even if safe_mode_allowed_env_vars is set to allow to change them. safe_mode_protected_env_vars = LD_LIBRARY_PATH ; open_basedir, if set, limits all file operations to the defined directory ; and below. This directive makes most sense if used in a per-directory ; or per-virtualhost web server configuration file. This directive is ; *NOT* affected by whether Safe Mode is turned On or Off. ;open_basedir = ; This directive allows you to disable certain functions for security reasons. ; It receives a comma-delimited list of function names. This directive is ; *NOT* affected by whether Safe Mode is turned On or Off. disable_functions = ; This directive allows you to disable certain classes for security reasons. ; It receives a comma-delimited list of class names. This directive is ; *NOT* affected by whether Safe Mode is turned On or Off. disable_classes = ; Colors for Syntax Highlighting mode. Anything that's acceptable in ; would work. ;highlight.string = #DD0000 ;highlight.comment = #FF9900 ;highlight.keyword = #007700 ;highlight.bg = #FFFFFF ;highlight.default = #0000BB ;highlight.html = #000000 ; ; Misc ; ; Decides whether PHP may expose the fact that it is installed on the server ; (e.g. by adding its signature to the Web server header). It is no security ; threat in any way, but it makes it possible to determine whether you use PHP ; on your server or not. expose_php = Off ;;;;;;;;;;;;;;;;;;; ; Resource Limits ; ;;;;;;;;;;;;;;;;;;; max_execution_time = 30 ; Maximum execution time of each script, in seconds max_input_time = 60 ; Maximum amount of time each script may spend parsing request data memory_limit = 32M ; Maximum amount of memory a script may consume (8MB) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Error handling and logging ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; error_reporting is a bit-field. Or each number up to get desired error ; reporting level ; E_ALL - All errors and warnings ; E_ERROR - fatal run-time errors ; E_WARNING - run-time warnings (non-fatal errors) ; E_PARSE - compile-time parse errors ; E_NOTICE - run-time notices (these are warnings which often result ; from a bug in your code, but it's possible that it was ; intentional (e.g., using an uninitialized variable and ; relying on the fact it's automatically initialized to an ; empty string) ; E_CORE_ERROR - fatal errors that occur during PHP's initial startup ; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's ; initial startup ; E_COMPILE_ERROR - fatal compile-time errors ; E_COMPILE_WARNING - compile-time warnings (non-fatal errors) ; E_USER_ERROR - user-generated error message ; E_USER_WARNING - user-generated warning message ; E_USER_NOTICE - user-generated notice message ; ; Examples: ; ; - Show all errors, except for notices ; ;error_reporting = E_ALL & ~E_NOTICE ; ; - Show only errors ; ;error_reporting = E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR ; ; - Show all errors except for notices ; error_reporting = E_ALL & ~E_NOTICE & ~E_WARNING ; Print out errors (as a part of the output). For production web sites, ; you're strongly encouraged to turn this feature off, and use error logging ; instead (see below). Keeping display_errors enabled on a production web site ; may reveal security information to end users, such as file paths on your Web ; server, your database schema or other information. display_errors = On ; Even when display_errors is on, errors that occur during PHP's startup ; sequence are not displayed. It's strongly recommended to keep ; display_startup_errors off, except for when debugging. display_startup_errors = Off ; Log errors into a log file (server-specific log, stderr, or error_log (below)) ; As stated above, you're strongly advised to use error logging in place of ; error displaying on production web sites. log_errors = Off ; Set maximum length of log_errors. In error_log information about the source is ; added. The default is 1024 and 0 allows to not apply any maximum length at all. log_errors_max_len = 1024 ; Do not log repeated messages. Repeated errors must occur in same file on same ; line until ignore_repeated_source is set true. ignore_repeated_errors = Off ; Ignore source of message when ignoring repeated messages. When this setting ; is On you will not log errors with repeated messages from different files or ; sourcelines. ignore_repeated_source = Off ; If this parameter is set to Off, then memory leaks will not be shown (on ; stdout or in the log). This has only effect in a debug compile, and if ; error reporting includes E_WARNING in the allowed list report_memleaks = On ; Store the last error/warning message in $php_errormsg (boolean). track_errors = Off ; Disable the inclusion of HTML tags in error messages. ;html_errors = Off ; If html_errors is set On PHP produces clickable error messages that direct ; to a page describing the error or function causing the error in detail. ; You can download a copy of the PHP manual from http://www.php.net/docs.php ; and change docref_root to the base URL of your local copy including the ; leading '/'. You must also specify the file extension being used including ; the dot. ;docref_root = "/phpmanual/" ;docref_ext = .html ; String to output before an error message. ;error_prepend_string = "" ; String to output after an error message. ;error_append_string = "" ; Log errors to specified file. ;error_log = filename ; Log errors to syslog (Event Log on NT, not valid in Windows 95). ;error_log = syslog ;;;;;;;;;;;;;;;;; ; Data Handling ; ;;;;;;;;;;;;;;;;; ; ; Note - track_vars is ALWAYS enabled as of PHP 4.0.3 ; The separator used in PHP generated URLs to separate arguments. ; Default is "&". ;arg_separator.output = "&" ; List of separator(s) used by PHP to parse input URLs into variables. ; Default is "&". ; NOTE: Every character in this directive is considered as separator! ;arg_separator.input = ";&" ; This directive describes the order in which PHP registers GET, POST, Cookie, ; Environment and Built-in variables (G, P, C, E & S respectively, often ; referred to as EGPCS or GPC). Registration is done from left to right, newer ; values override older values. variables_order = "EGPCS" ; Whether or not to register the EGPCS variables as global variables. You may ; want to turn this off if you don't want to clutter your scripts' global scope ; with user data. This makes most sense when coupled with track_vars - in which ; case you can access all of the GPC variables through the $HTTP_*_VARS[], ; variables. ; ; You should do your best to write your scripts so that they do not require ; register_globals to be on; Using form variables as globals can easily lead ; to possible security problems, if the code is not very well thought of. register_globals = Off ; This directive tells PHP whether to declare the argv&argc variables (that ; would contain the GET information). If you don't use these variables, you ; should turn it off for increased performance. register_argc_argv = On ; Maximum size of POST data that PHP will accept. post_max_size = 8M ; This directive is deprecated. Use variables_order instead. gpc_order = "GPC" ; Magic quotes ; ; Magic quotes for incoming GET/POST/Cookie data. magic_quotes_gpc = On ; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc. magic_quotes_runtime = Off ; Use Sybase-style magic quotes (escape ' with '' instead of \'). magic_quotes_sybase = Off ; Automatically add files before or after any PHP document. auto_prepend_file = auto_append_file = ; As of 4.0b4, PHP always outputs a character encoding by default in ; the Content-type: header. To disable sending of the charset, simply ; set it to be empty. ; ; PHP's built-in default is text/html default_mimetype = "text/html" ;default_charset = "iso-8859-1" ; Always populate the $HTTP_RAW_POST_DATA variable. ;always_populate_raw_post_data = On ;;;;;;;;;;;;;;;;;;;;;;;;; ; Paths and Directories ; ;;;;;;;;;;;;;;;;;;;;;;;;; ; UNIX: "/path1:/path2" ;include_path = ".:/php/includes" ; ; Windows: "\path1;\path2" ;include_path = ".;c:\php\includes" ; The root of the PHP pages, used only if nonempty. ; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root ; if you are running php as a CGI under any web server (other than IIS) ; see documentation for security issues. The alternate is to use the ; cgi.force_redirect configuration below doc_root = ; The directory under which PHP opens the script using /~username used only ; if nonempty. user_dir = ; Directory in which the loadable extensions (modules) reside. extension_dir = /opt/lsws/lib ; Whether or not to enable the dl() function. The dl() function does NOT work ; properly in multithreaded servers, such as IIS or Zeus, and is automatically ; disabled on them. enable_dl = Off ; cgi.force_redirect is necessary to provide security running PHP as a CGI under ; most web servers. Left undefined, PHP turns this on by default. You can ; turn it off here AT YOUR OWN RISK ; **You CAN safely turn this off for IIS, in fact, you MUST.** ; cgi.force_redirect = 1 ; if cgi.nph is enabled it will force cgi to always sent Status: 200 with ; every request. ; cgi.nph = 1 ; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape ; (iPlanet) web servers, you MAY need to set an environment variable name that PHP ; will look for to know it is OK to continue execution. Setting this variable MAY ; cause security issues, KNOW WHAT YOU ARE DOING FIRST. ; cgi.redirect_status_env = ; ; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's ; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok ; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting ; this to 1 will cause PHP CGI to fix it's paths to conform to the spec. A setting ; of zero causes PHP to behave as before. Default is zero. You should fix your scripts ; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. ; cgi.fix_pathinfo=0 ; FastCGI under IIS (on WINNT based OS) supports the ability to impersonate ; security tokens of the calling client. This allows IIS to define the ; security context that the request runs under. mod_fastcgi under Apache ; does not currently support this feature (03/17/2002) ; Set to 1 if running under IIS. Default is zero. ; fastcgi.impersonate = 1; ; Disable logging through FastCGI connection ; fastcgi.log = 0 ; cgi.rfc2616_headers configuration option tells PHP what type of headers to ; use when sending HTTP response code. If it's set 0 PHP sends Status: header that ; is supported by Apache. When this option is set to 1 PHP will send ; RFC2616 compliant header. ; Default is zero. ;cgi.rfc2616_headers = 0 ;;;;;;;;;;;;;;;; ; File Uploads ; ;;;;;;;;;;;;;;;; ; Whether to allow HTTP file uploads. file_uploads = On ; Temporary directory for HTTP uploaded files (will use system default if not ; specified). ;upload_tmp_dir = ; Maximum allowed size for uploaded files. upload_max_filesize = 16M ;;;;;;;;;;;;;;;;;; ; Fopen wrappers ; ;;;;;;;;;;;;;;;;;; ; Whether to allow the treatment of URLs (like http:// or ftp://) as files. allow_url_fopen = On ; Define the anonymous ftp password (your email address) ;from="john@doe.com" ; Define the User-Agent string ; user_agent="PHP" ; Default timeout for socket based streams (seconds) default_socket_timeout = 60 ; If your scripts have to deal with files from Macintosh systems, ; or you are running on a Mac and need to deal with files from ; unix or win32 systems, setting this flag will cause PHP to ; automatically detect the EOL character in those files so that ; fgets() and file() will work regardless of the source of the file. ; auto_detect_line_endings = Off ;;;;;;;;;;;;;;;;;;;;;; ; Dynamic Extensions ; ;;;;;;;;;;;;;;;;;;;;;; ; ; If you wish to have an extension loaded automatically, use the following ; syntax: ; ; extension=modulename.extension ; ; For example, on Windows: ; ; extension=msql.dll ; ; ... or under UNIX: ; ; extension=msql.so ; ; Note that it should be the name of the module only; no directory information ; needs to go here. Specify the location of the extension with the ; extension_dir directive above. ;Windows Extensions ;Note that MySQL and ODBC support is now built in, so no dll is needed for it. ; ;extension=php_mbstring.dll ;extension=php_bz2.dll ;extension=php_cpdf.dll ;extension=php_crack.dll ;extension=php_curl.dll ;extension=php_db.dll ;extension=php_dba.dll ;extension=php_dbase.dll ;extension=php_dbx.dll ;extension=php_domxml.dll ;extension=php_exif.dll ;extension=php_fdf.dll ;extension=php_filepro.dll ;extension=php_gd2.dll ;extension=php_gettext.dll ;extension=php_hyperwave.dll ;extension=php_iconv.dll ;extension=php_ifx.dll ;extension=php_iisfunc.dll ;extension=php_imap.dll ;extension=php_interbase.dll ;extension=php_java.dll ;extension=php_ldap.dll ;extension=php_mcrypt.dll ;extension=php_mhash.dll ;extension=php_mime_magic.dll ;extension=php_ming.dll ;extension=php_mssql.dll ;extension=php_msql.dll ;extension=php_oci8.dll ;extension=php_openssl.dll ;extension=php_oracle.dll ;extension=php_pdf.dll ;extension=php_pgsql.dll ;extension=php_printer.dll ;extension=php_shmop.dll ;extension=php_snmp.dll ;extension=php_sockets.dll ;extension=php_sybase_ct.dll ;extension=php_w32api.dll ;extension=php_xmlrpc.dll ;extension=php_xslt.dll ;extension=php_yaz.dll ;extension=php_zip.dll ;;;;;;;;;;;;;;;;;;; ; Module Settings ; ;;;;;;;;;;;;;;;;;;; [Syslog] ; Whether or not to define the various syslog variables (e.g. $LOG_PID, ; $LOG_CRON, etc.). Turning it off is a good idea performance-wise. In ; runtime, you can define these variables by calling define_syslog_variables(). define_syslog_variables = Off [mail function] ; For Win32 only. SMTP = localhost smtp_port = 25 ; For Win32 only. ;sendmail_from = me@example.com ; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). ;sendmail_path = [Java] ;java.class.path = .\php_java.jar ;java.home = c:\jdk ;java.library = c:\jdk\jre\bin\hotspot\jvm.dll ;java.library.path = .\ [SQL] sql.safe_mode = Off [ODBC] ;odbc.default_db = Not yet implemented ;odbc.default_user = Not yet implemented ;odbc.default_pw = Not yet implemented ; Allow or prevent persistent links. odbc.allow_persistent = On ; Check that a connection is still valid before reuse. odbc.check_persistent = On ; Maximum number of persistent links. -1 means no limit. odbc.max_persistent = -1 ; Maximum number of links (persistent + non-persistent). -1 means no limit. odbc.max_links = -1 ; Handling of LONG fields. Returns number of bytes to variables. 0 means ; passthru. odbc.defaultlrl = 4096 ; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char. ; See the documentation on odbc_binmode and odbc_longreadlen for an explanation ; of uodbc.defaultlrl and uodbc.defaultbinmode odbc.defaultbinmode = 1 [MySQL] ; Allow or prevent persistent links. mysql.allow_persistent = On ; Maximum number of persistent links. -1 means no limit. mysql.max_persistent = -1 ; Maximum number of links (persistent + non-persistent). -1 means no limit. mysql.max_links = -1 ; Default port number for mysql_connect(). If unset, mysql_connect() will use ; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the ; compile-time value defined MYSQL_PORT (in that order). Win32 will only look ; at MYSQL_PORT. mysql.default_port = ; Default socket name for local MySQL connects. If empty, uses the built-in ; MySQL defaults. mysql.default_socket = ; Default host for mysql_connect() (doesn't apply in safe mode). mysql.default_host = ; Default user for mysql_connect() (doesn't apply in safe mode). mysql.default_user = ; Default password for mysql_connect() (doesn't apply in safe mode). ; Note that this is generally a *bad* idea to store passwords in this file. ; *Any* user with PHP access can run 'echo get_cfg_var("mysql.default_password") ; and reveal this password! And of course, any users with read access to this ; file will be able to reveal the password as well. mysql.default_password = ; Maximum time (in seconds) for connect timeout. -1 means no limit mysql.connect_timeout = 60 ; Trace mode. When trace_mode is active (=On), warnings for table/index scans and ; SQL-Errors will be displayed. mysql.trace_mode = Off [mSQL] ; Allow or prevent persistent links. msql.allow_persistent = On ; Maximum number of persistent links. -1 means no limit. msql.max_persistent = -1 ; Maximum number of links (persistent+non persistent). -1 means no limit. msql.max_links = -1 [PostgresSQL] ; Allow or prevent persistent links. pgsql.allow_persistent = On ; Detect broken persistent links always with pg_pconnect(). Need a little overhead. pgsql.auto_reset_persistent = Off ; Maximum number of persistent links. -1 means no limit. pgsql.max_persistent = -1 ; Maximum number of links (persistent+non persistent). -1 means no limit. pgsql.max_links = -1 ; Ignore PostgreSQL backends Notice message or not. pgsql.ignore_notice = 0 ; Log PostgreSQL backends Noitce message or not. ; Unless pgsql.ignore_notice=0, module cannot log notice message. pgsql.log_notice = 0 [Sybase] ; Allow or prevent persistent links. sybase.allow_persistent = On ; Maximum number of persistent links. -1 means no limit. sybase.max_persistent = -1 ; Maximum number of links (persistent + non-persistent). -1 means no limit. sybase.max_links = -1 ;sybase.interface_file = "/usr/sybase/interfaces" ; Minimum error severity to display. sybase.min_error_severity = 10 ; Minimum message severity to display. sybase.min_message_severity = 10 ; Compatability mode with old versions of PHP 3.0. ; If on, this will cause PHP to automatically assign types to results according ; to their Sybase type, instead of treating them all as strings. This ; compatibility mode will probably not stay around forever, so try applying ; whatever necessary changes to your code, and turn it off. sybase.compatability_mode = Off [Sybase-CT] ; Allow or prevent persistent links. sybct.allow_persistent = On ; Maximum number of persistent links. -1 means no limit. sybct.max_persistent = -1 ; Maximum number of links (persistent + non-persistent). -1 means no limit. sybct.max_links = -1 ; Minimum server message severity to display. sybct.min_server_severity = 10 ; Minimum client message severity to display. sybct.min_client_severity = 10 [dbx] ; returned column names can be converted for compatibility reasons ; possible values for dbx.colnames_case are ; "unchanged" (default, if not set) ; "lowercase" ; "uppercase" ; the recommended default is either upper- or lowercase, but ; unchanged is currently set for backwards compatibility dbx.colnames_case = "unchanged" [bcmath] ; Number of decimal digits for all bcmath functions. bcmath.scale = 0 [browscap] ;browscap = extra/browscap.ini [Informix] ; Default host for ifx_connect() (doesn't apply in safe mode). ifx.default_host = ; Default user for ifx_connect() (doesn't apply in safe mode). ifx.default_user = ; Default password for ifx_connect() (doesn't apply in safe mode). ifx.default_password = ; Allow or prevent persistent links. ifx.allow_persistent = On ; Maximum number of persistent links. -1 means no limit. ifx.max_persistent = -1 ; Maximum number of links (persistent + non-persistent). -1 means no limit. ifx.max_links = -1 ; If on, select statements return the contents of a text blob instead of its id. ifx.textasvarchar = 0 ; If on, select statements return the contents of a byte blob instead of its id. ifx.byteasvarchar = 0 ; Trailing blanks are stripped from fixed-length char columns. May help the ; life of Informix SE users. ifx.charasvarchar = 0 ; If on, the contents of text and byte blobs are dumped to a file instead of ; keeping them in memory. ifx.blobinfile = 0 ; NULL's are returned as empty strings, unless this is set to 1. In that case, ; NULL's are returned as string 'NULL'. ifx.nullformat = 0 [Session] ; Handler used to store/retrieve data. session.save_handler = files ; Argument passed to save_handler. In the case of files, this is the path ; where data files are stored. Note: Windows users have to change this ; variable in order to use PHP's session functions. ; As of PHP 4.0.1, you can define the path as: ; session.save_path = "N;/path" ; where N is an integer. Instead of storing all the session files in ; /path, what this will do is use subdirectories N-levels deep, and ; store the session data in those directories. This is useful if you ; or your OS have problems with lots of files in one directory, and is ; a more efficient layout for servers that handle lots of sessions. ; NOTE 1: PHP will not create this directory structure automatically. ; You can use the script in the ext/session dir for that purpose. ; NOTE 2: See the section on garbage collection below if you choose to ; use subdirectories for session storage ;session.save_path = /tmp ; Whether to use cookies. session.use_cookies = 1 ; This option enables administrators to make their users invulnerable to ; attacks which involve passing session ids in URLs; defaults to 0. ; session.use_only_cookies = 1 ; Name of the session (used as cookie name). session.name = PHPSESSID ; Initialize session on request startup. session.auto_start = 0 ; Lifetime in seconds of cookie or, if 0, until browser is restarted. session.cookie_lifetime = 0 ; The path for which the cookie is valid. session.cookie_path = / ; The domain for which the cookie is valid. session.cookie_domain = ; Handler used to serialize data. php is the standard serializer of PHP. session.serialize_handler = php ; Define the probability that the 'garbage collection' process is started ; on every session initialization. ; The probability is calculated by using gc_probability/gc_divisor, ; e.g. 1/100 means there is a 1% chance that the GC process starts ; on each request. session.gc_probability = 1 session.gc_divisor = 100 ; After this number of seconds, stored data will be seen as 'garbage' and ; cleaned up by the garbage collection process. session.gc_maxlifetime = 1440 ; NOTE: If you are using the subdirectory option for storing session files ; (see session.save_path above), then garbage collection does *not* ; happen automatically. You will need to do your own garbage ; collection through a shell script, cron entry, or some other method. ; For example, the following script would is the equivalent of ; setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes): ; cd /path/to/sessions; find -cmin +24 | xargs rm ; PHP 4.2 and less have an undocumented feature/bug that allows you to ; to initialize a session variable in the global scope, albeit register_globals ; is disabled. PHP 4.3 and later will warn you, if this feature is used. ; You can disable the feature and the warning separately. At this time, ; the warning is only displayed, if bug_compat_42 is enabled. session.bug_compat_42 = 1 session.bug_compat_warn = 1 ; Check HTTP Referer to invalidate externally stored URLs containing ids. ; HTTP_REFERER has to contain this substring for the session to be ; considered as valid. session.referer_check = ; How many bytes to read from the file. session.entropy_length = 0 ; Specified here to create the session id. session.entropy_file = ;session.entropy_length = 16 ;session.entropy_file = /dev/urandom ; Set to {nocache,private,public,} to determine HTTP caching aspects ; or leave this empty to avoid sending anti-caching headers. session.cache_limiter = nocache ; Document expires after n minutes. session.cache_expire = 180 ; trans sid support is disabled by default. ; Use of trans sid may risk your users security. ; Use this option with caution. ; - User may send URL contains active session ID ; to other person via. email/irc/etc. ; - URL that contains active session ID may be stored ; in publically accessible computer. ; - User may access your site with the same session ID ; always using URL stored in browser's history or bookmarks. session.use_trans_sid = 0 ; The URL rewriter will look for URLs in a defined set of HTML tags. ; form/fieldset are special; if you include them here, the rewriter will ; add a hidden field with the info which is otherwise appended ; to URLs. If you want XHTML conformity, remove the form entry. ; Note that all valid entries require a "=", even if no value follows. url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=,fieldset=" [MSSQL] ; Allow or prevent persistent links. mssql.allow_persistent = On ; Maximum number of persistent links. -1 means no limit. mssql.max_persistent = -1 ; Maximum number of links (persistent+non persistent). -1 means no limit. mssql.max_links = -1 ; Minimum error severity to display. mssql.min_error_severity = 10 ; Minimum message severity to display. mssql.min_message_severity = 10 ; Compatability mode with old versions of PHP 3.0. mssql.compatability_mode = Off ; Connect timeout ;mssql.connect_timeout = 5 ; Query timeout ;mssql.timeout = 60 ; Valid range 0 - 2147483647. Default = 4096. ;mssql.textlimit = 4096 ; Valid range 0 - 2147483647. Default = 4096. ;mssql.textsize = 4096 ; Limits the number of records in each batch. 0 = all records in one batch. ;mssql.batchsize = 0 ; Specify how datetime and datetim4 columns are returned ; On => Returns data converted to SQL server settings ; Off => Returns values as YYYY-MM-DD hh:mm:ss ;mssql.datetimeconvert = On ; Use NT authentication when connecting to the server mssql.secure_connection = Off ; Specify max number of processes. -1 = library default ; msdlib defaults to 25 ; FreeTDS defaults to 4096 ;mssql.max_procs = -1 [Assertion] ; Assert(expr); active by default. ;assert.active = On ; Issue a PHP warning for each failed assertion. ;assert.warning = On ; Don't bail out by default. ;assert.bail = Off ; User-function to be called if an assertion fails. ;assert.callback = 0 ; Eval the expression with current error_reporting(). Set to true if you want ; error_reporting(0) around the eval(). ;assert.quiet_eval = 0 [Ingres II] ; Allow or prevent persistent links. ingres.allow_persistent = On ; Maximum number of persistent links. -1 means no limit. ingres.max_persistent = -1 ; Maximum number of links, including persistents. -1 means no limit. ingres.max_links = -1 ; Default database (format: [node_id::]dbname[/srv_class]). ingres.default_database = ; Default user. ingres.default_user = ; Default password. ingres.default_password = [Verisign Payflow Pro] ; Default Payflow Pro server. pfpro.defaulthost = "test-payflow.verisign.com" ; Default port to connect to. pfpro.defaultport = 443 ; Default timeout in seconds. pfpro.defaulttimeout = 30 ; Default proxy IP address (if required). ;pfpro.proxyaddress = ; Default proxy port. ;pfpro.proxyport = ; Default proxy logon. ;pfpro.proxylogon = ; Default proxy password. ;pfpro.proxypassword = [com] ; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs ;com.typelib_file = ; allow Distributed-COM calls ;com.allow_dcom = true ; autoregister constants of a components typlib on com_load() ;com.autoregister_typelib = true ; register constants casesensitive ;com.autoregister_casesensitive = false ; show warnings on duplicate constat registrations ;com.autoregister_verbose = true [Printer] ;printer.default_printer = "" [mbstring] ; language for internal character representation. ;mbstring.language = Japanese ; internal/script encoding. ; Some encoding cannot work as internal encoding. ; (e.g. SJIS, BIG5, ISO-2022-*) ;mbstring.internal_encoding = EUC-JP ; http input encoding. ;mbstring.http_input = auto ; http output encoding. mb_output_handler must be ; registered as output buffer to function ;mbstring.http_output = SJIS ; enable automatic encoding translation according to ; mbstring.internal_encoding setting. Input chars are ; converted to internal encoding by setting this to On. ; Note: Do _not_ use automatic encoding translation for ; portable libs/applications. ;mbstring.encoding_translation = Off ; automatic encoding detection order. ; auto means ;mbstring.detect_order = auto ; substitute_character used when character cannot be converted ; one from another ;mbstring.substitute_character = none; ; overload(replace) single byte functions by mbstring functions. ; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(), ; etc. Possible values are 0,1,2,4 or combination of them. ; For example, 7 for overload everything. ; 0: No overload ; 1: Overload mail() function ; 2: Overload str*() functions ; 4: Overload ereg*() functions ;mbstring.func_overload = 0 [FrontBase] ;fbsql.allow_persistent = On ;fbsql.autocommit = On ;fbsql.default_database = ;fbsql.default_database_password = ;fbsql.default_host = ;fbsql.default_password = ;fbsql.default_user = "_SYSTEM" ;fbsql.generate_warnings = Off ;fbsql.max_connections = 128 ;fbsql.max_links = 128 ;fbsql.max_persistent = -1 ;fbsql.max_results = 128 ;fbsql.batchSize = 1000 [Crack] ; Modify the setting below to match the directory location of the cracklib ; dictionary files. Include the base filename, but not the file extension. ; crack.default_dictionary = "c:\php\lib\cracklib_dict" [exif] ; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS. ; With mbstring support this will automatically be converted into the encoding ; given by corresponding encode setting. When empty mbstring.internal_encoding ; is used. For the decode settings you can distinguish between motorola and ; intel byte order. A decode setting cannot be empty. ;exif.encode_unicode = ISO-8859-15 ;exif.decode_unicode_motorola = UCS-2BE ;exif.decode_unicode_intel = UCS-2LE ;exif.encode_jis = ;exif.decode_jis_motorola = JIS ;exif.decode_jis_intel = JIS ; Local Variables: ; tab-width: 4 ; End:PK!plesk/httpd_config.xmlnu[ $HOSTNAME apache apache 0 / 0 60M /tmp/lshttpd/swap 1 0 1 2 /usr/sbin/httpd /etc/httpd/conf/httpd.conf %AP_PORT_OFFSET% 0 mod_php4,mod_php5,mod_php7,sapi_apache2,python %PHP_SUEXEC% 10 $SERVER_ROOT/conf/mime.properties 1 0 2 86400 1 %ADMIN_EMAIL% $SERVER_ROOT/admin/ /var/log/httpd/error_log DEBUG 0 2000M 1 1 $SERVER_ROOT/logs/access.log 10M 30 0 index.html, index.php, index.htm 31 .htaccess 1 image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800,font/*=A604800,application/x-font-ttf=A604800 10000 10000 120 10000 0 10 0 0 best 4096 20M 256K 40M 1 1 4 1 null 8192 16380 500M 8K 500M 1 1 default 1 1 0 1 000 000 000 000 0 0 0 0 10000 10000 15 300 200 11 10 0 60 120 1450M 1500M 1400 1450 0 0 deny,log,status:403 1 / /etc/* /dev/* $SERVER_ROOT/conf/* $SERVER_ROOT/admin/conf/* ALL logger /usr/local/psa/admin/sbin/pipelog Added for Plesk Pipe logger setup. 1 /usr/local/psa/admin/sbin/pipelog 1 10 35 PHP_LSAPI_CHILDREN=35 60 0 1 0 60 1400 1500 1 5 LSAPI_MAX_IDLE=60 60 0 60 0 50 1 300 3 400 500 PK!plesk/httpd_config.xml.debiannu[ $HOSTNAME www-data www-data 0 / 0 60M /tmp/lshttpd/swap 1 0 1 2 /usr/sbin/apache2 /etc/apache2/apache2.conf %AP_PORT_OFFSET% 0 mod_php4,mod_php5,mod_php7,sapi_apache2,python %PHP_SUEXEC% 10 APACHE_RUN_USER=www-data APACHE_RUN_GROUP=www-data APACHE_PID_FILE=%APACHE_PID_FILE% $SERVER_ROOT/conf/mime.properties 1 0 2 86400 1 %ADMIN_EMAIL% $SERVER_ROOT/admin/ /var/log/apache2/error.log DEBUG 0 2000M 1 1 $SERVER_ROOT/logs/access.log 10M 30 0 index.html, index.php, index.htm 31 .htaccess 1 image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800,font/*=A604800,application/x-font-ttf=A604800 10000 10000 120 10000 0 10 0 0 best 4096 20M 256K 40M 1 1 4 1 null 8192 16380 500M 8K 500M 1 1 default 1 1 0 1 000 000 000 000 0 0 0 0 10000 10000 15 300 200 11 10 0 60 120 1450M 1500M 1400 1450 0 0 deny,log,status:403 1 / /etc/* /dev/* $SERVER_ROOT/conf/* $SERVER_ROOT/admin/conf/* ALL logger /usr/local/psa/admin/sbin/pipelog Added for Plesk Pipe logger setup. 1 /usr/local/psa/admin/sbin/pipelog 1 10 35 PHP_LSAPI_CHILDREN=35 60 0 1 0 60 1400 1500 1 5 LSAPI_MAX_IDLE=60 60 0 60 0 50 1 300 3 400 500 PK!ECispmanager/httpd_config.xmlnu[PK!"frontpage/conf/srm.confnu[PK!ifrontpage/conf/access.confnu[PK!frontpage/conf/httpd.confnu[PK!QOhsphere/httpd_config.xmlnu[PK!os4^{{/cwp/httpd_config.xmlnu[PK!KڕGmodsec/inspectmulti.shnu7mPK!阼O Hwebcachemgr/MIN_VERnu[PK!4yTuuHwebcachemgr/autoloader.phpnuIwPK!>8{Lwebcachemgr/src/LogEntry.phpnuIwPK!g!,Swebcachemgr/src/Panel/CustomPanelExample.phpnuIwPK!a((&iwebcachemgr/src/Panel/ControlPanel.phpnuIwPK!ܐ} 4 4webcachemgr/src/Panel/Plesk.phpnuIwPK!*??%$webcachemgr/src/Panel/DirectAdmin.phpnuIwPK!Icii Udwebcachemgr/src/Panel/CPanel.phpnuIwPK!/$(vwebcachemgr/src/Panel/PhpBinaryParts.phpnuIwPK! XX)zwebcachemgr/src/Panel/CustomPanelBase.phpnuIwPK!X $+webcachemgr/src/WPInstallStorage.phpnuIwPK!l_Swebcachemgr/src/View/Model/MassDashNotifyProgressViewModel.phpnuIwPK!]B" " 9t\webcachemgr/src/View/Model/MassEnableDisableViewModel.phpnuIwPK!pLp~~?gwebcachemgr/src/View/Model/MassDashDisableProgressViewModel.phpnuIwPK![J J =pwebcachemgr/src/View/Model/FlagUnflagAllProgressViewModel.phpnuIwPK!{]7|webcachemgr/src/View/Model/CacheRootNotSetViewModel.phpnuIwPK!w8webcachemgr/src/View/Model/ScanProgressStepViewModel.phpnuIwPK!S[[Aԏwebcachemgr/src/View/Model/MassEnableDisableProgressViewModel.phpnuIwPK!z/́88.webcachemgr/src/View/Model/ManageViewModel.phpnuIwPK!35webcachemgr/src/View/Model/VersionChangeViewModel.phpnuIwPK!^=%=%8%webcachemgr/src/View/Model/Ajax/CacheMgrRowViewModel.phpnuIwPK!Q>229webcachemgr/src/View/Model/UnflagAllProgressViewModel.phpnuIwPK!`-2e webcachemgr/src/View/Model/MissingTplViewModel.phpnuIwPK!Ju 4webcachemgr/src/View/Model/ScanProgressViewModel.phpnuIwPK!G=webcachemgr/src/View/Model/RefreshStatusProgressViewModel.phpnuIwPK!L553$webcachemgr/src/View/Model/DataFileMsgViewModel.phpnuIwPK!FC!~-webcachemgr/src/View/AjaxView.phpnuIwPK! Mtt(3webcachemgr/src/View/Tpl/DataFileMsg.tplnuIwPK!O|26webcachemgr/src/View/Tpl/Blocks/InputSubmitBtn.tplnuIwPK!H}wnRR2;webcachemgr/src/View/Tpl/FlagUnflagAllProgress.tplnuIwPK!pHU U 3Awebcachemgr/src/View/Tpl/MassDashNotifyProgress.tplnuIwPK!;p` ` 4qKwebcachemgr/src/View/Tpl/MassDashDisableProgress.tplnuIwPK!I==)5Uwebcachemgr/src/View/Tpl/ScanProgress.tplnuIwPK!GU.\webcachemgr/src/View/Tpl/UnflagAllProgress.tplnuIwPK!I|*bwebcachemgr/src/View/Tpl/VersionManage.tplnuIwPK!]Z2|webcachemgr/src/View/Tpl/RefreshStatusProgress.tplnuIwPK!6Yv v .webcachemgr/src/View/Tpl/MassEnableDisable.tplnuIwPK!öfRR4webcachemgr/src/View/Tpl/Ajax/CacheMgrActionsCol.tplnuIwPK!(38webcachemgr/src/View/Tpl/Ajax/CacheMgrStatusCol.tplnuIwPK!csi1webcachemgr/src/View/Tpl/Ajax/CacheMgrFlagCol.tplnuIwPK! nn*webcachemgr/src/View/Tpl/VersionChange.tplnuIwPK!.webcachemgr/src/View/Tpl/ScanProgressStep2.tplnuIwPK!c۱'ƥwebcachemgr/src/View/Tpl/MissingTpl.tplnuIwPK!v; 6Φwebcachemgr/src/View/Tpl/MassEnableDisableProgress.tplnuIwPK! `.0webcachemgr/src/View/Tpl/ScanProgressStep1.tplnuIwPK!߭\\)webcachemgr/src/View/Tpl/DashNotifier.tplnuIwPK!?ӛ,kwebcachemgr/src/View/Tpl/CacheRootNotSet.tplnuIwPK!@66#bwebcachemgr/src/View/Tpl/Manage.tplnuIwPK!J}l0qPwebcachemgr/src/Context/RootCLIContextOption.phpnuIwPK!Q??0lTwebcachemgr/src/Context/UserCLIContextOption.phpnuIwPK!£v**# Ywebcachemgr/src/Context/Context.phpnuIwPK!\$)ewebcachemgr/src/Context/ContextOption.phpnuIwPK!vǒ2љwebcachemgr/src/Context/RootPanelContextOption.phpnuIwPK!Ď(( Şwebcachemgr/src/DashNotifier.phpnuIwPK!ȥ#*webcachemgr/src/PanelController.phpnuIwPK!_1webcachemgr/src/WPInstall.phpnuIwPK!ڻ__!0_ webcachemgr/src/PluginVersion.phpnuIwPK!YV0w0w, webcachemgr/src/UserCommand.phpnuIwPK!e,6 webcachemgr/bootstrap.phpnuIwPK! .8 webcachemgr/bootstrap_cli.phpnuIwPK!l ,< webcachemgr/VERSIONnuIwPK!*(x< lxadmin/httpd_config.xmlnu[PK!MrccS interworx/httpd_config.xmlnu[PK!jQ$>k snmp_monitoring/litespeed_extapp.xmlnu[PK!f/{ snmp_monitoring/class.litespeed_snmp_bridge.phpnu[PK!p# snmp_monitoring/litespeed_vhost.xmlnu[PK!n$PCC snmp_monitoring/READMEnu[PK!P%m snmp_monitoring/litespeed_general.xmlnu[PK!}Aff) snmp_monitoring/class.litespeed_stats.phpnu[PK!( fMfM,d snmp_monitoring/litespeed_cacti_template.xmlnu[PK!|& snmp_monitoring/sample.phpnu[PK!.xR$ cpanel/httpd_config.xmlnu[PK!P??I< cpanel/httpd_config.xml.ea4nu[PK!1pE1E11T cpanel/lsws_whm_plugin/lsws_whm_plugin_install.shnuȯPK!\ׅ% y rrdgraph/rrdgraph_install.shnuȯPK!KBB directadmin/httpd_config.xmlnu[PK!*ج directadmin/php.ininu[PK! H plesk/httpd_config.xmlnu[PK!a plesk/httpd_config.xml.debiannu[PKhh)=|