Guest User

server query ( include )

a guest
Dec 11th, 2010
281
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 9.59 KB | None | 0 0
  1. <?php
  2. /*********************************************
  3. *
  4. * SA-MP Query Server Version 0.3
  5. *
  6. * This class provides you with an easy to use interface to query
  7. * your SA-MP 0.2 servers. Usage is simple, but has changed a bit
  8. * since the last version, so be sure to check out the examples
  9. * that come along with this script. It is updated with some of
  10. * the new SA-MP 0.2 query-techniques that can be used.
  11. *
  12. * Author:  Peter Beverloo
  13. *          peter@dmx-network.com
  14. *          Ex SA-MP Developer
  15. *
  16. * Updated: Wouter van Eekelen
  17. *          wouter.van.eekelen@serverffs.com
  18. *          SA-MP Betatester
  19. *********************************************/
  20.  
  21. class QueryServer
  22. {
  23.     // Private variables used for the query-ing.
  24.     private $szServerIP;
  25.     private $iPort;
  26.     private $rSocketID;
  27.  
  28.     private $bStatus;
  29.  
  30.     // The __construct function gets called automatically
  31.     // by PHP once the class gets initialized.
  32.     function __construct( $szServerIP, $iPort )
  33.     {
  34.             $this->szServerIP = $this->VerifyAddress( $szServerIP );
  35.             $this->iPort = $iPort;
  36.  
  37.             if (empty( $this->szServerIP ) || !is_numeric( $iPort )) {
  38.                     throw new QueryServerException( 'Either the ip-address or the port isn\'t filled in correctly.' );
  39.             }
  40.  
  41.             $this->rSocketID = @fsockopen( 'udp://' . $this->szServerIP, $iPort, $iErrorNo, $szErrorStr, 5 );
  42.             if (!$this->rSocketID) {
  43.                     throw new QueryServerException( 'Cannot connect to the server: ' . $szErrorStr );
  44.             }
  45.  
  46.             socket_set_timeout( $this->rSocketID, 0, 500000 );
  47.             $this->bStatus = true;
  48.     }
  49.  
  50.     // The VerifyAddress function verifies the given hostname/
  51.     // IP address and returns the actual IP Address.
  52.     function VerifyAddress( $szServerIP )
  53.     {
  54.             if (ip2long( $szServerIP ) !== false &&
  55.                 long2ip( ip2long( $szServerIP ) ) == $szServerIP ) {
  56.                     return $szServerIP;
  57.             }
  58.  
  59.             $szAddress = gethostbyname( $szServerIP );
  60.             if ($szAddress == $szServerIP) {
  61.                     return "";
  62.             }
  63.  
  64.             return $szAddress;
  65.     }
  66.  
  67.     // The SendPacket function sends a packet to the server which
  68.     // requests information, based on the type of packet send.
  69.     function SendPacket( $cPacket )
  70.     {
  71.             $szPacket = 'SAMP';
  72.             $aIpChunks = explode( '.', $this->szServerIP );
  73.  
  74.             foreach( $aIpChunks as $szChunk ) {
  75.                     $szPacket .= chr( $szChunk );
  76.             }
  77.  
  78.             $szPacket .= chr( $this->iPort & 0xFF );
  79.             $szPacket .= chr( $this->iPort >> 8 & 0xFF );
  80.             $szPacket .= $cPacket;
  81.  
  82.             return fwrite( $this->rSocketID, $szPacket, strlen( $szPacket ) );
  83.     }
  84.  
  85.     // The GetPacket() function returns a specific number of bytes
  86.     // read from the socket. This uses a special way of getting stuff.
  87.     function GetPacket( $iBytes )
  88.     {
  89.             $iResponse = fread( $this->rSocketID, $iBytes );
  90.             if ($iResponse === false) {
  91.                     throw new QueryServerException( 'Connection to ' . $this->szServerIP . ' failed or has dropped.' );
  92.             }
  93.  
  94.             $iLength = ord( $iResponse );
  95.             if ($iLength > 0)
  96.                     return fread( $this->rSocketID, $iLength );
  97.  
  98.             return "";
  99.     }
  100.  
  101.     // After we're done, the connection needs to be closed using
  102.     // the Close() function. Otherwise stuff might go wrong.
  103.     function Close( )
  104.     {
  105.             if ($this->rSocketID !== false) {
  106.                     fclose( $this->rSocketID );
  107.             }
  108.     }
  109.  
  110.     // A little function that's needed to properly convert the
  111.     // four bytes we're recieving to integers to an actual PHP
  112.     // integer. ord() can't handle value's higher then 255.
  113.     function toInteger( $szData )
  114.     {
  115.             $iInteger = 0;
  116.  
  117.             $iInteger += ( ord( @$szData[ 0 ] ) );
  118.             $iInteger += ( ord( @$szData[ 1 ] ) << 8 );
  119.             $iInteger += ( ord( @$szData[ 2 ] ) << 16 );
  120.             $iInteger += ( ord( @$szData[ 3 ] ) << 24 );
  121.  
  122.             if( $iInteger >= 4294967294 )
  123.                     $iInteger -= 4294967296;
  124.  
  125.             return $iInteger;
  126.     }
  127.  
  128.     // The GetInfo() function returns basic information about the
  129.     // server, like the hostname, number of players online etc.
  130.     function GetInfo( )
  131.     {
  132.             if ($this->SendPacket('i') === false) {
  133.                     throw new QueryServerException( 'Connection to ' . $this->szServerIP . ' failed or has dropped.' );
  134.             }
  135.  
  136.             $szFirstData = fread( $this->rSocketID, 4 );
  137.             if (empty( $szFirstData ) || $szFirstData != 'SAMP') {
  138.                     throw new QueryServerException( 'The server at ' . $this->szServerIP . ' is not an SA-MP Server.' );
  139.             }
  140.  
  141.             // Pop the first seven characters returned.
  142.             fread( $this->rSocketID, 7 );
  143.  
  144.             return array (
  145.                     'Password'   =>   ord( fread( $this->rSocketID, 1 ) ),
  146.                     'Players'    =>   $this->toInteger( fread( $this->rSocketID, 2 ) ),
  147.                     'MaxPlayers' =>   $this->toInteger( fread( $this->rSocketID, 2 ) ),
  148.                     'Hostname'   =>   $this->GetPacket( 4 ),
  149.                     'Gamemode'   =>   $this->GetPacket( 4 ),
  150.                     'Map'        =>   $this->GetPacket( 4 )
  151.             );
  152.     }
  153.  
  154.     // The GetRules() function returns the rules which are set
  155.     // on the server, e.g. the gravity, version etcetera.
  156.     function GetRules( )
  157.     {
  158.             if ($this->SendPacket('r') === false) {
  159.                     throw new QueryServerException( 'Connection to ' . $this->szServerIP . ' failed or has dropped.' );
  160.             }
  161.  
  162.             // Pop the first 11 bytes from the response;
  163.             fread( $this->rSocketID, 11 );
  164.  
  165.             $iRuleCount = ord( fread( $this->rSocketID, 2 ) );
  166.             $aReturnArray = array( );
  167.  
  168.             for( $i = 0; $i < $iRuleCount; $i ++ ) {
  169.                     $szRuleName = $this->GetPacket( 1 );
  170.                     $aReturnArray[ $szRuleName ] = $this->GetPacket( 1 );
  171.             }
  172.  
  173.             return $aReturnArray;
  174.     }
  175.  
  176.     // The GetPlayers() function is pretty much simelar to the
  177.     // detailed function, but faster and contains less information.
  178.     function GetPlayers( )
  179.     {
  180.             if ($this->SendPacket('c') === false) {
  181.                     throw new QueryServerException( 'Connection to ' . $this->szServerIP . ' failed or has dropped.' );
  182.             }
  183.  
  184.             // Again, pop the first eleven bytes send;
  185.             fread( $this->rSocketID, 11 );
  186.  
  187.             $iPlayerCount = ord( fread( $this->rSocketID, 2 ) );
  188.             $aReturnArray = array( );
  189.  
  190.             for( $i = 0; $i < $iPlayerCount; $i ++ )
  191.             {
  192.                     $aReturnArray[ ] = array (
  193.                             'Nickname' => $this->GetPacket( 1 ),
  194.                             'Score'    => $this->toInteger( fread( $this->rSocketID, 4 ) )
  195.                     );
  196.             }
  197.  
  198.             return $aReturnArray;
  199.     }
  200.  
  201.     // The GetDetailedPlayers() function returns the player list,
  202.     // but in a detailed form inclusing the score and the ping.
  203.     function GetDetailedPlayers( )
  204.     {
  205.             if ($this->SendPacket('d') === false) {
  206.                     throw new QueryServerException( 'Connection to ' . $this->szServerIP . ' failed or has dropped.' );
  207.             }
  208.  
  209.             // Skip the first 11 bytes of the response;
  210.             fread( $this->rSocketID, 11 );
  211.  
  212.             $iPlayerCount = ord( fread( $this->rSocketID, 2 ) );
  213.             $aReturnArray = array( );
  214.  
  215.             for( $i = 0; $i < $iPlayerCount; $i ++ ) {
  216.                     $aReturnArray[ ] = array(
  217.                             'PlayerID'   =>  $this->toInteger( fread( $this->rSocketID, 1 ) ),
  218.                             'Nickname'   =>  $this->GetPacket( 1 ),
  219.                             'Score'      =>  $this->toInteger( fread( $this->rSocketID, 4 ) ),
  220.                             'Ping'       =>  $this->toInteger( fread( $this->rSocketID, 4 ) )
  221.                     );
  222.             }
  223.  
  224.             return $aReturnArray;
  225.     }
  226.  
  227. function RCON($rcon, $command)
  228.     {
  229.             echo 'Password '.$rcon.' with '.$command;
  230.             if ($this->SendPacket('x '.$rcon.' '.$command) === false) {
  231.                     throw new QueryServerException( 'Connection to ' . $this->szServerIP . ' failed or has dropped.' );
  232.             }
  233.  
  234.             // Pop the first 11 bytes from the response;
  235.             $aReturnArray = fread( $this->rSocketID, 11 );
  236.  
  237.             echo fread( $this->rSocketID, 11 );
  238.  
  239.             return $aReturnArray;
  240.     }
  241.  
  242. }
  243.  
  244. /*********************************************
  245. *
  246. * The QueryServerException is used to throw errors when querying
  247. * a specific server. That way we force the user to use proper
  248. * error-handling, and preferably even a try-/catch statement.
  249. *
  250. **********************************************/
  251.  
  252. class QueryServerException extends Exception
  253. {
  254.     // The actual error message is stored in this variable.
  255.     private $szMessage;
  256.  
  257.     // Again, the __construct function gets called as soon
  258.     // as the exception is being thrown, in here we copy the message.
  259.     function __construct( $szMessage )
  260.     {
  261.             $this->szMessage = $szMessage;
  262.     }
  263.  
  264.     // In order to read the exception being thrown, we have
  265.     // a .NET-like toString() function, which returns the message.
  266.     function toString( )
  267.     {
  268.             return $this->szMessage;
  269.     }
  270. }
  271. ?>
Add Comment
Please, Sign In to add comment