(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 ( !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';
if ( !file_exists($statusFile) ) {
throw new LSCMException(
'Cannot determine LSCache availability. Please start/switch to '
. 'LiteSpeed Web Server before trying again.',
LSCMException::E_PERMISSION
);
}
if ( ($f = fopen($statusFile, 'r')) === false ) {
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();
/**
*
* @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(
'!