FNAME = '/tmp/lshttpd/.admin'; $this->FSTATUS = '/tmp/lshttpd/.status'; $this->FPID = '/tmp/lshttpd/lshttpd.pid'; } function init() { clearstatcache(); $this->serverLastModTime = filemtime($this->FSTATUS); $this->readStatus(); } function refreshConf($data) { $listeners = $data['listener']; foreach( $listeners as $lname => $addr ) { if ( !isset($this->listeners[$lname]) ) { $this->listeners[$lname] = array(); $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 = array('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.']; } } function waitForChange() { for( $count = 0; $count < 5; ++$count) { if ( !$this->checkLastMod() ) sleep(1); else return true; } return false; } private function readStatus() { $this->listeners = array(); $this->adminL = array(); $this->vhosts = array(); $this->license = array(); $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) { if (substr($buffer, 11, 1) === '1') $this->debugOn = true; else $this->debugOn = 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) { if ( preg_match( "/\[(.+)\] (.+)$/", $buffer, $matches )) { $lname = $matches[1]; $l[$lname]['addr'] = $matches[2]; $l[$lname]['status'] = 'Running'; $tmp = fgets($fd, 512); while ( strncmp($tmp, 'ENDL' ,4) != 0 ) { if ( strncmp( $tmp, 'LVMAP', 5 ) == 0) { if ( preg_match( "/\[(.+)\] (.+)$/", $tmp, $tm )) { $l[$lname]['map'][$tm[1]][] = $tm[2]; } } $tmp = fgets($fd, 512); } } } private function readVh($buffer, &$fd) { 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 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 } } function checkLastMod() { clearstatcache(); $mt = filemtime($this->FSTATUS); if ( $this->serverLastModTime != $mt ) { $this->serverLastModTime = $mt; return true; } else { return false; } } function restartServer() { $this->cmd = array('restart'); CLIENT::singleton()->setChanged(false); $this->issueCmd(); } 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 = array('ValidateLicense'); } else { unset( $this->cmd ); return; //illegal action } $this->issueCmd(); $this->waitForChange(); $this->readStatus(); } function vhostControl() { $this->cmd = array("$this->act:vhost:$this->actId"); $this->issueCmd(); $this->waitForChange(); $this->readStatus(); } function install( $app ) { $this->cmd = array('install:' . $app); $this->issueCmd(); } public static function getCommandSocket($cmd) { $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'; 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; } } 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 )); } else return FALSE; } public static function retrieveCommandData($cmd) { $sock = Service::getCommandSocket($cmd); $buffer = ''; if ($sock != FALSE) { $read = array($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())); } else if ($num_changed_sockets > 0) { while (socket_recv($sock, $data, 8192, 0)) { $buffer .= $data; } } socket_close( $sock ); } return $buffer; } function isPending() { if ( file_exists($this->FNAME) ) { $this->cmdStatus = 'IS_PENDING'; return true; } else return false; } function getLogData() { $data = array(); $data['filename'] = $this->getServerLog(); $level = DUtil::getGoodVal(DUtil::grab_input('request','sel_level')); if ( $level == NULL ) $level = 'I'; if (!in_array($level, array('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; else if ($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'] = $searchFrom; $data['endPos'] = $endpos; return $data; } function showErrLog(&$buf, $len=20480) { $buf = array(); $data = array(); $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]; } 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 '