Сборка REDL: панель на PHP 8, капча-тумблер, закрытые уязвимости, установщики в один клик
- панель работает на PHP 8.4 (оригинал под PHP 7.0): elFinder utf8_encode, apache_get_modules, warnings - капча выключена и управляется из админки (флаг captcha_enable + блок настроек) - закрыты две SQL-инъекции без авторизации (createAuthLog: пароль из POST и CF-Connecting-IP) - убрано хранение паролей в открытом виде в authlog, XSS в поле ref - установщики install-panel.sh и install-node.sh (оригинальный затирал sources.list репозиториями Debian 9) - современный Dockerfile (оригинальный на debian:stretch больше не собирается) - планировщик и автозапуск работают без systemd - брендинг REDL.IO, год 2026, ссылки на redl.io - документация на русском: ИЗМЕНЕНИЯ, БЕЗОПАСНОСТЬ, ИНСТРУКЦИЯ
This commit is contained in:
@@ -0,0 +1,406 @@
|
||||
<?php
|
||||
/*
|
||||
Copyright (c) 2020 HOSTINPL (HOSTING-RUS) https://vk.com/hosting_rus
|
||||
Developed by Samir Shelenko and Alexander Zemlyanoy (https://vk.com/id00v / https://vk.com/mrsasha082)
|
||||
*/
|
||||
class SampRconAPI {
|
||||
private $sock = null;
|
||||
private $server = null;
|
||||
private $port = null;
|
||||
private $password = null;
|
||||
|
||||
/**
|
||||
* Creates a new SampRcon object.
|
||||
* @param $server hostname of the server
|
||||
* @param $port port of the server
|
||||
* @param $password rcon password for the server
|
||||
*/
|
||||
public function __construct($server, $port, $password) {
|
||||
$this->server = $server;
|
||||
$this->port = $port;
|
||||
$this->password = $password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of rcon commands.
|
||||
* @return Array
|
||||
* (
|
||||
* Array[0] => "echo"
|
||||
* ...
|
||||
* )
|
||||
* ...
|
||||
* @see getServerVariables()
|
||||
*/
|
||||
public function getCommandList() {
|
||||
$commands = $this->rconSend('cmdlist');
|
||||
|
||||
foreach($commands as &$command) {
|
||||
$command = trim($command);
|
||||
}
|
||||
return $commands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of server variables.
|
||||
* @return Array[]
|
||||
* (
|
||||
* ['variableName'] = variableValue
|
||||
* ...
|
||||
* )
|
||||
* @see getCommandList
|
||||
*/
|
||||
public function getServerVariables() {
|
||||
$aVariables = $this->rconSend('varlist');
|
||||
unset($aVariables[0]);
|
||||
$aReturn = array();
|
||||
|
||||
foreach($aVariables as $sString) {
|
||||
preg_match('/(.*)=[\s]+(.*)/', $sString, $aMatches);
|
||||
|
||||
if($aMatches[2][0] == '"') {
|
||||
preg_match('/\"(.*)\"[\s]+\(/', $aMatches[2], $aTemp);
|
||||
$aReturn[trim($aMatches[1])] = $aTemp[1];
|
||||
} else {
|
||||
preg_match('/(.*?)\s+\(/', $aMatches[2], $aTemp);
|
||||
$aReturn[trim($aMatches[1])] = $aTemp[1];
|
||||
}
|
||||
}
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the server's current weather, if no weather ID is given 1 is used.
|
||||
* @param $weatherID weather ID
|
||||
*/
|
||||
public function setWeather($weatherID=1) {
|
||||
$this->rconSend("weather ".$weatherID, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the server's current gravity, of mp gravity is given 0.008 is used.
|
||||
* @param $gravity gravity double / float
|
||||
*/
|
||||
public function setGravity($gravity=0.008) {
|
||||
$this->rconSend("gravity ".$gravity, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ban a player from the server.
|
||||
* @param $playerID player's ID
|
||||
* @return Output from ban
|
||||
*/
|
||||
public function ban($playerID) {
|
||||
return $this->rconSend("ban ".$playerID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kick a player from the server.
|
||||
* @param $playerID player's ID
|
||||
* @return Output from kick
|
||||
*/
|
||||
public function kick($playerID) {
|
||||
return $this->rconSend("kick ".$playerID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ban an IP address from the server.
|
||||
* @param $address IP address
|
||||
* @return Output from ban
|
||||
*/
|
||||
public function banAddress($address) {
|
||||
return $this->rconSend("banip ".$address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unban an IP address from the server.
|
||||
* @param $address IP address
|
||||
* @return Output from unban
|
||||
*/
|
||||
public function unbanAddress($address) {
|
||||
return $this->rconSend("unbanip ".$address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the server's log file.
|
||||
*/
|
||||
public function reloadLog() {
|
||||
return $this->rconSend("reloadlog");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the server's bans file.
|
||||
*/
|
||||
public function reloadBans() {
|
||||
return $this->rconSend("reloadbans");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an admin message to players on the server.
|
||||
* @param $message message to send to players
|
||||
*/
|
||||
public function say($message) {
|
||||
$this->rconSend("say ".$message, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change the server's current gamemode.
|
||||
* @param $gameMode game mode to change to
|
||||
*/
|
||||
public function changeGameMode($gameMode) {
|
||||
$this->rconSend("changemode ".$gameMode, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the server's current displayed game mode text.
|
||||
* @param $gameModeText game mode text to change to
|
||||
*/
|
||||
public function setGameModeText($gameModeText) {
|
||||
$this->rconSend("gamemodetext ".$gameModeText, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the server's next gamemode (gmx).
|
||||
*/
|
||||
public function nextGameMode() {
|
||||
$this->rconSend("gmx", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the server's next gamemode (gmx).
|
||||
*/
|
||||
public function gmx() {
|
||||
$this->nextGamemode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute config file.
|
||||
* @param $config config file to execute
|
||||
* @return Output from exec
|
||||
*/
|
||||
public function execConfig($config) {
|
||||
return $this->rconSend("exec ".$config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a filterscript.
|
||||
* @param $fs filterscript to load
|
||||
* @return Output from filterscript load
|
||||
*/
|
||||
public function loadFilterscript($fs) {
|
||||
return $this->rconSend("loadfs ".$fs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unload a filterscript.
|
||||
* @param $fs filterscript to unload
|
||||
* @return Output from filterscript unload
|
||||
*/
|
||||
public function unloadFilterscript($fs) {
|
||||
return $this->rconSend("unloadfs ".$fs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload a filterscript.
|
||||
* @param $fs filterscript to reload
|
||||
* @return Output from filterscript reload
|
||||
*/
|
||||
public function reloadFilterscript($fs) {
|
||||
return $this->rconSend("reloadfs ".$fs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the server.
|
||||
*/
|
||||
public function exitGame() {
|
||||
$this->rconSend("exit", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the server's host name.
|
||||
* @param $hostName the host name to set the server to
|
||||
*/
|
||||
public function setHostName($hostName) {
|
||||
$this->rconSend("hostname ".$hostName, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the server's map name.
|
||||
* @param $mapName the map name to set the server to
|
||||
*/
|
||||
public function setMapname($mapName) {
|
||||
$this->rconSend("mapname ".$mapName, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the server's time.
|
||||
* Note: This will not change the weather relative to the time.
|
||||
* @param $time the time to set the server to
|
||||
*/
|
||||
public function setTime($time) {
|
||||
$this->rconSend("worldtime ".$time, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the server's web url.
|
||||
* @param $url the url to set the server to
|
||||
*/
|
||||
public function setURL($url) {
|
||||
$this->rconSend("weburl ".$url, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the server's password.
|
||||
* @param $password the password to set the server to
|
||||
*/
|
||||
public function setPassword($password) {
|
||||
$this->rconSend("password ".$password, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the server's password.
|
||||
*/
|
||||
public function removePassword() {
|
||||
$this->rconSend("password 0", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the server's rcon password.
|
||||
* @param $password the password the rcon password should be set to
|
||||
*/
|
||||
public function setRconPassword($password) {
|
||||
$this->rconSend("rcon_password ".$password, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables remote rcon to the server.
|
||||
*/
|
||||
public function disableRcon() {
|
||||
$this->rconSend("rcon 0", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables remote queries to the server.
|
||||
*/
|
||||
public function enableQuery() {
|
||||
$this->rconSend("query 1", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables remote queries to the server.
|
||||
*/
|
||||
public function disableQuery() {
|
||||
$this->rconSend("query 0", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the server's announce.
|
||||
*/
|
||||
public function enableAnnounce() {
|
||||
$this->rconSend("announce 1", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the server's announce.
|
||||
*/
|
||||
public function disableAnnounce() {
|
||||
$this->rconSend("announce 0", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the server's max number of NPCs.
|
||||
* @param $maxNPCs the maximum numbers of NPCs
|
||||
*/
|
||||
public function setMaxNPCs($maxNPCs) {
|
||||
$this->rconSend("maxnpc ".$maxNPCs, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an rcon command.
|
||||
* @param $command command to execute
|
||||
* @param $delay delay time, if you don't expect any data back set this to false
|
||||
* @return Output from command
|
||||
*/
|
||||
public function call($command, $delay=1.0) {
|
||||
return $this->rconSend($command, $delay);
|
||||
}
|
||||
|
||||
private function rconSend($command, $delay=1.0) {
|
||||
fwrite($this->sock, $this->assemblePacket($command));
|
||||
|
||||
if ($delay === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$result = array();
|
||||
$iMicrotime = microtime(true) + $delay;
|
||||
|
||||
while (microtime(true) < $iMicrotime) {
|
||||
$temp = substr(fread($this->sock, 128), 13);
|
||||
|
||||
if (strlen($temp)) {
|
||||
$result[] = $temp;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function assemblePacket($command) {
|
||||
$sPacket = "SAMP";
|
||||
$sPacket .= chr(strtok($this->server, "."));
|
||||
$sPacket .= chr(strtok("."));
|
||||
$sPacket .= chr(strtok("."));
|
||||
$sPacket .= chr(strtok("."));
|
||||
$sPacket .= chr($this->port & 0xFF);
|
||||
$sPacket .= chr($this->port >> 8 & 0xFF);
|
||||
$sPacket .= "x";
|
||||
|
||||
$sPacket .= chr(strlen($this->password) & 0xFF);
|
||||
$sPacket .= chr(strlen($this->password) >> 8 & 0xFF);
|
||||
$sPacket .= $this->password;
|
||||
$sPacket .= chr(strlen($command) & 0xFF);
|
||||
$sPacket .= chr(strlen($command) >> 8 & 0xFF);
|
||||
$sPacket .= $command;
|
||||
|
||||
return $sPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to connect to the server and returns whether it was successful.
|
||||
* @return boolean
|
||||
*/
|
||||
public function connect() {
|
||||
$connected = false;
|
||||
|
||||
$packet = "SAMP";
|
||||
$packet .= chr(strtok($this->server, "."));
|
||||
$packet .= chr(strtok("."));
|
||||
$packet .= chr(strtok("."));
|
||||
$packet .= chr(strtok("."));
|
||||
$packet .= chr($this->port & 0xFF);
|
||||
$packet .= chr($this->port >> 8 & 0xFF);
|
||||
$packet .= "p0101";
|
||||
|
||||
$this->sock = fsockopen("udp://".$this->server, $this->port, $errorNum, $errorString, 2);
|
||||
socket_set_timeout($this->sock, 2);
|
||||
|
||||
fwrite($this->sock, $packet);
|
||||
|
||||
if(fread($this->sock, 10)) {
|
||||
if(fread($this->sock, 5) == 'p0101') {
|
||||
$connected = true;
|
||||
}
|
||||
}
|
||||
return $connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the connection
|
||||
*/
|
||||
public function close() {
|
||||
@fclose($this->sock);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user