HEX
Server: LiteSpeed
System: Linux php-prod-1.spaceapp.ru 5.15.0-157-generic #167-Ubuntu SMP Wed Sep 17 21:35:53 UTC 2025 x86_64
User: xnsbb3110 (1041)
PHP: 8.1.33
Disabled: NONE
Upload Files
File: //usr/local/lsws/admin/html/lib/ControllerBase.php
<?php

class ControllerBase
{
	protected $_serv;
	protected $_admin;
	protected $_curOne; //vh or tp
	protected $_special;

	protected $_disp;
	protected $_service;

	protected static $_instance = null;

	protected function __construct()
	{
		$this->_disp = DInfo::singleton();
	}

	public static function singleton()
	{
		if (!isset(self::$_instance)) {
			$c = __CLASS__;
			self::$_instance = new $c;
		}

		return self::$_instance;
	}

	public static function ConfigDispData()
	{
		$cc = self::singleton();

		$data = $cc->process_config();
		// temp
		if (is_a($data, 'CData'))
			$data = $data->GetRootNode();

		$cc->_disp->Set(DInfo::FLD_PgData, $data);

		return $cc->_disp;
	}

	public static function ServiceData($type)
	{
		$cc = self::singleton();
		$data = $cc->process_service_data($type);

		return $data;
	}

	public static function ServiceRequest($type, $actId = '')
	{
		$cc = self::singleton();
		$result = $cc->process_service_request($type, $actId);

		return $result;
	}

	public static function HasChanged()
	{
		return (isset($_SESSION['changed']) ? $_SESSION['changed'] : false);
	}

	public static function getServerLoad()
	{
		$avgload = \sys_getloadavg();
		if ($avgload === false) {
			return 'N/A';
		}
		return implode(', ', array_map(function($load) { return round($load, 3); }, $avgload));
	}

	protected function setChanged($changed)
	{
		$_SESSION['changed'] = $changed;
	}

	protected function getConfFilePath($type, $name='')
	{
		$path = null;

		if ( $type == DInfo::CT_SERV) {
			$path = SERVER_ROOT . 'conf/httpd_config.conf' ; //fixed location
		}
		elseif ( $type ==  DInfo::CT_ADMIN) {
			$adminRoot = PathTool::GetAbsFile('$SERVER_ROOT/admin/','SR'); //fixed loc

			if ($name == '') {
				$path = $adminRoot . 'conf/admin_config.conf' ;
			} elseif ($name == 'key') {
				$path = $adminRoot . 'conf/jcryption_keypair' ;
			}
		}
		elseif ( $type ==  DInfo::CT_VH ) {
			$vh = $this->_serv->GetChildNodeById('virtualhost', $name);
			if ($vh != null) {
				$vhrootpath = $vh->GetChildVal('vhRoot');
				$path = PathTool::GetAbsFile($vh->GetChildVal('configFile'), 'VR', $name, $vhrootpath);
			}
			else {
				die ("cannot find config file for vh $name\n");
				// should set as conf err
			}
		}
		elseif ($type == DInfo::CT_TP) {
			$tp = $this->_serv->GetChildNodeById('vhTemplate', $name);
			if ($tp != null)
				$path = PathTool::GetAbsFile($tp->GetChildVal('templateFile'), 'SR');
			else {
				die ("cannot find config file for tp $name\n");
				// should set as conf err
			}
		}

		return $path;
	}

	protected function getConfData()
	{
		$view = $this->_disp->Get(DInfo::FLD_View);
		$pid = $this->_disp->Get(DInfo::FLD_PID);
		$tid = $this->_disp->Get(DInfo::FLD_TID);

		if ( ($view == DInfo::CT_SERV && $tid && strpos($tid, 'S_MIME') !== false)
			|| ($view == DInfo::CT_ADMIN && $pid == 'usr')
			|| ($view == DInfo::CT_VH && $tid && (strpos($tid, 'V_UDB') !== false || strpos($tid, 'V_GDB') !== false))) {
			$confdata = $this->_special;
		}
		elseif (($view == DInfo::CT_VH && $pid != 'base') || ($view == DInfo::CT_TP && $pid != 'mbr')) {
			$confdata = $this->_curOne;
		}
		elseif ($this->_disp->Get(DInfo::FLD_ConfType) == DInfo::CT_ADMIN) {
			$confdata = $this->_admin;
		}
		else  {
			$confdata = $this->_serv;
		}

		$this->_disp->Set(DInfo::FLD_ConfData, $confdata);
		return $confdata;
	}

	protected function load_server_config($load_admin=false)
	{
		$this->_serv = new CData(DInfo::CT_SERV, $this->getConfFilePath(DInfo::CT_SERV));
		$this->_disp->Set(DInfo::FLD_ServData, $this->_serv);
		if (($conferr = $this->_serv->GetConfErr()) != null) {
			$this->_disp->Set(DInfo::FLD_TopMsg, $conferr);
		}

		$has_set_timout = CAuthorizer::HasSetTimeout();
		if (!$has_set_timout || $load_admin) {
			$this->_admin = new CData(DInfo::CT_ADMIN, $this->getConfFilePath(DInfo::CT_ADMIN));
			if (($conferr = $this->_admin->GetConfErr()) != null)
				$this->_disp->Set(DInfo::FLD_TopMsg, $conferr);

			if (!$has_set_timout) {
				$timeout = $this->_admin->GetChildVal('sessionTimeout');
				if ($timeout == null)
					$timeout = 60; // default
				CAuthorizer::SetTimeout($timeout);
			}
		}
	}

	protected function loadConfig()
	{
		// always load serv
		$this->load_server_config(($this->_disp->Get(DInfo::FLD_ConfType) == DInfo::CT_ADMIN));

		$view = $this->_disp->Get(DInfo::FLD_View);
		$pid = $this->_disp->Get(DInfo::FLD_PID);
		$tid = $this->_disp->Get(DInfo::FLD_TID);

		if (($view == DInfo::CT_VH && $pid != 'base') || ($view == DInfo::CT_TP && $pid != 'mbr')) {
			$confpath = $this->getConfFilePath($view, $this->_disp->Get(DInfo::FLD_ViewName));
			$this->_curOne = new CData($view, $confpath);
			if (($conferr = $this->_curOne->GetConfErr()) != null)
				$this->_disp->Set(DInfo::FLD_TopMsg, $conferr);
		}

		// special
		if ($view == DInfo::CT_SERV && $tid && strpos($tid, 'S_MIME') !== false) {
			$mime = $this->_serv->GetChildrenValues('mime');
			$file = PathTool::GetAbsFile($mime[0], 'SR');
			$this->_special = new CData(DInfo::CT_EX, $file, 'MIME');
			if (($conferr = $this->_special->GetConfErr()) != null)
				$this->_disp->Set(DInfo::FLD_TopMsg, $conferr);

		}
		elseif ($view == DInfo::CT_ADMIN && $pid == 'usr') {
			$file = SERVER_ROOT . 'admin/conf/htpasswd';
			$this->_special = new CData(DInfo::CT_EX, $file, 'ADMUSR');
			if (($conferr = $this->_special->GetConfErr()) != null)
				$this->_disp->Set(DInfo::FLD_TopMsg, $conferr);
		}
		elseif ($view == DInfo::CT_VH && $tid &&
				(($isudb = strpos($tid, 'V_UDB')) !== false || strpos($tid, 'V_GDB') !== false )) {
			$realm = $this->_curOne->GetChildNodeById('realm', $this->_disp->GetFirst(DInfo::FLD_REF));
			if ($realm != null) {
				$isudb = ($isudb !== false);
				$file = $realm->GetChildVal($isudb ? 'userDB:location' : 'groupDB:location');
				$vhroot = $this->_disp->GetVHRoot();
				$file = PathTool::GetAbsFile($file, 'VR', $this->_disp->Get(DInfo::FLD_ViewName), $vhroot);
				$this->_special = new CData(DInfo::CT_EX, $file, $isudb ? 'V_UDB' : 'V_GDB');
				if (($conferr = $this->_special->GetConfErr()) != null)
					$this->_disp->Set(DInfo::FLD_TopMsg, $conferr);
			}
		}

	}

	protected function process_config()
	{
		//init here
		$this->_disp->InitConf();
		$this->loadConfig();

		$confdata = $this->getConfData($this->_disp);

		$needTrim = 0;
		$tblDef = DTblDef::GetInstance();
		$disp_act = $this->_disp->Get(DInfo::FLD_ACT);
		if ( $disp_act == 's' )
		{
			$validator = new ConfValidation();
			$extracted = $validator->ExtractPost($this->_disp);
			if ($extracted->HasErr()) {
				$this->_disp->Set(DInfo::FLD_ACT, 'S');
				$this->_disp->Set(DInfo::FLD_TopMsg, $extracted->Get(CNode::FLD_ERR));
				return $extracted;
			}
			else {
				$confdata->SavePost( $extracted, $this->_disp);
				$this->setChanged(true);
				$needTrim = 2;
			}
		}
		elseif ($disp_act == 'a') {
			$added = new CNode(CNode::K_EXTRACTED, '');
			return $added;
		}
		elseif ( $disp_act == 'c' || $disp_act == 'n')
		{ // 'c': change, 'n': next
			$validator = new ConfValidation();
			$extracted = $validator->ExtractPost($this->_disp );
			if ($disp_act == 'n')
				$this->_disp->SwitchToSubTid($extracted);
			return $extracted;
		}
		elseif ($disp_act == 'D' )
		{
			$confdata->DeleteEntry($this->_disp);
			$this->setChanged(true);
			$needTrim = 1;
		}
		elseif ( $disp_act == 'I' )
		{
			if ( $this->instantiateTemplate() ) {
				$needTrim = 1;
			}
		}
		elseif ($disp_act == 'd' || $disp_act == 'i') {
			if ( $disp_act == 'd' ) {
				$actions = 'DC';
				$mesg = DMsg::UIStr('note_confirm_delete');
			}
			else {
				$actions = 'IC';
				$mesg = DMsg::UIStr('note_confirm_instantiate');
			}

			$adata = $this->_disp->GetActionData($actions);
			$mesg = '<p>' . $mesg . '</p>' . UI::GetActionButtons($adata, 'text');

			$this->_disp->Set(DInfo::FLD_TopMsg, $mesg);
		}

		$ctxseq = UIBase::GrabGoodInputWithReset('ANY', 'ctxseq', 'int');
		if ($ctxseq != 0 && $this->_curOne->ChangeContextSeq($ctxseq)) {
			$this->setChanged(true);
			$needTrim = 1;
		}

		if ( $needTrim ) {
			$this->_disp->TrimLastId();
			// need reload
			$this->loadConfig();
			$confdata = $this->getConfData($this->_disp);
		}

		return $confdata;
	}


	protected function instantiateTemplate()
	{
		$tpname = $this->_disp->Get(DInfo::FLD_ViewName);

		$vhname = $this->_disp->GetLast(DInfo::FLD_REF);
		$s_tpnode = $this->_serv->GetChildNodeById('vhTemplate', $tpname);
		if ($s_tpnode == null)
			return false;
		$s_vhnode = $s_tpnode->GetChildNodeById('member', $vhname);
		if ($s_vhnode == null)
			return false;

		$confpath = $this->getConfFilePath(DInfo::CT_TP, $tpname);
		$tp = new CData(DInfo::CT_TP, $confpath);
		if (($conferr = $tp->GetConfErr()) != null) {
			$this->_disp->Set(DInfo::FLD_TopMsg, $conferr);
			return false;
		}
		$tproot = $tp->GetRootNode();

		$configfile = $tproot->GetChildVal('configFile');
		if ($configfile == null)
			return false;

		$vhRoot_path = '';
		if ( strncasecmp('$VH_ROOT', $configfile, 8) == 0 ) {
			$vhRoot_path = $s_vhnode->GetChildVal('vhRoot'); // customized
			if ($vhRoot_path == null) {
				//default
				$vhRoot_path = $tproot->GetChildVal('vhRoot');
				if ($vhRoot_path == null)
					return false;
			}
		}
		$configfile = PathTool::GetAbsFile($configfile, 'VR', $vhname, $vhRoot_path);
		$vh = new CData(DInfo::CT_VH, $configfile, "`$vhname");
		if (($conferr = $vh->GetConfErr()) != null) {
			$this->_disp->Set(DInfo::FLD_TopMsg, $conferr);
			return false;
		}

		$domains = $s_vhnode->GetChildVal('vhDomain');
		if ($domains == null) {
			$domains = $vhname; // default
		}
		$domain = $domains;
		$alias = '';
		if ( ($domainalias = $s_vhnode->GetChildVal('vhAliases')) != null ) {
			$domains .= ", $domainalias";
			$alias = $domainalias;
		}

		$vhroot = $tproot->GetChildren('virtualHostConfig');
		if ($vhroot == false)
			return false;
		$vhroot->AddChild(new CNode('vhDomain', $domain));
		$vhroot->AddChild(new CNode('vhAliases', $alias));

		$vh->SetRootNode($vhroot);
		$vh->SaveFile();

		// save serv file
		$basemap = new DTblMap(array('','*virtualhost$name'), 'V_TOPD');
		$tproot->AddChild(new CNode('name', $vhname));
		$tproot->AddChild(new CNode('note', "Instantiated from template $tpname"));
		$basemap->Convert(0, $tproot, 1, $this->_serv->GetRootNode());
		$s_vhnode->RemoveFromParent();

		$listeners = $s_tpnode->GetChildVal('listeners');
		$lns = preg_split("/, /", $listeners, -1, PREG_SPLIT_NO_EMPTY);

		foreach( $lns as $ln) {
			$listener = $this->_serv->GetChildNodeById('listener', $ln);
			if ($listener != null) {
				$vhmap = new CNode('vhmap', $vhname);
				$vhmap->AddChild(new CNode('domain', $domains));
				$listener->AddChild($vhmap);
			}
			else {
				error_log("cannot find listener $ln \n");
			}
		}
		$this->_serv->SaveFile();
		return true;
	}

	protected function enableDisableVh($act, $actId)
	{
		$haschanged = false;
		$cur_disabled = [];
		$key = 'suspendedVhosts';

		if ($this->_serv == null) {
			$this->load_server_config();
		}
		$curnode = $this->_serv->GetRootNode()->GetChildren($key);
		if ($curnode != null && $curnode->Get(CNode::FLD_VAL) != null)
			$cur_disabled = preg_split("/[,;]+/", $curnode->Get(CNode::FLD_VAL), -1, PREG_SPLIT_NO_EMPTY);

		$found = in_array($actId, $cur_disabled);
		if ($act == SInfo::SREQ_VH_DISABLE) {
			if (!$found) {
				$cur_disabled[] = $actId;
				$haschanged = true;
			}
		}
		elseif ($act == SInfo::SREQ_VH_ENABLE) {
			if ($found) {
				$key = array_search($actId, $cur_disabled);
				unset($cur_disabled[$key]);
				$haschanged = true;
			}
		}
		if ($haschanged) {
			$vals = implode(',', $cur_disabled);
			if ($curnode == null)
				$this->_serv->GetRootNode()->AddChild(new CNode($key, $vals));
			else
				$curnode->SetVal($vals);
			$this->_serv->SaveFile();
		}
	}

	protected function process_service_request($type, $actId)
	{
		// has pending command processs
		if (file_exists(SInfo::FNAME)) {
			return false;
		}

		$cmd = '';
		$this->_service = new SInfo();

		switch ($type) {
			case SInfo::SREQ_RESTART_SERVER:
				$cmd = 'restart';
				$this->setChanged(false);
				break;

			case SInfo::SREQ_TOGGLE_DEBUG:
				$cmd = 'toggledbg';
				break;

			case SInfo::SREQ_VH_RELOAD:
				$cmd = 'restart:vhost:' . $actId;
				break;

			case SInfo::SREQ_VH_DISABLE:
				$cmd = 'disable:vhost:' . $actId;
				$this->enableDisableVh($type, $actId);
				break;

			case SInfo::SREQ_VH_ENABLE:
				$cmd = 'enable:vhost:' . $actId;
				$this->enableDisableVh($type, $actId);
				break;

			default:
				error_log("illegal type in process_service_request $type ");
				return false;
		}

		$this->issueCmd($cmd);
		$this->_service->WaitForChange();
	}


	protected function process_service_data($type)
	{
		// process static type
		switch ($type) {
			case SInfo::DATA_PID:
				return file_get_contents(SInfo::FPID);

			case SInfo::DATA_ADMIN_KEYFILE:
				return $this->getConfFilePath('admin', 'key');

			case SInfo::DATA_DEBUGLOG_STATE:
				return SInfo::GetDebugLogState();
		}

		// require config data
		$this->_service = new SInfo();
		$this->load_server_config();
		$this->_service->Init($this->_serv);

		switch($type) {
			case SInfo::DATA_ADMIN_EMAIL:
				return $this->_serv->GetChildVal('adminEmails');

			case SInfo::DATA_DASH_LOG:
			case SInfo::DATA_VIEW_LOG:
				return $this->_service->LoadLog($type);

			case SInfo::DATA_Status_LV:
				$this->_service->LoadStatus();
				return $this->_service;

			default: "Illegal type in process_service_data : $type ";
		}

		return false;
	}

	public static function getCommandSocket($cmd)
	{
		$ADMSOCK =  $_SERVER['LSWS_ADMIN_SOCK'];
		if ( strncmp( $ADMSOCK, 'uds://', 6 ) == 0 ) {
			$sock = socket_create( AF_UNIX, SOCK_STREAM, 0 );
			$chrootOffset = isset($_SERVER['LS_CHROOT']) ? strlen( $_SERVER['LS_CHROOT']) : 0;
			$addr = substr( $ADMSOCK, 5 + $chrootOffset );
			if ( !socket_connect( $sock, $addr ) ) {
				error_log( 'cmd ' . $cmd . ' failed to connect to server via admsock! socket_connect() failed: ' . socket_strerror(socket_last_error()) . " $ADMSOCK\n" );
				return false;
			}
		}
		else {
			error_log('admin.sock is not set. Please check lsws/admin/tmp/ directory and empty all files there, then restart.');
			$sock = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
			$addr = explode( ":", $ADMSOCK );
			if ( !socket_connect( $sock, $addr[0], intval( $addr[1] ) ) ) {
				error_log( 'cmd ' . $cmd . ' failed to connect to server via AF_INET! socket_connect() failed: ' . socket_strerror(socket_last_error()) . " $ADMSOCK\n" );
				return false;
			}
		}
		$cauth = CAuthorizer::singleton();
		$outBuf = $cauth->GetCmdHeader() . $cmd . "\nend of actions";
		socket_write( $sock, $outBuf );
		socket_shutdown( $sock, 1 );
		return $sock;
	}

	protected function issueCmd($cmd)
	{
        CAuthorizer::singleton()->Reauthenticate();

		$commandline = '';
		if (is_array($cmd)) {
			foreach( $cmd as $line ) {
				$commandline .= $line . "\n";
			}
		}
		else {
			$commandline = $cmd . "\n";
		}

		$sock = $this->getCommandSocket($commandline);
		if ($sock) {
			$res = socket_recv( $sock, $buffer, 1024, 0 );
			socket_close( $sock );
			return (( $res > 0 )&&(strncasecmp( $buffer, 'OK', 2 ) == 0 ));
		}
		else
			return false;
	}

	public function retrieveCommandData($cmd)
	{
		$sock = $this->getCommandSocket($cmd);
		$buffer = '';
		if ($sock) {
			$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;

	}

}