File manager - Edit - /usr/local/CyberCP/lsws-6.2/add-ons/webcachemgr/src/UserCommand.php
Back
<?php /** ********************************************* * LiteSpeed Web Server Cache Manager * * @author LiteSpeed Technologies, Inc. (https://www.litespeedtech.com) * @copyright (c) 2018-2020 * ******************************************* */ namespace Lsc\Wp; use \Exception; use \Lsc\Wp\Context\Context; use \Lsc\Wp\Context\ContextOption; use \Lsc\Wp\Context\UserCLIContextOption; use \Lsc\Wp\Panel\ControlPanel; /** * Running as user - suexec */ class UserCommand { const EXIT_ERROR = 1; const EXIT_SUCC = 2; const EXIT_FAIL = 4; const EXIT_INCR_SUCC = 8; const EXIT_INCR_FAIL = 16; const EXIT_INCR_BYPASS = 32; const RETURN_CODE_TIMEOUT = 124; const CMD_STATUS = 'status'; const CMD_ENABLE = 'enable'; const CMD_DIRECT_ENABLE = 'direct_enable'; const CMD_MASS_ENABLE = 'mass_enable'; const CMD_DISABLE = 'disable'; const CMD_MASS_DISABLE = 'mass_disable'; const CMD_UPGRADE = 'upgrade'; const CMD_MASS_UPGRADE = 'mass_upgrade'; const CMD_UPDATE_TRANSLATION = 'update_translation'; const CMD_REMOVE_LSCWP_PLUGIN_FILES = 'remove_lscwp_plugin_files'; const CMD_DASH_NOTIFY = 'dash_notify'; const CMD_MASS_DASH_NOTIFY = 'mass_dash_notify'; const CMD_DASH_DISABLE = 'dash_disable'; const CMD_MASS_DASH_DISABLE = 'mass_dash_disable'; const CMD_DASH_GET_MSG = 'dash_get_msg'; const CMD_DASH_ADD_MSG = 'dash_add_msg'; const CMD_DASH_DELETE_MSG = 'dash_delete_msg'; /** * @since 1.12 * @var string */ const CMD_GET_QUICCLOUD_API_KEY = 'getQuicCloudApiKey'; /** * @var bool */ private $asUser = false; /** * @var WPInstall */ private $currInstall; /** * @var string */ private $action; /** * @var string[] */ private $extraArgs; /** * * @param boolean $asUser * @throws LSCMException Thrown indirectly. */ private function __construct( $asUser = false ) { $this->asUser = $asUser; if ( $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. */ private static function handleUnexpectedError( $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; } /** * * @since 1.9 * * @param WPInstall $wpInstall * @param string $output * @throws LSCMException Thrown indirectly. */ private static function handleGetTranslationOutput( WPInstall $wpInstall, $output ) { $translationInfo = explode(' ', $output); $locale = $translationInfo[0]; $lscwpVer = $translationInfo[1]; if ( PluginVersion::retrieveTranslation($locale, $lscwpVer) ) { $subAction = self::CMD_UPDATE_TRANSLATION; $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)); foreach ( $subOutput as $subLine ) { if ( preg_match('/BAD_TRANSLATION=(.+)/', $subLine, $m) ) { $translationInfo = explode(' ', $m[1]); $locale = $translationInfo[0]; $lscwpVer = $translationInfo[1]; PluginVersion::removeTranslationZip( $locale, $lscwpVer ); } } } } /** * * @since 1.9 * * @param WPInstall $wpInstall * @param string $line * @param int $retStatus * @param int $cmdStatus * @param string $err * @return boolean * @throws LSCMException Thrown indirectly. */ 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. */ private static function removeLeftoverLscwpFiles( $wpInstall ) { $subAction = self::CMD_REMOVE_LSCWP_PLUGIN_FILES; $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)); $wpInstall->removeNewLscwpFlagFile(); } /** * * @param string $action * @param WPInstall $wpInstall * @param mixed[] $extraArgs * @return string * @throws LSCMException Thrown indirectly. */ protected static function getIssueCmd( $action, WPInstall $wpInstall, $extraArgs = array() ) { $su = $wpInstall->getSuCmd(); $timeout = ControlPanel::PHP_TIMEOUT; $phpBin = $wpInstall->getPhpBinary(); $path = $wpInstall->getPath(); $serverName = $wpInstall->getData(WPInstall::FLD_SERVERNAME); $env = Context::getOption()->getInvokerName(); if ( $serverName === null ) { $serverName = $docRoot = 'x'; } else { $docRoot = $wpInstall->getData(WPInstall::FLD_DOCROOT); if ( $docRoot === null ) { $docRoot = 'x'; } } $modifier = implode(' ', $extraArgs); $file = __FILE__; return "{$su} -c \"cd {$path}/wp-admin && timeout {$timeout} {$phpBin} " . "{$file} {$action} {$path} {$docRoot} {$serverName} {$env}" . (($modifier !== '') ? " {$modifier}\"" : '"'); } /** * * @since 1.12 * * @param string $action * @param WPInstall $wpInstall * @param string[] $extraArgs * @return null|mixed * @throws LSCMException Thrown indirectly. */ public static function getValueFromWordPress( $action, WPInstall $wpInstall, $extraArgs = array() ) { $ret = null; if ( !self::preIssueValidation($action, $wpInstall, $extraArgs) ) { return $ret; } $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)); $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; } /** * * @param string $action * @param WPInstall $wpInstall * @param string[] $extraArgs * @return boolean * @throws LSCMException Thrown indirectly. */ public static function issue( $action, WPInstall $wpInstall, $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 ( ($pos = 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( &$args ) { $wpPath = array_shift($args); if ( !$wpPath || !is_dir($wpPath) ) { return null; } $docRoot = array_shift($args); if ( !$docRoot ) { return null; } $serverName = array_shift($args); if ( !$serverName ) { return null; } /** * LSCWP_REF used by LSCWP plugin. */ $env = array_shift($args); define('LSCWP_REF', $env); $install = new WPInstall($wpPath); if ( $docRoot != 'x' ) { $install->setDocRoot($docRoot); } if ( $serverName != 'x' ) { $install->setServerName($serverName); } return $install; } /** * * @param string $action * @param WPInstall $wpInstall * @param string[] $extraArgs Not used at the moment. * @return boolean * @throws LSCMException Thrown directly and indirectly. * * @noinspection PhpUnusedParameterInspection */ private static function preIssueValidation( $action, WPInstall $wpInstall, $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: /** @noinspection PhpMissingBreakStatementInspection */ 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 echo'd output format to include "[LOG][$lvl] $msg". * Stopped echo'ing "[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, true); 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; } /** * * @param string $action * @return boolean */ private 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 boolean */ 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. */ private static function getUserCommand() { /** * Check if invoked from shell. */ if ( empty($_SERVER['argv']) ) { return null; } $args = $_SERVER['argv']; $script = array_shift($args); if ( $script != __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. */ public static function run() { if ( $cmd = self::getUserCommand() ) { if ( !defined('LSCM_RUN_AS_USER') ) { define('LSCM_RUN_AS_USER', 1); } $ret = $cmd->runAsUser(); exit($ret); } } } /** * This should only be invoked from command line. * * @noinspection PhpUnhandledExceptionInspection */ UserCommand::run();
| ver. 1.4 |
Github
|
.
| PHP 8.2.28 | Generation time: 0.02 |
proxy
|
phpinfo
|
Settings