AlkantarClanX12
Current Path : /usr/local/lsws/admin/html/classes/ws/ |
Current File : //usr/local/lsws/admin/html/classes/ws/Service.php |
<?php require_once('blowfish.php'); class Service { private $cmd = null; public $cmdStatus = null; public $act = null; public $actId = null; public $FNAME = null; public $FSTATUS = null; public $FPID = null; public $serverLog = null; public $serverLastModTime = 100; public $listeners = []; public $adminL = []; public $vhosts = []; public $awstats = []; public $serv = []; public $license = []; public $debugOn = null; public $messages = []; public function __construct() { $this->FNAME = '/tmp/lshttpd/.admin'; $this->FSTATUS = '/tmp/lshttpd/.status'; $this->FPID = '/tmp/lshttpd/lshttpd.pid'; } public function init() { clearstatcache(); $this->serverLastModTime = filemtime($this->FSTATUS); $this->readStatus(); } public function refreshConf($data) { $listeners = $data['listener']; foreach ($listeners as $lname => $addr) { if (!isset($this->listeners[$lname])) { $this->listeners[$lname] = []; $this->listeners[$lname]['addr'] = $addr; $this->listeners[$lname]['status'] = 'Error'; } } $vhnames = $data['vhost']; // first char 0|1 (active|inactive), 2nd char A:in conf only, M: in both, S: in status only foreach ($vhnames as $vhname) { if (!isset($this->vhosts[$vhname])) { $this->vhosts[$vhname] = '0A'; } else { $this->vhosts[$vhname] = substr($this->vhosts[$vhname], 0, 1) . 'M'; } } $this->serv['name'] = $data['serv']; if (array_key_exists('awstats', $data)) { $this->awstats = $data['awstats']; } else { $this->awstats = null; } $fd = fopen($this->FPID, 'r'); if ($fd) { $this->serv['pid'] = trim(fgets($fd)); fclose($fd); } $this->serverLog = $data['servLog']; } public function process($act, $actId) { $this->act = $act; $this->actId = $actId; if ($act == 'RESET_ALL_PHP_PROCESSES') { $this->resetphp(); return true; } if ($this->isPending()) { return false; } $this->checkLastMod(); if (( $act == 'upgrade' ) || ( $act == 'switchTo' ) || ( $act == 'validatelicense' ) || ( $act == 'remove' )) { $this->vermgr(); } elseif ($actId) { $this->vhostControl(); } elseif ($act == 'restart') { $this->restartServer(); } elseif ($act == 'toggledbg') { $this->cmd = ['toggledbg']; $this->issueCmd(); sleep(2); $this->readStatus(); } return true; } private function resetphp() { $touchfile = $_SERVER['LS_SERVER_ROOT'] . "admin/tmp/.lsphp_restart.txt"; //fixed location if (touch($touchfile)) { $this->messages[] = ['success', 'Successfully notified LiteSpeed server to restart all detached PHP processes.']; } else { $this->messages[] = ['error', 'Failed to notify LiteSpeed server to restart all detached PHP processes.']; } } public function waitForChange() { for ($count = 0; $count < 5; ++$count) { if ($this->checkLastMod()) { return true; } sleep(1); } return false; } private function readStatus() { $this->listeners = []; $this->adminL = []; $this->vhosts = []; $this->license = []; $fd = fopen($this->FSTATUS, 'r'); if (!$fd) { return false; } while (!feof($fd)) { $buffer = fgets($fd, 512); if (strncmp($buffer, 'LISTENER0', 9) == 0) { $this->readListener($this->listeners, $buffer, $fd); } elseif (strncmp($buffer, 'LISTENER1', 9) == 0) { $this->readListener($this->adminL, $buffer, $fd); } elseif (strncmp($buffer, 'VHOST', 5) == 0) { $this->readVh($buffer, $fd); } elseif (strncmp($buffer, 'DEBUG_LOG: ', 11) == 0) { $this->debugOn = (substr($buffer, 11, 1) === '1') ? true : false; } elseif (strncmp($buffer, 'LICENSE', 7) == 0 || strncmp($buffer, 'FEATURES', 8) == 0) { $this->readLicenseInfo($buffer, $d); } elseif (strncmp($buffer, 'EOF', 3) == 0) { break; } } fclose($fd); return true; } private function readListener(&$l, $buffer, &$fd) { $m = []; if (preg_match("/\[(.+)\] (.+)$/", $buffer, $m)) { $lname = $m[1]; $l[$lname]['addr'] = $m[2]; $l[$lname]['status'] = 'Running'; $tmp = fgets($fd, 512); while (strncmp($tmp, 'ENDL', 4) != 0) { if (strncmp($tmp, 'LVMAP', 5) == 0) { $tm = []; if (preg_match("/\[(.+)\] (.+)$/", $tmp, $tm)) { $l[$lname]['map'][$tm[1]][] = $tm[2]; } } $tmp = fgets($fd, 512); } } } private function readVh($buffer, &$fd) { $m = []; if (preg_match("/\[(.+)\] ([01])/", $buffer, $m)) { $vname = $m[1]; if ($vname != '_AdminVHost') { $this->vhosts[$m[1]] = $m[2] . 'S'; } } } private function readLicenseInfo($buffer, &$fd) { // LICENSE_EXPIRES: 0, UPDATE_EXPIRES: 1597636800, SERIAL: , TYPE: 9:2 $m = []; if (preg_match("/^LICENSE_EXPIRES: (\d+), UPDATE_EXPIRES: (\d+), SERIAL: (.+), TYPE: (.+)$/", $buffer, $m)) { $this->license['expires'] = $m[1]; $this->license['updateExpires'] = $m[2]; $this->license['serial'] = $m[3]; $proc = trim($m[4]); if ($this->license['expires'] == 0) { $this->license['expires_date'] = 'Never'; } else { $this->license['expires_date'] = date('M d, Y', $this->license['expires']); } $this->license['updateExpires_date'] = date('M d, Y', $this->license['updateExpires']); // translate proc to type $this->license['proc'] = $proc; $this->license['type'] = $this->translateLicProc($proc); } else if (preg_match("/FEATURES: (\d+)$/", $buffer, $m)) { $feature = $m[1]; $this->license['feature'] = $feature; if (($feature & 1) == 0 && $this->license['proc'] == 1) { // no cache, old 1-CPU license $this->license['type'] = '1-CPU License (1-Worker)'; } } } private function translateLicProc($proc) { if (strncmp($proc, '9:', 2) == 0) { return 'Web Host Elite (X-Worker = ' . substr($proc, 2) . ')'; } switch ($proc) { // old type, to be retired case 'V': return 'VPS License (1-Worker with 2GB Memory Limit)'; case 'U': case 'VU': case 'U1': return 'UltraVPS License (1-Worker with 8GB Memory Limit)'; case '8': return '8-CPU License (8-Worker)'; // current ones case 'F': return 'Free Starter (1-Domain & 1-Worker with 2GB Memory Limit)'; case 'S': // SiteOwner return 'Site Owner Plus (5-Domain & 1-Worker)'; case 'SM': // SiteOwner with memeory limit return 'Site Owner (5-Domain 1-Worker with 8GB Memory Limit)'; case 'D': // domain limit return 'Domain Limited (limited-Domain 1-Worker)'; case 'DM': // domain and memory limit return 'Domain Limited (limited-Domain 1-Worker with 8GB Memory Limit)'; case '1M': // 1cpu with memory limit return 'Web Host Lite (1-Worker with 8GB Memory Limit)'; case '1': return 'Web Host Essential (1-Worker)'; case '2': return 'Web Host Professional (2-Worker)'; case '3': return 'Dedicated (3-Worker)'; case '4': return 'Web Host Enterprise (4-Worker)'; case 'X': case '9': // failsafe, should not happen return 'Web Host Elite (X-Worker)'; default : return '1-Worker'; // do not error out to be safe } } public function checkLastMod() { clearstatcache(); $mt = filemtime($this->FSTATUS); if ($this->serverLastModTime != $mt) { $this->serverLastModTime = $mt; return true; } return false; } public function restartServer() { $this->cmd = ['restart']; CLIENT::singleton()->setChanged(false); $this->issueCmd(); } public function vermgr() { if ($this->act == 'switchTo') { $this->cmd = array("mgrver:$this->actId"); } elseif ($this->act == 'remove') { $this->cmd = array("mgrver:-d $this->actId"); } elseif ($this->act == 'upgrade') { $product = PRODUCT::GetInstance(); $edition = 'std'; if ($product->edition == 'ENTERPRISE') { $edition = 'ent'; } $this->cmd = array("{$this->act}:{$this->actId}-$edition"); } elseif ($this->act == 'validatelicense') { $this->cmd = ['ValidateLicense']; } else { unset($this->cmd); return; //illegal action } $this->issueCmd(); $this->waitForChange(); $this->readStatus(); } public function vhostControl() { $this->cmd = array("$this->act:vhost:$this->actId"); $this->issueCmd(); $this->waitForChange(); $this->readStatus(); } public function install($app) { $this->cmd = array('install:' . $app); $this->issueCmd(); } public static function getCommandSocket($cmd) { if (strncmp($_SERVER['LSWS_ADMIN_SOCK'], 'uds://', 6) == 0) { $sock = socket_create(AF_UNIX, SOCK_STREAM, 0); $chrootOffset = 0; if (isset($_SERVER['LS_CHROOT'])) { $chrootOffset = strlen($_SERVER['LS_CHROOT']); } $addr = substr($_SERVER['LSWS_ADMIN_SOCK'], 5 + $chrootOffset); if (socket_connect($sock, $addr) == false) { error_log("failed to connect to server addr ($addr)! socket_connect() failed: " . socket_strerror(socket_last_error()) . "\n"); return false; } } else { $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $addr = explode(':', $_SERVER['LSWS_ADMIN_SOCK']); if (socket_connect($sock, $addr[0], intval($addr[1])) == false) { error_log('failed to connect to server (' . $_SERVER['LSWS_ADMIN_SOCK'] . ')! socket_connect() failed: ' . socket_strerror(socket_last_error()) . "\n"); return false; } } $clientid = CLIENT::singleton()->getIdData(); $uid = PMA_blowfish_decrypt($clientid['id'], $clientid['sec0']); $password = PMA_blowfish_decrypt($clientid['pass'], $clientid['sec1']); $outBuf = "auth:" . $uid . ':' . $password . "\n"; $outBuf .= $cmd . "\n" . 'end of actions'; socket_write($sock, $outBuf); socket_shutdown($sock, 1); return $sock; } private function issueCmd() { CLIENT::singleton()->reauthenticate(); $commandline = ''; foreach ($this->cmd as $line) { $commandline .= $line . "\n"; } $sock = Service::getCommandSocket($commandline); if ($sock != false) { $res = socket_recv($sock, $buffer, 1024, 0); socket_close($sock); return (( $res > 0 ) && (strncasecmp($buffer, 'OK', 2) == 0 )); } return false; } public static function retrieveCommandData($cmd) { $sock = Service::getCommandSocket($cmd); $buffer = ''; if ($sock != false) { $read = [$sock]; $write = null; $except = null; $num_changed_sockets = socket_select($read, $write, $except, 3); //wait for max 3 seconds if ($num_changed_sockets === false) { error_log("socket_select failed: " . socket_strerror(socket_last_error())); } elseif ($num_changed_sockets > 0) { while (socket_recv($sock, $data, 8192, 0)) { $buffer .= $data; } } socket_close($sock); } return $buffer; } public function isPending() { if (file_exists($this->FNAME)) { $this->cmdStatus = 'IS_PENDING'; return true; } return false; } public function getLogData() { $data = []; $data['filename'] = $this->getServerLog(); $level = DUtil::getGoodVal(DUtil::grab_input('request', 'sel_level')); if ($level == null) { $level = 'I'; } if (!in_array($level, ['E', 'W', 'N', 'I', 'D'])) { return null; } $data['level'] = $level; $fd = fopen($data['filename'], 'r'); if (!$fd) { return null; } fseek($fd, 0, SEEK_END); $endpos = ftell($fd); fclose($fd); $data['logSize'] = number_format($endpos / 1024, 2); $searchSize = (int) DUtil::getGoodVal(DUtil::grab_input('request', 'searchSize')); if ($searchSize <= 0) { $searchSize = 20; } elseif ($searchSize > 512) { $searchSize = 512; } $data['searchSize'] = $searchSize; $searchFrom = (int) DUtil::getGoodVal(DUtil::grab_input('request', 'searchFrom')); if (isset($_REQUEST['end'])) { $searchFrom = $endpos; } else { if (isset($_REQUEST['prev'])) { $searchFrom -= $searchSize; } elseif (isset($_REQUEST['next'])) { $searchFrom += $searchSize; } elseif (isset($_REQUEST['begin'])) { $searchFrom = 0; } if ($searchFrom < 0) { $searchFrom = 0; } $data['searchFrom'] = $searchFrom; $searchFrom *= 1024; } $searchSize *= 1024; if ($searchFrom >= $endpos) { $searchFrom = $endpos - $searchSize; if ($searchFrom < 0) { $searchFrom = 0; } $data['searchFrom'] = number_format($searchFrom / 1024, 2, '.', ''); } if ($searchFrom + $searchSize < $endpos) { $endpos = $searchFrom + $searchSize; } $data['fromPos'] = (int) $searchFrom; $data['endPos'] = (int) $endpos; return $data; } public function showErrLog(&$buf, $len = 20480) { $buf = []; $data = []; $data['filename'] = $this->getServerLog(); $data['level'] = 'W'; $fd = fopen($data['filename'], 'r'); if (!$fd) { $buf[] = 'Failed read server log file from ' . $data['filename']; return 0; } fseek($fd, 0, SEEK_END); $data['endPos'] = ftell($fd); if ($data['endPos'] > $len) { $data['fromPos'] = $data['endPos'] - $len; } else { $data['fromPos'] = 0; } fclose($fd); $res = $this->getLog($data); if ($res[0] == 0) { return 0; } if ($res[0] > 10) { $r = explode("\n", $res[2]); $i = count($r) - 11; for ($j = 0; $j < 10; ++$j) { $buf[] = $r[$i + $j]; } $res[0] = 'last 10'; } else { $buf[] = $res[2]; } return $res[0]; } public function getLog($data) { $newlineTag = '[ERR[WAR[NOT[INF[DEB'; $levels = array('E' => 1, 'W' => 2, 'N' => 3, 'I' => 4, 'D' => 5); $level = $levels[substr($data['level'], 0, 1)]; $fd = fopen($data['filename'], 'r'); if (!$fd) { echo '<tr><td class="message_error" colspan=3>Failed to read server log from file ' . $data['filename'] . '</td></tr>'; exit; } $endpos = $data['endPos']; fseek($fd, (int)$data['fromPos']); $start = 0; $result = ''; $totalLine = 0; $line = 0; $cutline = 0; $buffer = fgets($fd); while (!preg_match("/^\d{4}-\d{2}-\d{2} /", $buffer)) { $buffer = fgets($fd); if ($buffer === false) { break; } $curpos = ftell($fd); if ($curpos >= $endpos) { break; } } do { $buffer = chop($buffer); // check if new line $c28 = substr($buffer, 28, 3); if ($c28 && strstr($newlineTag, $c28)) { // is new line $totalLine ++; if ($start) { // finish prior line $result .= '</td></tr>' . "\n"; $start = 0; } $b28 = substr($c28, 0, 1); if ($levels[$b28] <= $level) { // start a new line $start = 1; $line ++; $style = 'log_' . $b28; $result .= '<tr><td class="col_time ' . $style . '0">' . substr($buffer, 0, 26); $result .= '</td><td class="col_level ' . $style . '1">'; $i = strpos($buffer, ']', 27); $result .= ( substr($buffer, 28, $i - 28) ); $result .= '</td><td class="col_mesg ' . $style . '2">'; $result .= htmlspecialchars(substr($buffer, $i + 2)); } } elseif ($start) { // multi-line output $result .= '<br>' . htmlspecialchars($buffer); } $curpos = ftell($fd); if ($curpos >= $endpos) { break; } } while ($buffer = fgets($fd)); fclose($fd); if ($start) { $result .= '</td></tr>' . "\n"; } $res = []; $res[] = $line; $res[] = $totalLine; $res[] = $result; return $res; } public function getServerLog() { if ($this->serverLog == null) { require_once('ConfigFileEx.php'); $confpath = $_SERVER['LS_SERVER_ROOT'] . "conf/httpd_config.xml"; //fixed location $logpath = ConfigFileEx::grepTagValue($confpath, 'logging.log.fileName'); $this->serverLog = str_replace('//', '/', str_replace('$SERVER_ROOT', $_SERVER['LS_SERVER_ROOT'], $logpath)); } return $this->serverLog; } public function download($version) { //validate param if (!preg_match("/^\d+\.\d+(\.\d+)?(RC\d+)?$/", $version)) { return false; } $product = PRODUCT::GetInstance(); // e.g.: 'lsws-4.0.10-ent-i386-linux.tar.gz' $edition = 'std'; if ($product->edition == 'ENTERPRISE') { $edition = 'ent'; } $platform = $_SERVER['LS_PLATFORM']; if (strpos($platform, 'freebsd') !== false) { $pfrelease = explode('.', php_uname('r')); if ($pfrelease[0] >= 6) { $platform .= '6'; } } $main_ver = $version[0] . '.0'; $file = strtolower($product->type) . '-' . $version . '-' . $edition . '-' . $platform . '.tar.gz'; $downloadurl = 'http://download.litespeedtech.com/packages/' . $main_ver . '/' . $file; $savedfile = $_SERVER['LS_SERVER_ROOT'] . 'autoupdate/' . $file; //echo "download url: $downloadurl\n"; $buffer = file_get_contents($downloadurl); if ($buffer == false) { return false; } $saved = fopen($savedfile, 'wb'); if ($saved == false) { return false; } $i = fwrite($saved, $buffer); if (!fclose($saved) || $i == false) { return false; } return true; } public function loadParam(&$holder, $line) { $t = preg_split('/[\s,:]/', $line, -1, PREG_SPLIT_NO_EMPTY); $c = count($t) / 2; for ($i = 0; $i < $c; ++$i) { if (is_array($holder) && array_key_exists($t[2 * $i], $holder)) { $holder[$t[2 * $i]] += $t[2 * $i + 1]; } else { $holder[$t[2 * $i]] = $t[2 * $i + 1]; } } } public static function GetLoadAvg() { $avgload = \sys_getloadavg(); if ($avgload === false) { return 'N/A'; } return implode(', ', array_map(function($load) { return round($load, 3); }, $avgload)); } }