The old SourceQuery library has been removed
This commit is contained in:
parent
cf70b5dd43
commit
3405e159ab
|
@ -1,94 +0,0 @@
|
||||||
<?php
|
|
||||||
if (!DEFINED('EGP'))
|
|
||||||
exit(header('Refresh: 0; URL=http://' . $_SERVER['SERVER_NAME'] . '/404'));
|
|
||||||
|
|
||||||
abstract class BaseSocket
|
|
||||||
{
|
|
||||||
public $Socket;
|
|
||||||
public $Engine;
|
|
||||||
public $Address;
|
|
||||||
public $Port;
|
|
||||||
public $Timeout;
|
|
||||||
|
|
||||||
public function __destruct()
|
|
||||||
{
|
|
||||||
$this->Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract public function Close();
|
|
||||||
|
|
||||||
abstract public function Open($Address, $Port, $Timeout, $Engine);
|
|
||||||
|
|
||||||
abstract public function Write($Header, $String = '');
|
|
||||||
|
|
||||||
abstract public function Read($Length = 1400);
|
|
||||||
|
|
||||||
protected function ReadInternal($Buffer, $Length, $SherlockFunction)
|
|
||||||
{
|
|
||||||
if ($Buffer->Remaining() === 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if ($Buffer->Remaining() === 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$Header = $Buffer->GetLong();
|
|
||||||
|
|
||||||
if ($Header === -2) {
|
|
||||||
$Packets = [];
|
|
||||||
$IsCompressed = false;
|
|
||||||
$ReadMore = false;
|
|
||||||
|
|
||||||
do {
|
|
||||||
$RequestID = $Buffer->GetLong();
|
|
||||||
|
|
||||||
switch ($this->Engine) {
|
|
||||||
case SourceQuery::GOLDSOURCE:
|
|
||||||
{
|
|
||||||
$PacketCountAndNumber = $Buffer->GetByte();
|
|
||||||
$PacketCount = $PacketCountAndNumber & 0xF;
|
|
||||||
$PacketNumber = $PacketCountAndNumber >> 4;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SourceQuery::SOURCE:
|
|
||||||
{
|
|
||||||
$IsCompressed = ($RequestID & 0x80000000) !== 0;
|
|
||||||
$PacketCount = $Buffer->GetByte();
|
|
||||||
$PacketNumber = $Buffer->GetByte() + 1;
|
|
||||||
|
|
||||||
if ($IsCompressed) {
|
|
||||||
$Buffer->GetLong();
|
|
||||||
|
|
||||||
$PacketChecksum = $Buffer->GetUnsignedLong();
|
|
||||||
} else
|
|
||||||
$Buffer->GetShort();
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$Packets[$PacketNumber] = $Buffer->Get();
|
|
||||||
|
|
||||||
$ReadMore = $PacketCount > sizeof($Packets);
|
|
||||||
} while ($ReadMore && $SherlockFunction($Buffer, $Length));
|
|
||||||
|
|
||||||
$Data = Implode($Packets);
|
|
||||||
|
|
||||||
if ($IsCompressed) {
|
|
||||||
if (!Function_Exists('bzdecompress'))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$Data = bzdecompress($Data);
|
|
||||||
|
|
||||||
if (CRC32($Data) !== $PacketChecksum)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$Buffer->Set(SubStr($Data, 4));
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return $Buffer;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,102 +0,0 @@
|
||||||
<?php
|
|
||||||
if (!DEFINED('EGP'))
|
|
||||||
exit(header('Refresh: 0; URL=http://' . $_SERVER['SERVER_NAME'] . '/404'));
|
|
||||||
|
|
||||||
class Buffer
|
|
||||||
{
|
|
||||||
|
|
||||||
private $Buffer;
|
|
||||||
private $Length;
|
|
||||||
private $Position;
|
|
||||||
|
|
||||||
public function Set($Buffer)
|
|
||||||
{
|
|
||||||
$this->Buffer = $Buffer;
|
|
||||||
$this->Length = StrLen($Buffer);
|
|
||||||
$this->Position = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Remaining()
|
|
||||||
{
|
|
||||||
return $this->Length - $this->Position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Get($Length = -1)
|
|
||||||
{
|
|
||||||
if ($Length === 0)
|
|
||||||
return '';
|
|
||||||
|
|
||||||
$Remaining = $this->Remaining();
|
|
||||||
|
|
||||||
if ($Length === -1)
|
|
||||||
$Length = $Remaining;
|
|
||||||
|
|
||||||
else if ($Length > $Remaining)
|
|
||||||
return '';
|
|
||||||
|
|
||||||
$Data = SubStr($this->Buffer, $this->Position, $Length);
|
|
||||||
|
|
||||||
$this->Position += $Length;
|
|
||||||
|
|
||||||
return $Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetByte()
|
|
||||||
{
|
|
||||||
return Ord($this->Get(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetShort()
|
|
||||||
{
|
|
||||||
if ($this->Remaining() < 2)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$Data = UnPack('v', $this->Get(2));
|
|
||||||
|
|
||||||
return $Data[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetLong()
|
|
||||||
{
|
|
||||||
if ($this->Remaining() < 4)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$Data = UnPack('l', $this->Get(4));
|
|
||||||
|
|
||||||
return $Data[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetFloat()
|
|
||||||
{
|
|
||||||
if ($this->Remaining() < 4)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$Data = UnPack('f', $this->Get(4));
|
|
||||||
|
|
||||||
return $Data[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetUnsignedLong()
|
|
||||||
{
|
|
||||||
if ($this->Remaining() < 4)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$Data = UnPack('V', $this->Get(4));
|
|
||||||
|
|
||||||
return $Data[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetString()
|
|
||||||
{
|
|
||||||
$ZeroBytePosition = StrPos($this->Buffer, "\0", $this->Position);
|
|
||||||
|
|
||||||
if ($ZeroBytePosition === false)
|
|
||||||
return '';
|
|
||||||
|
|
||||||
$String = $this->Get($ZeroBytePosition - $this->Position);
|
|
||||||
|
|
||||||
$this->Position++;
|
|
||||||
|
|
||||||
return $String;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,101 +0,0 @@
|
||||||
<?php
|
|
||||||
if (!DEFINED('EGP'))
|
|
||||||
exit(header('Refresh: 0; URL=http://' . $_SERVER['SERVER_NAME'] . '/404'));
|
|
||||||
|
|
||||||
class GoldSourceRcon
|
|
||||||
{
|
|
||||||
private $Socket;
|
|
||||||
|
|
||||||
private $RconPassword;
|
|
||||||
private $RconRequestId;
|
|
||||||
private $RconChallenge;
|
|
||||||
|
|
||||||
public function __construct($Socket)
|
|
||||||
{
|
|
||||||
$this->Socket = $Socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Close()
|
|
||||||
{
|
|
||||||
$this->RconChallenge = 0;
|
|
||||||
$this->RconRequestId = 0;
|
|
||||||
$this->RconPassword = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Open()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Write($Header, $String = '')
|
|
||||||
{
|
|
||||||
$Command = Pack('cccca*', 0xFF, 0xFF, 0xFF, 0xFF, $String);
|
|
||||||
$Length = StrLen($Command);
|
|
||||||
|
|
||||||
return $Length === FWrite($this->Socket->Socket, $Command, $Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Read($Length = 1400)
|
|
||||||
{
|
|
||||||
$Buffer = $this->Socket->Read();
|
|
||||||
|
|
||||||
$StringBuffer = '';
|
|
||||||
$ReadMore = false;
|
|
||||||
|
|
||||||
do {
|
|
||||||
$ReadMore = $Buffer->Remaining() > 0;
|
|
||||||
|
|
||||||
if ($ReadMore) {
|
|
||||||
if ($Buffer->GetByte() !== SourceQuery::S2A_RCON)
|
|
||||||
sys::outjs(array('e' => 'неправильный rcon запрос.'));
|
|
||||||
|
|
||||||
$Packet = $Buffer->Get();
|
|
||||||
$StringBuffer .= $Packet;
|
|
||||||
|
|
||||||
$ReadMore = StrLen($Packet) > 1000;
|
|
||||||
|
|
||||||
if ($ReadMore)
|
|
||||||
$Buffer = $this->Socket->Read();
|
|
||||||
}
|
|
||||||
} while ($ReadMore);
|
|
||||||
|
|
||||||
$Trimmed = trim($StringBuffer);
|
|
||||||
|
|
||||||
if ($Trimmed === 'Bad rcon_password.')
|
|
||||||
sys::outjs(array('e' => 'rcon_password из server.cfg не подходит.'));
|
|
||||||
|
|
||||||
else if ($Trimmed === 'You have been banned from this server.')
|
|
||||||
sys::outjs(array('e' => 'Игровой сервер заблокировал доступ.'));
|
|
||||||
|
|
||||||
$Buffer->Set($Trimmed);
|
|
||||||
|
|
||||||
return $Buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Command($Command)
|
|
||||||
{
|
|
||||||
if (!$this->RconChallenge)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$this->Write(0, 'rcon ' . $this->RconChallenge . ' "' . $this->RconPassword . '" ' . $Command . "\0");
|
|
||||||
$Buffer = $this->Read();
|
|
||||||
|
|
||||||
if ($Buffer)
|
|
||||||
return $Buffer->Get();
|
|
||||||
|
|
||||||
return $Buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Authorize($Password)
|
|
||||||
{
|
|
||||||
$this->RconPassword = $Password;
|
|
||||||
|
|
||||||
$this->Write(0, 'challenge rcon');
|
|
||||||
$Buffer = $this->Socket->Read();
|
|
||||||
|
|
||||||
if ($Buffer->Get(14) !== 'challenge rcon')
|
|
||||||
sys::outjs(array('e' => 'Не удалось выполнить rcon запрос.'));
|
|
||||||
|
|
||||||
$this->RconChallenge = Trim($Buffer->Get());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
<?php
|
|
||||||
if (!DEFINED('EGP'))
|
|
||||||
exit(header('Refresh: 0; URL=http://' . $_SERVER['SERVER_NAME'] . '/404'));
|
|
||||||
|
|
||||||
class Socket extends BaseSocket
|
|
||||||
{
|
|
||||||
public function Close()
|
|
||||||
{
|
|
||||||
if ($this->Socket) {
|
|
||||||
FClose($this->Socket);
|
|
||||||
|
|
||||||
$this->Socket = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Open($Address, $Port, $Timeout, $Engine)
|
|
||||||
{
|
|
||||||
$this->Timeout = $Timeout;
|
|
||||||
$this->Engine = $Engine;
|
|
||||||
$this->Port = $Port;
|
|
||||||
$this->Address = $Address;
|
|
||||||
|
|
||||||
$this->Socket = @FSockOpen('udp://' . $Address, $Port, $ErrNo, $ErrStr, $Timeout);
|
|
||||||
|
|
||||||
if ($ErrNo || $this->Socket === false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Stream_Set_Timeout($this->Socket, $Timeout);
|
|
||||||
Stream_Set_Blocking($this->Socket, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Write($Header, $String = '')
|
|
||||||
{
|
|
||||||
$Command = Pack('ccccca*', 0xFF, 0xFF, 0xFF, 0xFF, $Header, $String);
|
|
||||||
$Length = StrLen($Command);
|
|
||||||
|
|
||||||
return $Length === FWrite($this->Socket, $Command, $Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Read($Length = 1400)
|
|
||||||
{
|
|
||||||
$Buffer = new Buffer();
|
|
||||||
$Buffer->Set(FRead($this->Socket, $Length));
|
|
||||||
|
|
||||||
$this->ReadInternal($Buffer, $Length, [$this, 'Sherlock']);
|
|
||||||
|
|
||||||
return $Buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Sherlock($Buffer, $Length)
|
|
||||||
{
|
|
||||||
$Data = FRead($this->Socket, $Length);
|
|
||||||
|
|
||||||
if (StrLen($Data) < 4)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$Buffer->Set($Data);
|
|
||||||
|
|
||||||
return $Buffer->GetLong() === -2;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,331 +0,0 @@
|
||||||
<?php
|
|
||||||
if (!DEFINED('EGP'))
|
|
||||||
exit(header('Refresh: 0; URL=http://' . $_SERVER['SERVER_NAME'] . '/404'));
|
|
||||||
|
|
||||||
class SourceQuery
|
|
||||||
{
|
|
||||||
const GOLDSOURCE = 0;
|
|
||||||
const SOURCE = 1;
|
|
||||||
const A2S_PING = 0x69;
|
|
||||||
const A2S_INFO = 0x54;
|
|
||||||
const A2S_PLAYER = 0x55;
|
|
||||||
const A2S_RULES = 0x56;
|
|
||||||
const A2S_SERVERQUERY_GETCHALLENGE = 0x57;
|
|
||||||
const S2A_PING = 0x6A;
|
|
||||||
const S2A_CHALLENGE = 0x41;
|
|
||||||
const S2A_INFO = 0x49;
|
|
||||||
const S2A_INFO_OLD = 0x6D;
|
|
||||||
const S2A_PLAYER = 0x44;
|
|
||||||
const S2A_RULES = 0x45;
|
|
||||||
const S2A_RCON = 0x6C;
|
|
||||||
const SERVERDATA_EXECCOMMAND = 2;
|
|
||||||
const SERVERDATA_AUTH = 3;
|
|
||||||
const SERVERDATA_RESPONSE_VALUE = 0;
|
|
||||||
const SERVERDATA_AUTH_RESPONSE = 2;
|
|
||||||
|
|
||||||
private $Rcon;
|
|
||||||
private $Socket;
|
|
||||||
private $Connected;
|
|
||||||
private $Challenge;
|
|
||||||
private $UseOldGetChallengeMethod;
|
|
||||||
|
|
||||||
public function __construct(BaseSocket $Socket = null)
|
|
||||||
{
|
|
||||||
$this->Socket = $Socket ?: new Socket();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __destruct()
|
|
||||||
{
|
|
||||||
$this->Disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Connect($Address, $Port, $Timeout = 3, $Engine = self::SOURCE)
|
|
||||||
{
|
|
||||||
$this->Disconnect();
|
|
||||||
|
|
||||||
if (!is_int($Timeout) || $Timeout < 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$this->Socket->Open($Address, (int)$Port, $Timeout, (int)$Engine);
|
|
||||||
|
|
||||||
$this->Connected = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function SetUseOldGetChallengeMethod($Value)
|
|
||||||
{
|
|
||||||
$Previous = $this->UseOldGetChallengeMethod;
|
|
||||||
|
|
||||||
$this->UseOldGetChallengeMethod = $Value === true;
|
|
||||||
|
|
||||||
return $Previous;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Disconnect()
|
|
||||||
{
|
|
||||||
$this->Connected = false;
|
|
||||||
$this->Challenge = 0;
|
|
||||||
|
|
||||||
$this->Socket->Close();
|
|
||||||
|
|
||||||
if ($this->Rcon) {
|
|
||||||
$this->Rcon->Close();
|
|
||||||
|
|
||||||
$this->Rcon = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Ping()
|
|
||||||
{
|
|
||||||
if (!$this->Connected)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$this->Socket->Write(self::A2S_PING);
|
|
||||||
$Buffer = $this->Socket->Read();
|
|
||||||
|
|
||||||
return $Buffer->GetByte() === self::S2A_PING;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetInfo()
|
|
||||||
{
|
|
||||||
if (!$this->Connected)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$this->Socket->Write(self::A2S_INFO, "Source Engine Query\0");
|
|
||||||
$Buffer = $this->Socket->Read();
|
|
||||||
|
|
||||||
$Type = $Buffer->GetByte();
|
|
||||||
|
|
||||||
if ($Type === self::S2A_INFO_OLD && $this->Socket->Engine === self::GOLDSOURCE) {
|
|
||||||
$Server['Address'] = $Buffer->GetString();
|
|
||||||
$Server['HostName'] = $Buffer->GetString();
|
|
||||||
$Server['Map'] = $Buffer->GetString();
|
|
||||||
$Server['ModDir'] = $Buffer->GetString();
|
|
||||||
$Server['ModDesc'] = $Buffer->GetString();
|
|
||||||
$Server['Players'] = $Buffer->GetByte();
|
|
||||||
$Server['MaxPlayers'] = $Buffer->GetByte();
|
|
||||||
$Server['Protocol'] = $Buffer->GetByte();
|
|
||||||
$Server['Dedicated'] = Chr($Buffer->GetByte());
|
|
||||||
$Server['Os'] = Chr($Buffer->GetByte());
|
|
||||||
$Server['Password'] = $Buffer->GetByte() === 1;
|
|
||||||
$Server['IsMod'] = $Buffer->GetByte() === 1;
|
|
||||||
|
|
||||||
if ($Server['IsMod']) {
|
|
||||||
$Mod['Url'] = $Buffer->GetString();
|
|
||||||
$Mod['Download'] = $Buffer->GetString();
|
|
||||||
$Buffer->Get(1);
|
|
||||||
$Mod['Version'] = $Buffer->GetLong();
|
|
||||||
$Mod['Size'] = $Buffer->GetLong();
|
|
||||||
$Mod['ServerSide'] = $Buffer->GetByte() === 1;
|
|
||||||
$Mod['CustomDLL'] = $Buffer->GetByte() === 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$Server['Secure'] = $Buffer->GetByte() === 1;
|
|
||||||
$Server['Bots'] = $Buffer->GetByte();
|
|
||||||
|
|
||||||
if (isset($Mod))
|
|
||||||
$Server['Mod'] = $Mod;
|
|
||||||
|
|
||||||
return $Server;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($Type !== self::S2A_INFO)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if ($Type !== self::S2A_INFO)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$Server['Protocol'] = $Buffer->GetByte();
|
|
||||||
$Server['HostName'] = $Buffer->GetString();
|
|
||||||
$Server['Map'] = $Buffer->GetString();
|
|
||||||
$Server['ModDir'] = $Buffer->GetString();
|
|
||||||
$Server['ModDesc'] = $Buffer->GetString();
|
|
||||||
$Server['AppID'] = $Buffer->GetShort();
|
|
||||||
$Server['Players'] = $Buffer->GetByte();
|
|
||||||
$Server['MaxPlayers'] = $Buffer->GetByte();
|
|
||||||
$Server['Bots'] = $Buffer->GetByte();
|
|
||||||
$Server['Dedicated'] = Chr($Buffer->GetByte());
|
|
||||||
$Server['Os'] = Chr($Buffer->GetByte());
|
|
||||||
$Server['Password'] = $Buffer->GetByte() === 1;
|
|
||||||
$Server['Secure'] = $Buffer->GetByte() === 1;
|
|
||||||
|
|
||||||
if ($Server['AppID'] === 2400) {
|
|
||||||
$Server['GameMode'] = $Buffer->GetByte();
|
|
||||||
$Server['WitnessCount'] = $Buffer->GetByte();
|
|
||||||
$Server['WitnessTime'] = $Buffer->GetByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
$Server['Version'] = $Buffer->GetString();
|
|
||||||
|
|
||||||
if ($Buffer->Remaining() > 0) {
|
|
||||||
$Server['ExtraDataFlags'] = $Flags = $Buffer->GetByte();
|
|
||||||
|
|
||||||
if ($Flags & 0x80)
|
|
||||||
$Server['GamePort'] = $Buffer->GetShort();
|
|
||||||
|
|
||||||
if ($Flags & 0x10) {
|
|
||||||
$SteamIDLower = $Buffer->GetUnsignedLong();
|
|
||||||
$SteamIDInstance = $Buffer->GetUnsignedLong();
|
|
||||||
$SteamID = 0;
|
|
||||||
|
|
||||||
if (PHP_INT_SIZE === 4) {
|
|
||||||
if (extension_loaded('gmp')) {
|
|
||||||
$SteamIDLower = gmp_abs($SteamIDLower);
|
|
||||||
$SteamIDInstance = gmp_abs($SteamIDInstance);
|
|
||||||
$SteamID = gmp_strval(gmp_or($SteamIDLower, gmp_mul($SteamIDInstance, gmp_pow(2, 32))));
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
} else
|
|
||||||
$SteamID = $SteamIDLower | ($SteamIDInstance << 32);
|
|
||||||
|
|
||||||
$Server['SteamID'] = $SteamID;
|
|
||||||
|
|
||||||
unset($SteamIDLower, $SteamIDInstance, $SteamID);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($Flags & 0x40) {
|
|
||||||
$Server['SpecPort'] = $Buffer->GetShort();
|
|
||||||
$Server['SpecName'] = $Buffer->GetString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($Flags & 0x20)
|
|
||||||
$Server['GameTags'] = $Buffer->GetString();
|
|
||||||
|
|
||||||
if ($Flags & 0x01)
|
|
||||||
$Server['GameID'] = $Buffer->GetUnsignedLong() | ($Buffer->GetUnsignedLong() << 32);
|
|
||||||
|
|
||||||
if ($Buffer->Remaining() > 0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $Server;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetPlayers()
|
|
||||||
{
|
|
||||||
if (!$this->Connected)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$this->GetChallenge(self::A2S_PLAYER, self::S2A_PLAYER);
|
|
||||||
|
|
||||||
$this->Socket->Write(self::A2S_PLAYER, $this->Challenge);
|
|
||||||
$Buffer = $this->Socket->Read(14000);
|
|
||||||
$Type = $Buffer->GetByte();
|
|
||||||
|
|
||||||
if ($Type !== self::S2A_PLAYER)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$Players = [];
|
|
||||||
$Count = $Buffer->GetByte();
|
|
||||||
|
|
||||||
while ($Count-- > 0 && $Buffer->Remaining() > 0) {
|
|
||||||
$Player['Id'] = $Buffer->GetByte();
|
|
||||||
$Player['Name'] = $Buffer->GetString();
|
|
||||||
$Player['Frags'] = $Buffer->GetLong();
|
|
||||||
$Player['Time'] = (int)$Buffer->GetFloat();
|
|
||||||
$Player['TimeF'] = GMDate(($Player['Time'] > 3600 ? "H:i:s" : "i:s"), $Player['Time']);
|
|
||||||
|
|
||||||
$Players[] = $Player;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $Players;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetRules()
|
|
||||||
{
|
|
||||||
if (!$this->Connected)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$this->GetChallenge(self::A2S_RULES, self::S2A_RULES);
|
|
||||||
$this->Socket->Write(self::A2S_RULES, $this->Challenge);
|
|
||||||
$Buffer = $this->Socket->Read();
|
|
||||||
$Type = $Buffer->GetByte();
|
|
||||||
|
|
||||||
if ($Type !== self::S2A_RULES)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$Rules = [];
|
|
||||||
$Count = $Buffer->GetShort();
|
|
||||||
|
|
||||||
while ($Count-- > 0 && $Buffer->Remaining() > 0) {
|
|
||||||
$Rule = $Buffer->GetString();
|
|
||||||
$Value = $Buffer->GetString();
|
|
||||||
|
|
||||||
if (!empty($Rule))
|
|
||||||
$Rules[$Rule] = $Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $Rules;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function GetChallenge($Header, $ExpectedResult)
|
|
||||||
{
|
|
||||||
if ($this->Challenge)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ($this->UseOldGetChallengeMethod)
|
|
||||||
$Header = self::A2S_SERVERQUERY_GETCHALLENGE;
|
|
||||||
|
|
||||||
$this->Socket->Write($Header, "\xFF\xFF\xFF\xFF");
|
|
||||||
$Buffer = $this->Socket->Read();
|
|
||||||
$Type = $Buffer->GetByte();
|
|
||||||
|
|
||||||
switch ($Type) {
|
|
||||||
case self::S2A_CHALLENGE:
|
|
||||||
{
|
|
||||||
$this->Challenge = $Buffer->Get(4);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case $ExpectedResult:
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function SetRconPassword($Password)
|
|
||||||
{
|
|
||||||
if (!$this->Connected) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($this->Socket->Engine) {
|
|
||||||
case SourceQuery::GOLDSOURCE:
|
|
||||||
{
|
|
||||||
$this->Rcon = new GoldSourceRcon($this->Socket);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SourceQuery::SOURCE:
|
|
||||||
{
|
|
||||||
$this->Rcon = new SourceRcon($this->Socket);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->Rcon->Open();
|
|
||||||
$this->Rcon->Authorize($Password);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Rcon($Command)
|
|
||||||
{
|
|
||||||
if (!$this->Connected) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->Rcon === null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->Rcon->Command($Command);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,140 +0,0 @@
|
||||||
<?php
|
|
||||||
if (!DEFINED('EGP'))
|
|
||||||
exit(header('Refresh: 0; URL=http://' . $_SERVER['SERVER_NAME'] . '/404'));
|
|
||||||
|
|
||||||
class SourceRcon
|
|
||||||
{
|
|
||||||
private $Socket;
|
|
||||||
private $RconSocket;
|
|
||||||
private $RconRequestId;
|
|
||||||
|
|
||||||
public function __construct($Socket)
|
|
||||||
{
|
|
||||||
$this->Socket = $Socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Close()
|
|
||||||
{
|
|
||||||
if ($this->RconSocket) {
|
|
||||||
FClose($this->RconSocket);
|
|
||||||
|
|
||||||
$this->RconSocket = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->RconRequestId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Open()
|
|
||||||
{
|
|
||||||
if (!$this->RconSocket) {
|
|
||||||
$this->RconSocket = @FSockOpen($this->Socket->Address, $this->Socket->Port, $ErrNo, $ErrStr, $this->Socket->Timeout);
|
|
||||||
|
|
||||||
if ($ErrNo || !$this->RconSocket)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Stream_Set_Timeout($this->RconSocket, $this->Socket->Timeout);
|
|
||||||
Stream_Set_Blocking($this->RconSocket, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Write($Header, $String = '')
|
|
||||||
{
|
|
||||||
$Command = Pack('VV', ++$this->RconRequestId, $Header) . $String . "\x00\x00";
|
|
||||||
$Command = Pack('V', StrLen($Command)) . $Command;
|
|
||||||
$Length = StrLen($Command);
|
|
||||||
|
|
||||||
return $Length === FWrite($this->RconSocket, $Command, $Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Read()
|
|
||||||
{
|
|
||||||
$Buffer = new Buffer();
|
|
||||||
$Buffer->Set(FRead($this->RconSocket, 4));
|
|
||||||
|
|
||||||
if ($Buffer->Remaining() < 4)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$PacketSize = $Buffer->GetLong();
|
|
||||||
|
|
||||||
$Buffer->Set(FRead($this->RconSocket, $PacketSize));
|
|
||||||
|
|
||||||
$Data = $Buffer->Get();
|
|
||||||
|
|
||||||
$Remaining = $PacketSize - StrLen($Data);
|
|
||||||
|
|
||||||
while ($Remaining > 0) {
|
|
||||||
$Data2 = FRead($this->RconSocket, $Remaining);
|
|
||||||
|
|
||||||
$PacketSize = StrLen($Data2);
|
|
||||||
|
|
||||||
if ($PacketSize === 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$Data .= $Data2;
|
|
||||||
$Remaining -= $PacketSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
$Buffer->Set($Data);
|
|
||||||
|
|
||||||
return $Buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Command($Command)
|
|
||||||
{
|
|
||||||
$this->Write(SourceQuery::SERVERDATA_EXECCOMMAND, $Command);
|
|
||||||
$Buffer = $this->Read();
|
|
||||||
|
|
||||||
$Buffer->GetLong();
|
|
||||||
|
|
||||||
$Type = $Buffer->GetLong();
|
|
||||||
|
|
||||||
if ($Type === SourceQuery::SERVERDATA_AUTH_RESPONSE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if ($Type !== SourceQuery::SERVERDATA_RESPONSE_VALUE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$Data = $Buffer->Get();
|
|
||||||
|
|
||||||
if (StrLen($Data) >= 4000) {
|
|
||||||
do {
|
|
||||||
$this->Write(SourceQuery::SERVERDATA_RESPONSE_VALUE);
|
|
||||||
|
|
||||||
$Buffer = $this->Read();
|
|
||||||
|
|
||||||
$Buffer->GetLong();
|
|
||||||
|
|
||||||
if ($Buffer->GetLong() !== SourceQuery::SERVERDATA_RESPONSE_VALUE)
|
|
||||||
break;
|
|
||||||
|
|
||||||
$Data2 = $Buffer->Get();
|
|
||||||
|
|
||||||
if ($Data2 === "\x00\x01\x00\x00\x00\x00")
|
|
||||||
break;
|
|
||||||
|
|
||||||
$Data .= $Data2;
|
|
||||||
} while (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rtrim($Data, "\0");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Authorize($Password)
|
|
||||||
{
|
|
||||||
$this->Write(SourceQuery::SERVERDATA_AUTH, $Password);
|
|
||||||
$Buffer = $this->Read();
|
|
||||||
|
|
||||||
$RequestID = $Buffer->GetLong();
|
|
||||||
$Type = $Buffer->GetLong();
|
|
||||||
|
|
||||||
if ($Type === SourceQuery::SERVERDATA_RESPONSE_VALUE) {
|
|
||||||
$Buffer = $this->Read();
|
|
||||||
|
|
||||||
$RequestID = $Buffer->GetLong();
|
|
||||||
$Type = $Buffer->GetLong();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($RequestID === -1 || $Type !== SourceQuery::SERVERDATA_AUTH_RESPONSE)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue