xt3z0ne

samp_query

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