mirror of
https://github.com/xPaw/PHP-Source-Query.git
synced 2026-06-08 06:25:59 +02:00
Strict checks; implement GameID from extra data flags
This commit is contained in:
@@ -70,21 +70,20 @@
|
|||||||
*/
|
*/
|
||||||
public function Get( $Length = -1 )
|
public function Get( $Length = -1 )
|
||||||
{
|
{
|
||||||
if( $Length == 0 )
|
if( $Length === 0 )
|
||||||
{
|
{
|
||||||
// Why even bother
|
return '';
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$Remaining = $this->Remaining( );
|
$Remaining = $this->Remaining( );
|
||||||
|
|
||||||
if( $Length == -1 )
|
if( $Length === -1 )
|
||||||
{
|
{
|
||||||
$Length = $Remaining;
|
$Length = $Remaining;
|
||||||
}
|
}
|
||||||
else if( $Length > $Remaining )
|
else if( $Length > $Remaining )
|
||||||
{
|
{
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$Data = SubStr( $this->Buffer, $this->Position, $Length );
|
$Data = SubStr( $this->Buffer, $this->Position, $Length );
|
||||||
|
|||||||
@@ -69,7 +69,19 @@
|
|||||||
{
|
{
|
||||||
$this->Buffer->Set( FRead( $this->Socket, $Length ) );
|
$this->Buffer->Set( FRead( $this->Socket, $Length ) );
|
||||||
|
|
||||||
if( $this->Buffer->Remaining( ) > 0 && $this->Buffer->GetLong( ) == -2 )
|
if( $this->Buffer->Remaining( ) === 0 )
|
||||||
|
{
|
||||||
|
// TODO: Should we throw an exception here?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$Header = $this->Buffer->GetLong( );
|
||||||
|
|
||||||
|
if( $Header === -1 ) // Single packet
|
||||||
|
{
|
||||||
|
// We don't have to do anything
|
||||||
|
}
|
||||||
|
else if( $Header === -2 ) // Split packet
|
||||||
{
|
{
|
||||||
$Packets = Array( );
|
$Packets = Array( );
|
||||||
$IsCompressed = false;
|
$IsCompressed = false;
|
||||||
@@ -91,7 +103,7 @@
|
|||||||
}
|
}
|
||||||
case SourceQuery :: SOURCE:
|
case SourceQuery :: SOURCE:
|
||||||
{
|
{
|
||||||
$IsCompressed = ( $RequestID & 0x80000000 ) != 0;
|
$IsCompressed = ( $RequestID & 0x80000000 ) !== 0;
|
||||||
$PacketCount = $this->Buffer->GetByte( );
|
$PacketCount = $this->Buffer->GetByte( );
|
||||||
$PacketNumber = $this->Buffer->GetByte( ) + 1;
|
$PacketNumber = $this->Buffer->GetByte( ) + 1;
|
||||||
|
|
||||||
@@ -129,7 +141,7 @@
|
|||||||
|
|
||||||
$Data = bzdecompress( $Data );
|
$Data = bzdecompress( $Data );
|
||||||
|
|
||||||
if( CRC32( $Data ) != $PacketChecksum )
|
if( CRC32( $Data ) !== $PacketChecksum )
|
||||||
{
|
{
|
||||||
throw new SourceQueryException( 'CRC32 checksum mismatch of uncompressed packet data.' );
|
throw new SourceQueryException( 'CRC32 checksum mismatch of uncompressed packet data.' );
|
||||||
}
|
}
|
||||||
@@ -137,6 +149,10 @@
|
|||||||
|
|
||||||
$this->Buffer->Set( SubStr( $Buffer, 4 ) );
|
$this->Buffer->Set( SubStr( $Buffer, 4 ) );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new SourceQueryException( 'Socket read: Raw packet header mismatch. (0x' . DecHex( $Header ) . ')' );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function Sherlock( $Length )
|
private function Sherlock( $Length )
|
||||||
@@ -150,6 +166,6 @@
|
|||||||
|
|
||||||
$this->Buffer->Set( $Data );
|
$this->Buffer->Set( $Data );
|
||||||
|
|
||||||
return $this->Buffer->GetLong( ) == -2;
|
return $this->Buffer->GetLong( ) === -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,7 +191,7 @@
|
|||||||
$this->Socket->Write( self :: A2S_PING );
|
$this->Socket->Write( self :: A2S_PING );
|
||||||
$this->Socket->Read( );
|
$this->Socket->Read( );
|
||||||
|
|
||||||
return $this->Buffer->GetByte( ) == self :: S2A_PING;
|
return $this->Buffer->GetByte( ) === self :: S2A_PING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -213,13 +213,13 @@
|
|||||||
|
|
||||||
$Type = $this->Buffer->GetByte( );
|
$Type = $this->Buffer->GetByte( );
|
||||||
|
|
||||||
if( $Type == 0 )
|
if( $Type === 0 )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Old GoldSource protocol, HLTV still uses it
|
// Old GoldSource protocol, HLTV still uses it
|
||||||
if( $Type == self :: S2A_INFO_OLD && $this->Socket->Engine == self :: GOLDSOURCE )
|
if( $Type === self :: S2A_INFO_OLD && $this->Socket->Engine === self :: GOLDSOURCE )
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* If we try to read data again, and we get the result with type S2A_INFO (0x49)
|
* If we try to read data again, and we get the result with type S2A_INFO (0x49)
|
||||||
@@ -237,8 +237,8 @@
|
|||||||
$Server[ 'Protocol' ] = $this->Buffer->GetByte( );
|
$Server[ 'Protocol' ] = $this->Buffer->GetByte( );
|
||||||
$Server[ 'Dedicated' ] = Chr( $this->Buffer->GetByte( ) );
|
$Server[ 'Dedicated' ] = Chr( $this->Buffer->GetByte( ) );
|
||||||
$Server[ 'Os' ] = Chr( $this->Buffer->GetByte( ) );
|
$Server[ 'Os' ] = Chr( $this->Buffer->GetByte( ) );
|
||||||
$Server[ 'Password' ] = $this->Buffer->GetByte( ) == 1;
|
$Server[ 'Password' ] = $this->Buffer->GetByte( ) === 1;
|
||||||
$Server[ 'IsMod' ] = $this->Buffer->GetByte( ) == 1;
|
$Server[ 'IsMod' ] = $this->Buffer->GetByte( ) === 1;
|
||||||
|
|
||||||
if( $Server[ 'IsMod' ] )
|
if( $Server[ 'IsMod' ] )
|
||||||
{
|
{
|
||||||
@@ -247,11 +247,11 @@
|
|||||||
$this->Buffer->Get( 1 ); // NULL byte
|
$this->Buffer->Get( 1 ); // NULL byte
|
||||||
$Mod[ 'Version' ] = $this->Buffer->GetLong( );
|
$Mod[ 'Version' ] = $this->Buffer->GetLong( );
|
||||||
$Mod[ 'Size' ] = $this->Buffer->GetLong( );
|
$Mod[ 'Size' ] = $this->Buffer->GetLong( );
|
||||||
$Mod[ 'ServerSide' ] = $this->Buffer->GetByte( ) == 1;
|
$Mod[ 'ServerSide' ] = $this->Buffer->GetByte( ) === 1;
|
||||||
$Mod[ 'CustomDLL' ] = $this->Buffer->GetByte( ) == 1;
|
$Mod[ 'CustomDLL' ] = $this->Buffer->GetByte( ) === 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
$Server[ 'Secure' ] = $this->Buffer->GetByte( ) == 1;
|
$Server[ 'Secure' ] = $this->Buffer->GetByte( ) === 1;
|
||||||
$Server[ 'Bots' ] = $this->Buffer->GetByte( );
|
$Server[ 'Bots' ] = $this->Buffer->GetByte( );
|
||||||
|
|
||||||
if( isset( $Mod ) )
|
if( isset( $Mod ) )
|
||||||
@@ -262,7 +262,7 @@
|
|||||||
return $Server;
|
return $Server;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( $Type != self :: S2A_INFO )
|
if( $Type !== self :: S2A_INFO )
|
||||||
{
|
{
|
||||||
throw new SourceQueryException( 'GetInfo: Packet header mismatch. (0x' . DecHex( $Type ) . ')' );
|
throw new SourceQueryException( 'GetInfo: Packet header mismatch. (0x' . DecHex( $Type ) . ')' );
|
||||||
}
|
}
|
||||||
@@ -278,11 +278,11 @@
|
|||||||
$Server[ 'Bots' ] = $this->Buffer->GetByte( );
|
$Server[ 'Bots' ] = $this->Buffer->GetByte( );
|
||||||
$Server[ 'Dedicated' ] = Chr( $this->Buffer->GetByte( ) );
|
$Server[ 'Dedicated' ] = Chr( $this->Buffer->GetByte( ) );
|
||||||
$Server[ 'Os' ] = Chr( $this->Buffer->GetByte( ) );
|
$Server[ 'Os' ] = Chr( $this->Buffer->GetByte( ) );
|
||||||
$Server[ 'Password' ] = $this->Buffer->GetByte( ) == 1;
|
$Server[ 'Password' ] = $this->Buffer->GetByte( ) === 1;
|
||||||
$Server[ 'Secure' ] = $this->Buffer->GetByte( ) == 1;
|
$Server[ 'Secure' ] = $this->Buffer->GetByte( ) === 1;
|
||||||
|
|
||||||
// The Ship
|
// The Ship (they violate query protocol spec by modifying the response)
|
||||||
if( $Server[ 'AppID' ] == 2400 )
|
if( $Server[ 'AppID' ] === 2400 )
|
||||||
{
|
{
|
||||||
$Server[ 'GameMode' ] = $this->Buffer->GetByte( );
|
$Server[ 'GameMode' ] = $this->Buffer->GetByte( );
|
||||||
$Server[ 'WitnessCount' ] = $this->Buffer->GetByte( );
|
$Server[ 'WitnessCount' ] = $this->Buffer->GetByte( );
|
||||||
@@ -294,7 +294,7 @@
|
|||||||
// Extra Data Flags
|
// Extra Data Flags
|
||||||
if( $this->Buffer->Remaining( ) > 0 )
|
if( $this->Buffer->Remaining( ) > 0 )
|
||||||
{
|
{
|
||||||
$Flags = $this->Buffer->GetByte( );
|
$Server[ 'ExtraDataFlags' ] = $Flags = $this->Buffer->GetByte( );
|
||||||
|
|
||||||
// The server's game port
|
// The server's game port
|
||||||
if( $Flags & 0x80 )
|
if( $Flags & 0x80 )
|
||||||
@@ -305,7 +305,7 @@
|
|||||||
// The server's SteamID - does this serve any purpose?
|
// The server's SteamID - does this serve any purpose?
|
||||||
if( $Flags & 0x10 )
|
if( $Flags & 0x10 )
|
||||||
{
|
{
|
||||||
$Server[ 'ServerID' ] = $this->Buffer->GetUnsignedLong( ) | ( $this->Buffer->GetUnsignedLong( ) << 32 );
|
$Server[ 'ServerID' ] = $this->Buffer->GetUnsignedLong( ) | ( $this->Buffer->GetUnsignedLong( ) << 32 ); // TODO: verify this
|
||||||
}
|
}
|
||||||
|
|
||||||
// The spectator port and then the spectator server name
|
// The spectator port and then the spectator server name
|
||||||
@@ -321,7 +321,16 @@
|
|||||||
$Server[ 'GameTags' ] = $this->Buffer->GetString( );
|
$Server[ 'GameTags' ] = $this->Buffer->GetString( );
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x01 - The server's 64-bit GameID
|
// GameID -- alternative to AppID?
|
||||||
|
if( $Flags & 0x01 )
|
||||||
|
{
|
||||||
|
$Server[ 'GameID' ] = $this->Buffer->GetUnsignedLong( ) | ( $this->Buffer->GetUnsignedLong( ) << 32 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( $this->Buffer->Remaining( ) > 0 )
|
||||||
|
{
|
||||||
|
throw new SourceQueryException( 'GetInfo: unread data? ' . $this->Buffer->Remaining( ) . ' bytes remaining in the buffer. Please report it to the library developer.' );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $Server;
|
return $Server;
|
||||||
@@ -355,11 +364,11 @@
|
|||||||
|
|
||||||
$Type = $this->Buffer->GetByte( );
|
$Type = $this->Buffer->GetByte( );
|
||||||
|
|
||||||
if( $Type == 0 )
|
if( $Type === 0 )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if( $Type != self :: S2A_PLAYER )
|
else if( $Type !== self :: S2A_PLAYER )
|
||||||
{
|
{
|
||||||
throw new SourceQueryException( 'GetPlayers: Packet header mismatch. (0x' . DecHex( $Type ) . ')' );
|
throw new SourceQueryException( 'GetPlayers: Packet header mismatch. (0x' . DecHex( $Type ) . ')' );
|
||||||
}
|
}
|
||||||
@@ -412,11 +421,11 @@
|
|||||||
|
|
||||||
$Type = $this->Buffer->GetByte( );
|
$Type = $this->Buffer->GetByte( );
|
||||||
|
|
||||||
if( $Type == 0 )
|
if( $Type === 0 )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if( $Type != self :: S2A_RULES )
|
else if( $Type !== self :: S2A_RULES )
|
||||||
{
|
{
|
||||||
throw new SourceQueryException( 'GetRules: Packet header mismatch. (0x' . DecHex( $Type ) . ')' );
|
throw new SourceQueryException( 'GetRules: Packet header mismatch. (0x' . DecHex( $Type ) . ')' );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Source Query PHP Class</title>
|
<title>Source Query PHP Class</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/css/bootstrap.min.css">
|
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.jumbotron {
|
.jumbotron {
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
<table class="table table-bordered table-striped">
|
<table class="table table-bordered table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="2">Server Info <em>(queried in <?php echo $Timer; ?>s)</em></th>
|
<th colspan="2">Server Info <span class="label label-<?php echo $Timer > 1.0 ? 'danger' : 'success'; ?>"><?php echo $Timer; ?>s</span></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -97,7 +97,18 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
echo htmlspecialchars( $InfoValue );
|
if( $InfoValue === true )
|
||||||
|
{
|
||||||
|
echo 'true';
|
||||||
|
}
|
||||||
|
else if( $InfoValue === false )
|
||||||
|
{
|
||||||
|
echo 'false';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
echo htmlspecialchars( $InfoValue );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?></td>
|
?></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user