Advertisement
Guest User

gsquery.php

a guest
Nov 8th, 2011
1,589
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 73.80 KB | None | 0 0
  1. <?php
  2. /* vim: set expandtab tabstop=2 shiftwidth=2 softtabstop=2 foldmethod=marker: */
  3.  
  4. /*
  5.  * Gameserver Query Protocol Class
  6.  * Copyright (C) 2004 Manuel Mausz ( manuel @ clanserver.eu )
  7.  * ClanServer - Just Gaming!
  8.  * http://www.clanserver.eu
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2, or (at your option)
  13.  * any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  */
  24.  
  25. /* {{{ Description
  26.  * Gameserver Query Protocol Class
  27.  *
  28.  * Queries different gameservers and returns the current
  29.  * status information. supports several query protocols.
  30.  *
  31.  * Supported Protocols:
  32.  * For further information: http://www.int64.org/protocols/
  33.  *   - Half-Life/Half-Life: Source ("HalfLife")
  34.  *   - All Seeing Eye ("AllSeeingEye")
  35.  *   - Quake 1/Quake World ("Quake1")
  36.  *   - Quake 2 ("Quake2")
  37.  *   - Quake 3 ("Quake3")
  38.  *   - Doom 3/Quake 4/Enemy Territory: Quake Wars ("Doom3")
  39.  *   - GameSpy/UT ("GameSpy")
  40.  *   - GameSpy 2 ("GameSpy2")
  41.  *   - GameSpy 3 ("GameSpy3")
  42.  *   - GameSpy 4 ("GameSpy4")
  43.  *
  44.  * Users:
  45.  *   $this->SetProtocol("protocol")
  46.  *     ... protocol to use for query
  47.  *
  48.  *   $this->SetIpPort("ip:port:queryport")
  49.  *     ... ip, port and queryport to use for query
  50.  *         the queryport is optional
  51.  *
  52.  *   $this->SetLocalQuery(0 or 1)
  53.  *     ... set localhost query (used for halflife query)
  54.  *
  55.  *   $this->SetRequestData(array("infotype1", "infotype2", ...))
  56.  *     ... data to request from server. must be type array
  57.  *         use the alias "FullInfo" for full information
  58.  *
  59.  *   array = $this->GetData()
  60.  *     ... request the data from gameserver
  61.  *         data will be returned as type array
  62.  *
  63.  *   bool = $this->ERROR
  64.  *     ... TRUE if an error occur, FALSE otherwise
  65.  *
  66.  *   string = $this->ERRSTR
  67.  *     ... contains the error message as string
  68.  *
  69.  * Advanced Users:
  70.  *   $this->SetSocketTimeOut(int seconds, int microseconds)
  71.  *     ... sets socket timeout. default: 0s, 50000ms
  72.  *
  73.  *   $this->SetSocketLoopTimeOut(int microseconds)
  74.  *     ... sets loop timeout in microseconds. default: 1000
  75.  *
  76.  * Debug Modus:
  77.  *   define("DEBUG", TRUE)
  78.  *     ... enables debug modus
  79.  *
  80.  *  AutoDetection:
  81.  *    $this->SetProtocol("AutoDetect")
  82.  *      ... must be set to "AutoDetect"
  83.  *    $this->SetProtocols(array("protocol1", "protocol2", ...))
  84.  *      ... protocols to use for autodetection
  85.  *      ... NOTE: GameSpyPortPlus10 is an alias for GameSpy but uses QueryPort+10
  86.  *
  87.  * Developers:
  88.  *   This class contains an autodetect-query-protocol-engine
  89.  *   If you want to add your own query, you will have to name your methodes like:
  90.  *     _YourNameMain()       ... main methode. will be called first from engine
  91.  *     _YourNameString1()    ... sub methode. must be called from main methode
  92.  *                               will request string1 from gameserver (eg: _YourNameDetails)
  93.  *     _YourNameAutoDetect() ... will be called from autodetection engine before _YourNameMain
  94.  *                               normally used for setting correct query port
  95.  *                               if you don't want autodetection, don't define this methode
  96.  *     _YourNameFullInfo()   ... wrapper for requestdatatype "FullInfo"
  97.  *
  98.  }}} */
  99.  
  100. /* {{{ ToDo:
  101.  *  - HalfLife/HalfLifeSource
  102.  *    - Sometimes query comes in fragments prefixed by an id
  103.  *      syntax: "<id>2" -> 02, 12, 22, ... (not sure about that)
  104.  *      this behavior is only recognized in _HalfLifeRules()
  105.  *      -> append fragments depending on their queryid
  106.  *  - GameSpy
  107.  *    - If one player name contains the string deliminater "\", the query will probably stop working
  108.  *    - Protocol is fragmental and will send a queryid followed by a number at the end
  109.  *      -> append fragments depending on their queryid
  110.  *  - Better Error Handling!
  111.  }}} */
  112.  
  113. class GSQuery
  114. {
  115.   // {{{ global variable definitions
  116.   var $ERROR;
  117.   var $ERRSTR;
  118.   var $DEBUG;
  119.  
  120.   var $_ip;
  121.   var $_port;
  122.   var $_queryport;
  123.   var $_fullinfo;
  124.   var $_localquery;
  125.   var $_socket;
  126.   var $_stimeout;
  127.   var $_mstimeout;
  128.   var $_looptimeout;
  129.   var $_protocol;
  130.   var $_gettypes;
  131.   var $_protocols;
  132.   // }}}
  133.  
  134.   // {{{ GSQuery() - main class constructor
  135.   function GSQuery()
  136.   {
  137.     $this->ERROR  = FALSE;
  138.     $this->ERRSTR = "";
  139.     $this->DEBUG  = FALSE;
  140.    
  141.     $this->_ip          = 0;
  142.     $this->_port        = 0;
  143.     $this->_queryport   = 0;
  144.     $this->_fullinfo    = 0;
  145.     $this->_localquery  = 0;
  146.     $this->_socket      = 0;
  147.     $this->_stimeout    = 0;
  148.     $this->_mstimeout   = 50000;
  149.     $this->_looptimeout = 1000;
  150.     $this->_protocol    = "";
  151.     $this->_gettypes    = array();
  152.     $this->_protocols   = array();
  153.     $this->_globalvars = array();
  154.  
  155.     if (defined('DEBUG') && DEBUG)
  156.       $this->DEBUG = TRUE;
  157. // Commented out to disable error messages
  158. //    set_error_handler(array(&$this, "_ErrorHandler"));
  159.     return TRUE;
  160.   }
  161.   // }}}
  162.  
  163.   // {{{ SetProtocol() - sets query protocol to use
  164.   // @param  string $arg1  protocol to use for gameserver query
  165.   // @return bool          always TRUE
  166.   // @access public
  167.   function SetProtocol($string)
  168.   {
  169.     $this->_protocol = $string;
  170.     trigger_error("<b>Set Protocol</b>: ".$string);
  171.     return TRUE;
  172.   }
  173.   // }}}
  174.  
  175.   // {{{ SetIpPort() - sets ip, port and optional queryport
  176.   // @param  string $arg1  format: "ip:port" or "ip:port:queryport"
  177.   // @return bool          always TRUE
  178.   // @access public
  179.   function SetIpPort($string)
  180.   {
  181.     if (substr_count($string, ":") == 2)
  182.       list($this->_ip, $this->_port, $this->_queryport) = explode(":", $string);
  183.     else
  184.     {
  185.       list($this->_ip, $this->_port) = explode(":", $string);
  186.       $this->_queryport = 0;
  187.     }
  188.     $this->_port = intval($this->_port);
  189.     $this->_queryport = intval($this->_queryport);
  190.  
  191.     trigger_error("<b>Set Gameserver IP</b>: ".$this->_ip);
  192.     trigger_error("<b>Set Gameserver Port</b>: ".$this->_port);
  193.     if ($this->_queryport != 0)
  194.       trigger_error("<b>Set Gameserver QueryPort</b>: ".$this->_queryport);
  195.     return TRUE;
  196.   }
  197.   // }}}
  198.  
  199.   // {{{ SetRequestData() - sets data which query will request from gameserver
  200.   // @param  array $arg1  data to request from gameserver
  201.   // @return bool         always TRUE
  202.   // @access public
  203.   function SetRequestData($gettypes)
  204.   {
  205.     if (!is_array($gettypes))
  206.     {
  207.       $this->_SoftError("SetRequestData(): argument 1 is not an array");
  208.       return FALSE;
  209.     }
  210.  
  211.     $this->_gettypes = $gettypes;
  212.  
  213.     if ($this->_gettypes[0] == "FullInfo")
  214.       $this->_fullinfo = 1;
  215.  
  216.     foreach ($this->_gettypes as $type)
  217.       trigger_error("<b>Set RequestData</b>: ".$type);
  218.     return TRUE;
  219.   }
  220.   // }}}
  221.  
  222.   // {{{ SetProtocols() - set autodetect protocols
  223.   // @param  array $arg1  protocols to autodetect
  224.   // @return bool         always TRUE
  225.   // @access public
  226.   function SetProtocols($protocols)
  227.   {
  228.     if (!is_array($protocols))
  229.     {
  230.       $this->_SoftError("SetProtocols(): argument 1 is not an array");
  231.       return FALSE;
  232.     }
  233.  
  234.     $this->_protocols = $protocols;
  235.     foreach ($this->_protocols as $type)
  236.       trigger_error("<b>Set AutoDetect Protocols</b>: ".$type);
  237.     return TRUE;
  238.   }
  239.   // }}}
  240.  
  241.   // {{{ SetLocalQuery() - set local query (used for halflife query)
  242.   // @param  int          0 or 1
  243.   // @return bool         always TRUE
  244.   // @access public
  245.   function SetLocalQuery($enable)
  246.   {
  247.     $this->_localquery = $enable;
  248.     trigger_error("<b>Set Local Query</b>: ".$this->_localquery);
  249.     return TRUE;
  250.   }
  251.   // }}}
  252.  
  253.   // {{{ SetSocketTimeOut() - sets an optional socket timeout
  254.   // @param  int $arg1  socket timeout in seconds
  255.   //         int $arg2  socket timeout in microseconds
  256.   // @return bool       always TRUE
  257.   // @access public
  258.   function SetSocketTimeOut($stimeout, $mstimeout)
  259.   {
  260.     $this->_stimeout  = $stimeout;
  261.     $this->_mstimeout = $mstimeout;
  262.     trigger_error("<b>Set Socket Timeout Seconds</b>: ".$this->_stimeout);
  263.     trigger_error("<b>Set Socket Timeout MicroSeconds</b>: ".$this->_mstimeout);
  264.     return TRUE;
  265.   }
  266.   // }}}
  267.  
  268.   // {{{ SetSocketLoopTimeOut() - sets an optional socket loop timeout
  269.   // @param  int $arg1  socket loop timeout in microseconds
  270.   // @return bool       always TRUE
  271.   // @access public
  272.   function SetSocketLoopTimeOut($timeout)
  273.   {
  274.     $this->_looptimeout = $timeout;
  275.     trigger_error("<b>Set Socket Loop Timeout</b>: ".$this->_looptimeout);
  276.     return TRUE;
  277.   }
  278.   // }}}
  279.  
  280.   // {{{ GetData() - requests data from gameserver and returns an array
  281.   // @return array  requested data as array in format: $array["data1"][...]
  282.   //         bool   FALSE if an error occur
  283.   // @access public
  284.   function GetData()
  285.   {
  286.     $recvdata = array();
  287.  
  288.     $this->_CheckSettings();
  289.     if ($this->ERROR)
  290.       return FALSE;
  291.     if ($this->_fullinfo && $this->_protocol != "AutoDetect")
  292.     {
  293.       $recvdata = call_user_func(array(&$this, "_".$this->_protocol."FullInfo"));
  294.       $recvdata["Protocol"] = $this->_protocol;
  295.     }
  296.     else
  297.       $recvdata = call_user_func(array(&$this, "_".$this->_protocol."Main"));
  298.     $this->_CleanUP();
  299.  
  300.     return $recvdata;
  301.   }
  302.   // }}}
  303.  
  304.   // {{{ _GetMicroTime() - returns current timestamp as microseconds
  305.   // @return float  timestamp as micrososeconds
  306.   // @access protected
  307.   function _GetMicroTime()
  308.   {
  309.     list($usec, $sec) = explode(" ",microtime());
  310.     return ((float)$usec + (float)$sec);
  311.   }
  312.   // }}}
  313.  
  314.   // {{{ _CleanUp() - class clean up
  315.   // @return bool  always TRUE
  316.   // @access protected
  317.   function _CleanUp()
  318.   {
  319.     restore_error_handler();
  320.     return TRUE;
  321.   }
  322.   // }}}
  323.  
  324.   // {{{ _CheckSettings() - check for valid settings
  325.   // @return bool  TRUE if no error occur
  326.   //               FALSE otherwise
  327.   // @access protected
  328.   function _CheckSettings()
  329.   {
  330.     $type = "";
  331.  
  332.     // check available protocol
  333.     if ($this->_protocol == "")
  334.     {
  335.       $this->_SoftError("No protocol set");
  336.       return FALSE;
  337.     }
  338.     if (!is_callable(array(&$this, "_".$this->_protocol."Main")))
  339.     {
  340.       $this->_SoftError("\"".$this->_protocol."\" protocol not available");
  341.       return FALSE;
  342.     }
  343.  
  344.     // check available methodes for this protocol
  345.     if (empty($this->_gettypes))
  346.     {
  347.       $this->_SoftError("No requesttypes set");
  348.       return FALSE;
  349.     }
  350.     if ($this->_protocol != "AutoDetect")
  351.     {
  352.       foreach ($this->_gettypes as $type)
  353.       {
  354.         if ($type != "RCon")
  355.         {
  356.           if (!is_callable(array(&$this, "_".$this->_protocol.$type)))
  357.           {
  358.             $this->_SoftError("SetRequestData() Type: \"".$type."\" now known in Protocol: \"".$this->_protocol."\"");
  359.             return FALSE;
  360.           }
  361.         }
  362.       }
  363.     }
  364.  
  365.     // check ip and port
  366.     if ($this->_ip == "" || $this->_port == "")
  367.     {
  368.       $this->_SoftError("No IP or Port set");
  369.       return FALSE;
  370.     }
  371.     if (!preg_match("/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})$/", gethostbyname($this->_ip)))
  372.     {
  373.       $this->_SoftError("Wrong Gameserver IP Format");
  374.       return FALSE;
  375.     }
  376.     if (!is_integer($this->_port) || $this->_port <= 0 || 65536 < $this->_port)
  377.     {
  378.       $this->_SoftError("Wrong Gameserver Port Format");
  379.       return FALSE;
  380.     }
  381.     if ($this->_queryport != 0 && (!is_integer($this->_queryport) || $this->_queryport <= 0 || 65536 < $this->_queryport))
  382.     {
  383.       $this->_SoftError("Wrong Gameserver QueryPort Format");
  384.       return FALSE;
  385.     }
  386.  
  387.     // check and calculate socket loop timeout
  388.     if ($this->_looptimeout < 500)  $this->_looptimeout = 500;
  389.     if ($this->_looptimeout > 2000) $this->_looptimeout = 2000;
  390.     $this->_looptimeout = doubleval($this->_looptimeout / 1000.0);
  391.  
  392.     return TRUE;
  393.   }
  394.   // }}}
  395.  
  396.   // {{{ _ErrorHandler() - main php error handler
  397.   // @param  -> reference to php documentation
  398.   // @return bool  always TRUE
  399.   //               stops script if error number is E_USER_ERROR
  400.   // @access protected
  401.   function _ErrorHandler($errno, $errstr, $errfile, $errline)
  402.   {
  403.     switch ($errno) {
  404.       case E_USER_ERROR:
  405.         echo "<b>[FATAL]</b> ".$errstr." in <b>".$errfile."</b> on line <b>".$errline."</b><br />\n";
  406.         exit(1);
  407.         break;
  408.       case E_USER_WARNING:
  409.         echo "<b>[ERROR]</b> ".$errstr." in <b>".$errfile."</b> on line <b>".$errline."</b><br />\n";
  410.         break;
  411.       case E_USER_NOTICE:
  412.         if ($this->DEBUG)
  413.           echo "<b>[DEBUG]</b> ".$errstr."</b>\n";
  414.         break;
  415.       case E_NOTICE:
  416.         echo "<b>[NOTICE]</b> ".$errstr." in <b>".$errfile."</b> on line <b>".$errline."</b><br />\n";
  417.         break;
  418.       default:
  419.         echo "<b>[UNKNOWN]</b> ".$errstr." in <b>".$errfile."</b> on line <b>".$errline."</b><br />\n";
  420.         break;
  421.     }
  422.     return TRUE;
  423.   }
  424.   // }}}
  425.  
  426.   // {{{ _SoftError() - soft error handler
  427.   // @param  string $arg1  error message
  428.   // @return bool          always TRUE
  429.   // @access proteced
  430.   function _SoftError($errstr)
  431.   {
  432.     $this->ERROR  = ($errstr === false || strlen($errstr) === 0) ? FALSE : TRUE;
  433.     $this->ERRSTR = $errstr;
  434.     return TRUE;
  435.   }
  436.   // }}}
  437.  
  438.   // {{{ _CreateUDPSocket() - creates an udp socket
  439.   // @return bool  always TRUE
  440.   //               stops script if an error occur
  441.   // @access protected
  442.   function _CreateUDPSocket()
  443.   {
  444.     if ($this->_queryport == 0)
  445.       $this->_queryport = $this->_port;
  446.     if (!$this->_socket = fsockopen("udp://".$this->_ip, $this->_queryport, $errnr, $errstr))
  447.     {
  448.       trigger_error("Could not create socket (".$errstr.")", E_USER_ERROR);
  449.     }
  450.     socket_set_blocking($this->_socket, TRUE);
  451.     socket_set_timeout($this->_socket, $this->_stimeout, $this->_mstimeout);
  452.     return TRUE;
  453.   }
  454.   // }}}
  455.  
  456.   // {{{ _SendSocket() - write data to socket
  457.   // @param  string $arg1  string to write to socket
  458.   // @return bool          always TRUE
  459.   //                       stops script if an error occur
  460.   // @access protected
  461.   function _SendSocket($string)
  462.   {
  463.     if (!fwrite($this->_socket, $string, strlen($string)))
  464.       trigger_error("Could not send data", E_USER_ERROR);
  465.     return TRUE;
  466.   }
  467.   // }}}
  468.  
  469.   // {{{ _GetSocketData() - read data from socket
  470.   // @return string  data received from socket buffer
  471.   //         bool    FALSE and triggers _SoftError() if an error occur
  472.   // @access protected
  473.   function _GetSocketData()
  474.   {
  475.     $recv = "";
  476.     $socketstatus = array();
  477.     $start = $this->_GetMicroTime();
  478.     do
  479.     {
  480.       $recv .= fgetc($this->_socket);
  481.       $socketstatus = socket_get_status($this->_socket);
  482.       if ($this->_GetMicroTime() > ($start + $this->_looptimeout))
  483.       {
  484.         $this->_CloseUDPSocket();
  485.         $this->_SoftError("Connection to server timeout out");
  486.         return FALSE;
  487.       }
  488.     }
  489.     while ($socketstatus["unread_bytes"]);
  490.  
  491.     if ($recv == "")
  492.       $this->_SoftError("Nothing received from server");
  493.  
  494.     return $recv;
  495.   }
  496.   // }}}
  497.  
  498.   // {{{ _GetSocketDataNr() - read multiple times from socket
  499.   // @param  int $arg1  number how often _GetSocketData() will be called
  500.   // @return array      one array element for every received data
  501.   //                    triggers _SoftError() if no data will be received
  502.   // @access protected
  503.   function _GetSocketDataNr($nr)
  504.   {
  505.     $recv = "";
  506.     $data = array();
  507.     for ($i = 0; $i < $nr; $i++)
  508.     {
  509.       $recv = $this->_GetSocketData();
  510.       if ($recv != "")
  511.         array_push($data, $recv);
  512.     }
  513.     if (count($data))
  514.       $this->_SoftError(FALSE);
  515.  
  516.     return $data;
  517.   }
  518.   // }}}
  519.  
  520.   // {{{ _CloseUDPSocket() - close an udp socket
  521.   // @return bool  always TRUE
  522.   //               stops script if socket cannot be closed
  523.   // @access protected
  524.   function _CloseUDPSocket()
  525.   {
  526.     if (!fclose($this->_socket))
  527.       trigger_error("Could not close socket", E_USER_ERROR);
  528.     return TRUE;
  529.   }
  530.   // }}}
  531.  
  532.   // {{{ _CheckQueryHeader() - checks for query header
  533.   // @param  string $arg1  string to search in. string will be shortened automatically
  534.   //         string $arg2  string to search for
  535.   //         string $arg3  will be set to the snippet-string off $arg1
  536.   // @return bool          TRUE if $arg2 was found
  537.   //                       FALSE otherwise
  538.   // @access protected
  539.   function _CheckQueryHeader(&$data, $header, &$snippet)
  540.   {
  541.     $offset  = 0;
  542.     $snippet = "";
  543.  
  544.     if ($this->ERROR)
  545.       return FALSE;
  546.  
  547.     if (($offset = strpos($data, $header)) !== FALSE)
  548.     {
  549.       $snippet = substr($data, 0, $offset);
  550.       $data = substr($data, $offset + strlen($header));
  551.       return TRUE;
  552.     }
  553.     $this->_SoftError("No query header found in received data");
  554.     return FALSE;
  555.   }
  556.   // }}}
  557.  
  558.   // {{{ _CheckQueryFooter() - checks for query footer
  559.   // @param  string $arg1  string to search in. string will be shortened automatically
  560.   //         string $arg2  string to search for
  561.   //         string $arg3  will be set to the snippet-string off $arg1
  562.   // @return bool          TRUE if $arg2 was found
  563.   //                       FALSE otherwise
  564.   // @access protected
  565.   function _CheckQueryFooter(&$data, $footer, &$snippet)
  566.   {
  567.     $offset  = 0;
  568.     $snippet = "";
  569.  
  570.     if ($this->ERROR)
  571.       return FALSE;
  572.  
  573.     if (($offset = strpos($data, $footer)) !== FALSE)
  574.     {
  575.       $snippet = substr($data, $offset + strlen($footer));
  576.       $data = substr($data, 0, $offset);
  577.       return TRUE;
  578.     }
  579.     $this->_SoftError("No query footer found in received data");
  580.     return FALSE;
  581.   }
  582.   // }}}
  583.  
  584.   // {{{ _GetCharacterTerminatedString() - get a character-terminated-string
  585.   // @param  string $arg1  string to search in. string will be shortened automatically
  586.   // @param  char   $arg2  character to search for
  587.   // @return string        first character-terminated string
  588.   // @access protected
  589.   function _GetCharacterTerminatedString(&$data, $chr)
  590.   {
  591.     $str     = "";
  592.     $counter = 0;
  593.     while ((strlen($data) > $counter) && ($data{$counter++} != $chr))
  594.       $str .= $data{$counter-1};
  595.     $data = substr($data, strlen($str) + 1);
  596.     return $str;
  597.   }
  598.   // }}}
  599.  
  600.   // {{{ _GetDelimitedVariables() - splits a string delimated by a character
  601.   // @param  string $arg1  string to search in
  602.   // @return array         splitted array. format: $data["before_character"] = after_character
  603.   // @access protected
  604.   function _GetDelimitedVariables(&$data, $delimiter)
  605.   {
  606.     $name  = "";
  607.     $value = "";
  608.     $vars  = array();
  609.  
  610.     $name = strtok($data, $delimiter);
  611.     $value = strtok($delimiter);
  612.     while (strlen($name))
  613.     {
  614.       $vars[$name] = $value;
  615.       $name = strtok($delimiter);
  616.       $value = strtok($delimiter);
  617.     }
  618.     return $vars;
  619.   }
  620.   // }}}
  621.  
  622.   // {{{ _GetByteAsChr() -  get one byte as character
  623.   // @param  string $arg1  string to search in. string will be shortened automatically
  624.   // @return string        first byte of string as ascii character
  625.   //         bool          FALSE if length of $arg1 is zero
  626.   // @access protected
  627.   function _GetByteAsChr(&$data)
  628.   {
  629.     $str = "";
  630.     if (!strlen($data))
  631.       return FALSE;
  632.     $str = $data{0};
  633.     $data = substr($data, 1);
  634.     return $str;
  635.   }
  636.   // }}}
  637.  
  638.   // {{{ _GetByteAsAscii() - get one byte as ascii value
  639.   // @param  string $arg1  string to search in. string will be shortened automatically
  640.   // @return string        first byte of string as type ascii value
  641.   // @access protected
  642.   function _GetByteAsAscii(&$data)
  643.   {
  644.     $str = "";
  645.     $str = ord($this->_GetByteAsChr($data));
  646.     return $str;
  647.   }
  648.   // }}}
  649.  
  650.   // {{{ _GetStringByLength() - get a string by length
  651.   // @param  string $arg1  string to snip. string will be shortened automatically
  652.   //         int    $arg2  length to snip off
  653.   // @return string        snippet string
  654.   // @access protected
  655.   function _GetStringByLength(&$data, $length)
  656.   {
  657.     $str  = "";
  658.     $str  = substr($data, 0, $length);
  659.     $data = substr($data, strlen($str));
  660.     return $str;
  661.   }
  662.   // }}}
  663.  
  664.   // {{{ _GetInt16AsInt() - get int16 value
  665.   // @param  string $arg1  string to search in. string will be shortened automatically
  666.   // @return int           corresponding int16 value
  667.   //         bool          FALSE if length of $arg1 is too short
  668.   // @access proteced
  669.   function _GetInt16AsInt(&$data)
  670.   {
  671.     $str = "";
  672.     if (strlen($data) < 2)
  673.       return FALSE;
  674.     $str = $this->_GetByteAsChr($data).$this->_GetByteAsChr($data);
  675.     $str = unpack('sint', $str);
  676.     return $str["int"];
  677.   }
  678.   // }}}
  679.  
  680.   // {{{ _GetInt32AsInt() - get int32 value
  681.   // @param  string $arg1  string to search in. string will be shortened automatically
  682.   // @return int           corresponding int32 value
  683.   //         bool          FALSE if length of $arg1 is too short
  684.   // @access proteced
  685.   function _GetInt32AsInt(&$data)
  686.   {
  687.     $str = "";
  688.     if (strlen($data) < 4)
  689.       return FALSE;
  690.     $str = $this->_GetByteAsChr($data).$this->_GetByteAsChr($data).$this->_GetByteAsChr($data).$this->_GetByteAsChr($data);
  691.     $str = unpack('iint', $str);
  692.     return $str["int"];
  693.   }
  694.   // }}}
  695.  
  696.   // {{{ _GetFloat32AsFloat() - get float32 value
  697.   // @param  string $arg1  string to search in. string will be shortened automatically
  698.   // @return float         corresponding float32 value
  699.   //         bool          FALSE if length of $arg1 is too short
  700.   // @access proteced
  701.   function _GetFloat32AsFloat(&$data)
  702.   {
  703.     $str = "";
  704.     if (strlen($data) < 4)
  705.       return FALSE;
  706.     $str = $this->_GetByteAsChr($data).$this->_GetByteAsChr($data).$this->_GetByteAsChr($data).$this->_GetByteAsChr($data);
  707.     $str = unpack('fint', $str);
  708.     return $str["int"];
  709.   }
  710.   // }}}
  711.  
  712.   // {{{ _GetLongAsLong() - get long value
  713.   // @param  string $arg1  string to search in. string will be shortened automatically
  714.   // @return long          corresponding long value
  715.   //         bool          FALSE if length of $arg1 is too short
  716.   // @access proteced
  717.   function _GetLongAsLong(&$data)
  718.   {
  719.     $str = "";
  720.     if (strlen($data) < 4)
  721.       return FALSE;
  722.     $str = $this->_GetByteAsChr($data).$this->_GetByteAsChr($data).$this->_GetByteAsChr($data).$this->_GetByteAsChr($data);
  723.     $str = unpack('llong', $str);
  724.     return $str["long"];
  725.   }
  726.   // }}}
  727.  
  728.  
  729.   // {{{ _HexDump() - dump bytes as hex
  730.   // @param  string $arg1  data to dump
  731.   // @return bool          TRUE
  732.   // @access proteced
  733.   function _HexDump($data)
  734.   {
  735.     echo  "Length: ".strlen($data)."\n";
  736.  
  737.     $cache = "";
  738.     for ($i = 0; $i < strlen($data); $i++)
  739.     {
  740.       if ($i % 16 == 0)
  741.         printf("%08x  ", $i);
  742.       elseif ($i % 8 == 0)
  743.         echo "  ";
  744.       else
  745.         echo " ";
  746.  
  747.       $cache .= $data{$i};
  748.       printf("%02x", ord($data{$i}));
  749.  
  750.       if (strlen($cache) == 16 || $i == strlen($data) - 1)
  751.       {
  752.         if (strlen($cache) < 16)
  753.         {
  754.           $shift = "";
  755.           for ($j = strlen($cache); $j < 16; $j++)
  756.           {
  757.             if ($j % 8 == 0)
  758.               $shift .= "  ";
  759.             $shift .= "   ";
  760.           }
  761.           echo substr($shift, 0, strlen($shift) - 1);
  762.           if (strlen($shift) < 3*8)
  763.             echo " ";
  764.         }
  765.  
  766.         echo "  |";
  767.         for ($j = 0; $j < strlen($cache); $j++)
  768.         {
  769.           $chr = $cache{$j};
  770.           if (ord($chr) < ord("\x20") || ord($chr) > ord("\x7E"))
  771.             $chr = ".";
  772.           echo htmlentities($chr);
  773.         }
  774.         echo "|";
  775.         echo "\n";
  776.  
  777.         $cache = "";
  778.       }
  779.     }
  780.  
  781.     return TRUE;
  782.   }
  783.   // }}}
  784.  
  785.  
  786.   // {{{ _AutoDetectMain() - main methode of the autodetect routine
  787.   // @return array  decoded data received from gameserver
  788.   //         bool   FALSE if an error occur
  789.   // @access protected
  790.   function _AutoDetectMain()
  791.   {
  792.     $protocol = "";
  793.     $subproto = "";
  794.     $data     = array();
  795.  
  796.     // first some checks
  797.     if (empty($this->_protocols))
  798.     {
  799.       $this->_SoftError("No autodetect protocols set");
  800.       return FALSE;
  801.     }
  802.     foreach ($this->_protocols as $protocol)
  803.     {
  804.       if (!is_callable(array(&$this, "_".$protocol."Main")))
  805.       {
  806.         $this->_SoftError("\"".$protocol."\" protocol not available");
  807.         return FALSE;
  808.       }
  809.       if (!is_callable(array(&$this, "_".$protocol."AutoDetect")))
  810.       {
  811.         $this->_SoftError("No Autodetection method available for Protocol: \"".$protocol."\"");
  812.         return FALSE;
  813.       }
  814.       foreach ($this->_gettypes as $subproto)
  815.       {
  816.         if (!is_callable(array(&$this, "_".$protocol.$subproto)))
  817.         {
  818.           $this->_SoftError("SetRequestData() Type: \"".$subproto."\" now known in Protocol: \"".$protocol."\"");
  819.           return FALSE;
  820.         }
  821.       }
  822.     }
  823.     if ($this->_queryport != 0)
  824.     {
  825.       $this->_SoftError("Never set a queryport if you use autodetection");
  826.       return FALSE;
  827.     }
  828.  
  829.     trigger_error("<b>Starting AutoDetection</b>");
  830.     foreach ($this->_protocols as $type)
  831.     {
  832.       call_user_func(array(&$this, "_".$type."AutoDetect"));
  833.       $autodetect = new GSQuery();
  834.       $autodetect->SetProtocol($type);
  835.       $autodetect->SetIpPort($this->_ip.":".$this->_port.":".$this->_queryport);
  836.       $autodetect->SetRequestData($this->_gettypes);
  837.       $autodetect->SetSocketTimeOut($this->_stimeout, $this->_mstimeout);
  838.       $autodetect->SetSocketLoopTimeOut($this->_looptimeout);
  839.       $data = $autodetect->GetData();
  840.       $this->ERROR  = $autodetect->ERROR;
  841.       $this->ERRSTR = $autodetect->ERRSTR;
  842.       if ($autodetect->ERROR == FALSE)
  843.         break;
  844.     }
  845.  
  846.     return $data;
  847.   }
  848.   // }}}
  849.  
  850.   // {{{ Query Protocol definitions
  851.   // {{{ Query Protocol: HalfLife
  852.   // {{{ _HalfLifeMain() - Query Protocol: HalfLife - Type: Main Methode
  853.   // @return array  decoded data received from gameserver
  854.   //         bool   FALSE if an error occur
  855.   // @access protected
  856.   function _HalfLifeMain()
  857.   {
  858.     $challenge = "\xFF\xFF\xFF\xFF";
  859.     $data = array();
  860.     $this->_CreateUDPSocket();
  861.  
  862.     if (!$this->_localquery)
  863.       $challenge = call_user_func(array(&$this, "_".$this->_protocol."Challenge"));
  864.  
  865.     foreach ($this->_gettypes as $type)
  866.     {
  867.       $data[$type] = call_user_func(array(&$this, "_".$this->_protocol.$type), $challenge);
  868.       if ($this->ERROR)
  869.         return FALSE;
  870.      }
  871.     $this->_CloseUDPSocket();
  872.  
  873.     return $data;
  874.   }
  875.   /// }}}
  876.  
  877.   // {{{ Query Protocol definitions
  878.   // {{{ Query Protocol: HalfLife
  879.   // {{{ _HalfLifeRecv() - Query Protocol: HalfLife - Type: Recv
  880.   // @access protected
  881.   function _HalfLifeRecv($query)
  882.   {
  883.     $this->_SendSocket($query);
  884.  
  885.     $recv       = "";
  886.     $packets    = array();
  887.     $packetcnt  = 1;
  888.     $compressed = false;
  889.     for ($i = 0; $i < $packetcnt; $i++)
  890.     {
  891.       $recv = implode("", $this->_GetSocketDataNr(1));
  892.       # split packet
  893.      if (substr($recv, 0, 4) == "\xFE\xFF\xFF\xFF")
  894.       {
  895.         $recv = substr($recv, 4);
  896.         $requestid = $this->_GetLongAsLong($recv); # maybe check too?
  897.        $compressed = (($requestid & (int)(1 << 31)) == (int)(1 << 31)) ? true : false;
  898.         if (isset($this->_globalvars["ProtocolVersion"]) && $this->_globalvars["ProtocolVersion"] == 48)
  899.         {
  900.           $tmp = $this->_GetByteAsAscii($recv);
  901.           $packetcnt = $tmp & 0xF;
  902.           $packetnum = ($tmp >> 4) & 0xF;
  903.         }
  904.         else
  905.         {
  906.           $packetcnt = $this->_GetByteAsAscii($recv);
  907.           $packetnum = $this->_GetByteAsAscii($recv);
  908.         }
  909.         # only in tf2 and newer source engines. should be harcoded?!
  910.        if (substr($recv, 0, 2) == "\xE0\x04")
  911.           $this->_GetInt16AsInt($recv);
  912.         if ($compressed)
  913.         {
  914.           $realsize = $this->_GetInt32AsInt($recv);
  915.           $realcrc32 = $this->_GetInt32AsInt($recv);
  916.         }
  917.         $packets[$packetnum] = $recv;
  918.       }
  919.       # single packet
  920.      elseif (substr($recv, 0, 4) == "\xFF\xFF\xFF\xFF")
  921.       {
  922.         $packets[0] = $recv;
  923.       }
  924.       # unknown
  925.      else
  926.       {
  927.         $this->_SoftError("Unknown header in half-life packet");
  928.         return FALSE;
  929.       }
  930.     }
  931.  
  932.     $recv = implode("", $packets);
  933.     if ($compressed)
  934.       $recv = bzdecompress($recv);
  935.  
  936.     return $recv;
  937.   }
  938.   /// }}}
  939.  
  940.  
  941.   // {{{ _HalfLifeDetails() - Query Protocol: HalfLife - Type: Server Details
  942.   // @return array  decoded data received from gameserver
  943.   //         bool   FALSE if an error occur
  944.   // @access protected
  945.   function _HalfLifeDetails()
  946.   {
  947.     $recv   = "";
  948.     $prefix = "";
  949.     $data   = array();
  950.     $tmp    = array();
  951.  
  952.     $this->_SendSocket("\xFF\xFF\xFF\xFFTSource Engine Query\x00");
  953.     $recv = implode("", $this->_GetSocketDataNr(1));
  954.  
  955.     if (!$this->_CheckQueryHeader($recv, "\xFF\xFF\xFF\xFF", $prefix))
  956.       return FALSE;
  957.  
  958.     # Half-Life reply
  959.    if ($recv{0} == "m")
  960.     {
  961.       $recv = substr($recv, 1);
  962.       $tmp = explode(":", $this->_GetCharacterTerminatedString($recv, "\x00"));
  963.       $data["Ip"]              = $tmp[0];
  964.       $data["Port"]            = $tmp[1];
  965.       $data["Hostname"]        = $this->_GetCharacterTerminatedString($recv, "\x00");
  966.       $data["Map"]             = $this->_GetCharacterTerminatedString($recv, "\x00");
  967.       $data["GameDir"]         = $this->_GetCharacterTerminatedString($recv, "\x00");
  968.       $data["GameDesc"]        = $this->_GetCharacterTerminatedString($recv, "\x00");
  969.       $data["PlayerCount"]     = $this->_GetByteAsAscii($recv);
  970.       $data["MaxPlayers"]      = $this->_GetByteAsAscii($recv);
  971.       $data["ProtocolVersion"] = $this->_GetByteAsAscii($recv);
  972.       $data["ServerType"]      = $this->_GetByteAsChr($recv);
  973.       $data["ServerOS"]        = $this->_GetByteAsChr($recv);
  974.       $data["Password"]        = $this->_GetByteAsAscii($recv);
  975.       $data["Modded"]          = $this->_GetByteAsAscii($recv);
  976.       if ($data["Modded"])
  977.       {
  978.         $data["ModWebsite"]        = $this->_GetCharacterTerminatedString($recv, "\x00");
  979.         $data["ModDownloadServer"] = $this->_GetCharacterTerminatedString($recv, "\x00");
  980.         $this->_GetCharacterTerminatedString($recv, "\x00");
  981.         $data["ModVersion"]        = $this->_GetInt32AsInt($recv);
  982.         $data["ModSize"]           = $this->_GetInt32AsInt($recv);
  983.         $data["ModServerSideOnly"] = $this->_GetByteAsAscii($recv);
  984.         $data["ModCustomDLL"]      = $this->_GetByteAsAscii($recv);
  985.       }
  986.       $data["Secure"] = $this->_GetByteAsAscii($recv);
  987.     }
  988.     # Half-Life Source reply
  989.    elseif ($recv{0} == "I")
  990.     {
  991.       $recv = substr($recv, 1);
  992.       $data["ProtocolVersion"] = $this->_GetByteAsAscii($recv);
  993.       $this->_globalvars["ProtocolVersion"] = $data["ProtocolVersion"];
  994.       $data["Hostname"]        = $this->_GetCharacterTerminatedString($recv, "\x00");
  995.       $data["Map"]             = $this->_GetCharacterTerminatedString($recv, "\x00");
  996.       $data["GameDir"]         = $this->_GetCharacterTerminatedString($recv, "\x00");
  997.       $data["GameDesc"]        = $this->_GetCharacterTerminatedString($recv, "\x00");
  998.       $data["SteamAppID"]      = $this->_GetInt16AsInt($recv);
  999.       $data["PlayerCount"]     = $this->_GetByteAsAscii($recv);
  1000.       $data["MaxPlayers"]      = $this->_GetByteAsAscii($recv);
  1001.       $data["BotCount"]        = $this->_GetByteAsAscii($recv);
  1002.       $data["ServerType"]      = $this->_GetByteAsChr($recv);
  1003.       $data["ServerOS"]        = $this->_GetByteAsChr($recv);
  1004.       $data["Password"]        = $this->_GetByteAsAscii($recv);
  1005.       $data["Secure"]          = $this->_GetByteAsAscii($recv);
  1006.     }
  1007.     else
  1008.       $this->_SoftError("Unknown reply from HalfLife");
  1009.  
  1010.     return $data;
  1011.   }
  1012.   // }}}
  1013.  
  1014.   // {{{ _HalfLifeChallenge() - Query Protocol: HalfLife - get challenge string for quering
  1015.   // @return string  challenge string
  1016.   // @access protected
  1017.   function _HalfLifeChallenge()
  1018.   {
  1019.     $recv   = "";
  1020.     $prefix = "";
  1021.     $challenge = "";
  1022.  
  1023.     // there's a bug in new hlds protocol which fucks up the challenge query.
  1024.     // so fallback to A2S_PLAYER with -1 as challenge id */
  1025.     //$this->_SendSocket("\xFF\xFF\xFF\xFFW");
  1026.     $this->_SendSocket("\xFF\xFF\xFF\xFFV\xFF\xFF\xFF\xFF");
  1027.     $recv = implode("", $this->_GetSocketDataNr(1));
  1028.  
  1029.     if (!$this->_CheckQueryHeader($recv, "\xFF\xFF\xFF\xFFA", $prefix))
  1030.       return FALSE;
  1031.  
  1032.     $challenge = substr($recv, 0, 4);
  1033.  
  1034.     return $challenge;
  1035.   }
  1036.   // }}}
  1037.  
  1038.   // {{{ _HalfLifeRules() - Query Protocol: HalfLife - Type: Server Rules
  1039.   // @param  string challenge string
  1040.   // @return array  decoded data received from gameserver
  1041.   //         bool   FALSE if an error occur
  1042.   // @access protected
  1043.   function _HalfLifeRules($challenge)
  1044.   {
  1045.     $prefix = "";
  1046.     $recv = $this->_HalfLifeRecv("\xFF\xFF\xFF\xFFV".$challenge);
  1047.  
  1048.     if (!$this->_CheckQueryHeader($recv, "\xFF\xFF\xFF\xFFE", $prefix))
  1049.       return FALSE;
  1050.  
  1051.     $data["RuleCount"] = $this->_GetInt16AsInt($recv);
  1052.     for ($i = 0; $i < $data["RuleCount"]; $i++)
  1053.       $data[$this->_GetCharacterTerminatedString($recv, "\x00")] = $this->_GetCharacterTerminatedString($recv, "\x00");
  1054.  
  1055.     return $data;
  1056.   }
  1057.   // }}}
  1058.  
  1059.   // {{{ _HalfLifePlayers() - Query Protocol: HalfLife - Type: Players
  1060.   // @param  string challenge string
  1061.   // @return array  decoded data received from gameserver
  1062.   //         bool   FALSE if an error occur
  1063.   // @access protected
  1064.   function _HalfLifePlayers($challenge)
  1065.   {
  1066.     $prefix = "";
  1067.     $recv = $this->_HalfLifeRecv("\xFF\xFF\xFF\xFFU".$challenge);
  1068.  
  1069.     if (!$this->_CheckQueryHeader($recv, "\xFF\xFF\xFF\xFFD", $prefix))
  1070.       return FALSE;
  1071.  
  1072.     $data["PlayerCount"] = $this->_GetByteAsAscii($recv);
  1073.     $data["Players"] = array();
  1074.     for ($i = 0; $i < $data["PlayerCount"]; $i++)
  1075.     {
  1076.       $player = array();
  1077.       $player["Number"] = $this->_GetByteAsAscii($recv);
  1078.       $player["Name"]   = $this->_GetCharacterTerminatedString($recv, "\x00");
  1079.       $player["Score"]  = $this->_GetInt32AsInt($recv);
  1080.       $player["Time"]   = round($this->_GetFloat32AsFloat($recv), 0) + 82800;
  1081.       if ($player["Name"] == "" && $player["Score"] == 0 && $player["Time"] == 82800)
  1082.         $player["Number"] = $player["Time"] = 0;
  1083.       array_push($data["Players"], $player);
  1084.     }
  1085.  
  1086.     return $data;
  1087.   }
  1088.   // }}}
  1089.  
  1090.   // {{{ _HalfLifeAutoDetect() - Query Protocol: HalfLife - Type: AutoDetect Methode
  1091.   // @return bool  always TRUE
  1092.   // @access protected
  1093.   function _HalfLifeAutoDetect()
  1094.   {
  1095.     $this->_queryport = $this->_port;
  1096.     return TRUE;
  1097.   }
  1098.   // }}}
  1099.  
  1100.   // {{{ _HalfLifeFullInfo() - Query Protocol: HalfLife - Type: Request Full Server Info
  1101.   // @return array  decoded data received from gameserver
  1102.   // @access protected
  1103.   function _HalfLifeFullInfo()
  1104.   {
  1105.     $this->SetRequestData(array("Details", "Rules", "Players"));
  1106.     return $this->_HalfLifeMain();
  1107.   }
  1108.   // }}}
  1109.   // }}}
  1110.  
  1111.   // {{{ Query Protocol: AllSeeingEye
  1112.   // {{{ _AllSeeingEyeMain() - Query Protocol: AllSeeingEye - Type: Main Methode
  1113.   // @return array  decoded data received from gameserver
  1114.   //         bool   FALSE if an error occur
  1115.   // @access protected
  1116.   function _AllSeeingEyeMain()
  1117.   {
  1118.     $recv   = "";
  1119.     $prefix = "";
  1120.     $tmp    = array();
  1121.     $data   = array();
  1122.  
  1123.     $this->_CreateUDPSocket();
  1124.     $this->_SendSocket("s");
  1125.     $recv = implode("", $this->_GetSocketDataNr(1));
  1126.  
  1127.     if (!$this->_CheckQueryHeader($recv, "EYE1", $prefix))
  1128.       return FALSE;
  1129.  
  1130.     $tmp["Details"] = $this->_AllSeeingEyeDetails($recv);
  1131.     $tmp["Players"] = $this->_AllSeeingEyePlayers($recv);
  1132.     if ($this->ERROR)
  1133.       return FALSE;
  1134.     $this->_CloseUDPSocket();
  1135.  
  1136.  
  1137.     foreach ($this->_gettypes as $type)
  1138.       $data[$type] = $tmp[$type];
  1139.  
  1140.     return $data;
  1141.   }
  1142.   // }}}
  1143.  
  1144.   // {{{ _AllSeeingEyeDetails() - Query Protocol: AllSeeingEye - Type: Server Details
  1145.   // @return array  decoded data received from gameserver
  1146.   // @access protected
  1147.   function _AllSeeingEyeDetails(&$recv)
  1148.   {
  1149.     $tmp  = "";
  1150.     $data = array();
  1151.  
  1152.     $data["GameName"]    = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1153.     $data["Port"]        = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1154.     $data["HostName"]    = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1155.     $data["GameTyp"]     = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1156.     $data["Map"]         = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1157.     $data["Version"]     = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1158.     $data["Password"]    = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1159.     $data["PlayerCount"] = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1160.     $data["MaxPlayers"]  = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1161.  
  1162.     while (($tmp = $this->_GetByteAsAscii($recv)) != "1")
  1163.       $data[$this->_GetStringByLength($recv, $tmp - 1)] = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1164.  
  1165.     return $data;
  1166.   }
  1167.   // }}}
  1168.  
  1169.   // {{{ _AllSeeingEyePlayers() - Query Protocol: AllSeeingEye - Type: Players
  1170.   // @return array  decoded data received from gameserver
  1171.   // @access protected
  1172.   function _AllSeeingEyePlayers(&$recv)
  1173.   {
  1174.     $tmp     = "";
  1175.     $counter = 0;
  1176.     $players = array();
  1177.  
  1178.     if (strlen($recv) == 0)
  1179.       return $players;
  1180.  
  1181.     while(strlen($recv) > 0)
  1182.     {
  1183.       $tmp = $this->_GetByteAsAscii($recv);
  1184.       if ($tmp & 1)
  1185.         $players[$counter]["Name"]  = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1186.       if ($tmp & 2)
  1187.         $players[$counter]["Team"]  = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1188.       if ($tmp & 4)
  1189.         $players[$counter]["Skin"]  = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1190.       if ($tmp & 8)
  1191.         $players[$counter]["Score"] = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1192.       if ($tmp & 16)
  1193.         $players[$counter]["Ping"]  = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1194.       if ($tmp & 32)
  1195.         $players[$counter]["Time"]  = $this->_GetStringByLength($recv, $this->_GetByteAsAscii($recv) - 1);
  1196.       $counter++;
  1197.     }
  1198.  
  1199.     return $players;
  1200.   }
  1201.   // }}}
  1202.  
  1203.   // {{{ _AllSeeingEyeAutoDetect() - Query Protocol: AllSeeingEye - Type: AutoDetect Methode
  1204.   // @return bool  always TRUE
  1205.   // @access protected
  1206.   function _AllSeeingEyeAutoDetect()
  1207.   {
  1208.     $this->_queryport = $this->_port + 123;
  1209.     return TRUE;
  1210.   }
  1211.   // }}}
  1212.  
  1213.   // {{{ _AllSeeingEyeFullInfo() - Query Protocol: AllSeeingEye - Type: Request Full Server Info
  1214.   // @return array  decoded data received from gameserver
  1215.   // @access protected
  1216.   function _AllSeeingEyeFullInfo()
  1217.   {
  1218.     $this->SetRequestData(array("Details", "Players"));
  1219.     return $this->_AllSeeingEyeMain();
  1220.   }
  1221.   // }}}
  1222.   // }}}
  1223.  
  1224.   // {{{ Query Protocol: Quake1
  1225.   // {{{ _Quake1Main() - Query Protocol: Quake1 - Type: Main Methode
  1226.   // @return array  decoded data received from gameserver
  1227.   //         bool   FALSE if an error occur
  1228.   // @access protected
  1229.   function _Quake1Main()
  1230.   {
  1231.     $recv   = "";
  1232.     $prefix = "";
  1233.     $tmp    = array();
  1234.     $data   = array();
  1235.  
  1236.     $this->_CreateUDPSocket();
  1237.     $this->_SendSocket("\xFF\xFF\xFF\xFFstatus");
  1238.     $recv = implode("", $this->_GetSocketDataNr(1));
  1239.  
  1240.     if (!$this->_CheckQueryHeader($recv, "\xFF\xFF\xFF\xFFn\\", $prefix))
  1241.       return FALSE;
  1242.  
  1243.     $tmp["Details"] = substr($recv, 0, strpos($recv, "\n"))."\\";
  1244.     $tmp["Players"] = substr($recv, strpos($recv,"\n") + 1);
  1245.     $tmp["Players"] = substr($tmp["Players"], 0, strlen($tmp["Players"]) - 1);
  1246.  
  1247.     foreach ($this->_gettypes as $type)
  1248.     {
  1249.       $data[$type] = call_user_func(array(&$this, "_".$this->_protocol.$type), $tmp[$type]);
  1250.       if ($this->ERROR)
  1251.         return FALSE;
  1252.     }
  1253.     $this->_CloseUDPSocket();
  1254.  
  1255.     return $data;
  1256.   }
  1257.   // }}}
  1258.  
  1259.   // {{{ _Quake1Details() - Query Protocol: Quake1 - Type: Server Details
  1260.   // @return array  decoded data received from gameserver
  1261.   // @access protected
  1262.   function _Quake1Details($recv)
  1263.   {
  1264.     $data = array();
  1265.     $data = $this->_GetDelimitedVariables($recv, "\\");
  1266.     return $data;
  1267.   }
  1268.   // }}}
  1269.  
  1270.   // {{{ _Quake1Players() - Query Protocol: Quake1 - Type: Players
  1271.   // @return array  decoded data received from gameserver
  1272.   // @access protected
  1273.   function _Quake1Players($recv)
  1274.   {
  1275.     $counter = 0;
  1276.     $data    = array();
  1277.     $player  = array();
  1278.     $players = array();
  1279.  
  1280.     if (strlen($recv) == 0)
  1281.       return $players;
  1282.  
  1283.     $data = explode("\n", $recv);
  1284.     foreach ($data as $line)
  1285.     {
  1286.       if (strlen($line) == 0)
  1287.         continue;
  1288.       if (preg_match("/^([-0-9]+) ([-0-9]+) ([-0-9]+) ([-0-9]+) \"(.*)\" \"(.*)\" ([-0-9]+) ([-0-9]+)$/i", $line, $player))
  1289.       {
  1290.         $players[$counter]["Number"] = $player[1];
  1291.         $players[$counter]["Score"]  = $player[2];
  1292.         $players[$counter]["Time"]   = $player[3];
  1293.         $players[$counter]["Ping"]   = $player[4];
  1294.         $players[$counter]["Name"]   = $player[5];
  1295.         $players[$counter]["Skin"]   = $player[6];
  1296.         $players[$counter]["Score1"] = $player[7];
  1297.         $players[$counter]["Score2"] = $player[8];
  1298.         $counter++;
  1299.       }
  1300.       else
  1301.         $this->_SoftError("Unknown players data format received in Protocol: \"".$this->_protocol."\"");
  1302.     }
  1303.     return $players;
  1304.   }
  1305.   // }}}
  1306.  
  1307.   // {{{ _Quake1AutoDetect() - Query Protocol: Quake1 - Type: AutoDetect Methode
  1308.   // @return bool  always TRUE
  1309.   // @access protected
  1310.   function _Quake1AutoDetect()
  1311.   {
  1312.     $this->_queryport = $this->_port;
  1313.     return TRUE;
  1314.   }
  1315.   // }}}
  1316.  
  1317.   // {{{ _Quake1FullInfo() - Query Protocol: Quake1 - Type: Request Full Server Info
  1318.   // @return array  decoded data received from gameserver
  1319.   function _Quake1FullInfo()
  1320.   {
  1321.     $this->SetRequestData(array("Details", "Players"));
  1322.     return $this->_Quake1Main();
  1323.   }
  1324.   // }}}
  1325.   // }}}
  1326.  
  1327.   // {{{ Query Protocol: Quake2
  1328.   // {{{ _Quake2Main() - Query Protocol: Quake2 - Type: Main Methode
  1329.   // @return array  decoded data received from gameserver
  1330.   //         bool   FALSE if an error occur
  1331.   // @access protected
  1332.   function _Quake2Main()
  1333.   {
  1334.     $recv   = "";
  1335.     $prefix = "";
  1336.     $tmp    = array();
  1337.     $data   = array();
  1338.  
  1339.     $this->_CreateUDPSocket();
  1340.     $this->_SendSocket("\xFF\xFF\xFF\xFFstatus");
  1341.     $recv = implode("", $this->_GetSocketDataNr(1));
  1342.  
  1343.     if (!$this->_CheckQueryHeader($recv, "\xFF\xFF\xFF\xFFprint\x0A", $prefix))
  1344.       return FALSE;
  1345.  
  1346.     $tmp["Details"] = substr($recv, 0, strpos($recv, "\n"))."\\";
  1347.     $tmp["Players"] = substr($recv, strpos($recv,"\n") + 1);
  1348.     $tmp["Players"] = substr($tmp["Players"], 0, strlen($tmp["Players"]) - 1);
  1349.  
  1350.     foreach ($this->_gettypes as $type)
  1351.     {
  1352.       $data[$type] = call_user_func(array(&$this, "_".$this->_protocol.$type), $tmp[$type]);
  1353.       if ($this->ERROR)
  1354.         return FALSE;
  1355.     }
  1356.     $this->_CloseUDPSocket();
  1357.  
  1358.     return $data;
  1359.   }
  1360.   // }}}
  1361.  
  1362.   // {{{ _Quake2Details() - Query Protocol: Quake2 - Type: Server Details
  1363.   // @return array  decoded data received from gameserver
  1364.   // @access protected
  1365.   function _Quake2Details($recv)
  1366.   {
  1367.     $data = array();
  1368.     $data = $this->_GetDelimitedVariables($recv, "\\");
  1369.     return $data;
  1370.   }
  1371.   // }}}
  1372.  
  1373.   // {{{ _Quake2Players() - Query Protocol: Quake2 - Type: Players
  1374.   // @return array  decoded data received from gameserver
  1375.   // @access protected
  1376.   function _Quake2Players($recv)
  1377.   {
  1378.     $counter = 0;
  1379.     $data    = array();
  1380.     $player  = array();
  1381.     $players = array();
  1382.  
  1383.     if (strlen($recv) == 0)
  1384.       return $players;
  1385.  
  1386.     $data = explode("\n", $recv);
  1387.     foreach ($data as $line)
  1388.     {
  1389.       if (strlen($line) == 0)
  1390.         continue;
  1391.       if (preg_match("/^([-0-9]+) ([-0-9]+) \"(.*)\"$/i", $line, $player))
  1392.       {
  1393.         $players[$counter]["Score"]  = $player[1];
  1394.         $players[$counter]["Ping"]   = $player[2];
  1395.         $players[$counter]["Name"]   = $player[3];
  1396.         $counter++;
  1397.       }
  1398.       else
  1399.         $this->_SoftError("Unknown players data format received in Protocol: \"".$this->_protocol."\"");
  1400.     }
  1401.     return $players;
  1402.   }
  1403.   // }}}
  1404.  
  1405.   // {{{ _Quake2AutoDetect() - Query Protocol: Quake2 - Type: AutoDetect Methode
  1406.   // @return bool  always TRUE
  1407.   // @access protected
  1408.   function _Quake2AutoDetect()
  1409.   {
  1410.     $this->_queryport = $this->_port;
  1411.     return TRUE;
  1412.   }
  1413.   // }}}
  1414.  
  1415.   // {{{ _Quake2FullInfo() - Query Protocol: Quake2 - Type: Request Full Server Info
  1416.   // @return array  decoded data received from gameserver
  1417.   function _Quake2FullInfo()
  1418.   {
  1419.     $this->SetRequestData(array("Details", "Players"));
  1420.     return $this->_Quake2Main();
  1421.   }
  1422.   // }}}
  1423.   // }}}
  1424.  
  1425.   // {{{ Query Protocol: Quake3
  1426.   // {{{ _Quake3Main() - Query Protocol: Quake3 - Type: Main Methode
  1427.   // @return array  decoded data received from gameserver
  1428.   //         bool   FALSE if an error occur
  1429.   // @access protected
  1430.   function _Quake3Main()
  1431.   {
  1432.     $recv   = "";
  1433.     $prefix = "";
  1434.     $tmp    = array();
  1435.     $data   = array();
  1436.  
  1437.     $this->_CreateUDPSocket();
  1438.     $this->_SendSocket("\xFF\xFF\xFF\xFFgetstatus\x0A");
  1439.     $recv = implode("", $this->_GetSocketDataNr(1));
  1440.  
  1441.     if (!$this->_CheckQueryHeader($recv, "\xFF\xFF\xFF\xFFstatusResponse\x0A\\", $prefix))
  1442.       return FALSE;
  1443.  
  1444.     $tmp["Details"] = substr($recv, 0, strpos($recv, "\n"))."\\";
  1445.     $tmp["Players"] = substr($recv, strpos($recv,"\n") + 1);
  1446.     $tmp["Players"] = substr($tmp["Players"], 0, strlen($tmp["Players"]) - 1);
  1447.  
  1448.     foreach ($this->_gettypes as $type)
  1449.     {
  1450.       $data[$type] = call_user_func(array(&$this, "_".$this->_protocol.$type), $tmp[$type]);
  1451.       if ($this->ERROR)
  1452.         return FALSE;
  1453.     }
  1454.     $this->_CloseUDPSocket();
  1455.  
  1456.     return $data;
  1457.   }
  1458.   // }}}
  1459.  
  1460.   // {{{ _Quake3Details() - Query Protocol: Quake3 - Type: Server Details
  1461.   // @return array  decoded data received from gameserver
  1462.   // @access protected
  1463.   function _Quake3Details($recv)
  1464.   {
  1465.     $data = array();
  1466.     $data = $this->_GetDelimitedVariables($recv, "\\");
  1467.     return $data;
  1468.   }
  1469.   // }}}
  1470.  
  1471.   // {{{ _Quake3Players() - Query Protocol: Quake3 - Type: Players
  1472.   // @return array  decoded data received from gameserver
  1473.   // @access protected
  1474.   function _Quake3Players($recv)
  1475.   {
  1476.     $data    = array();
  1477.     $player  = array();
  1478.     $players = array();
  1479.  
  1480.     if (strlen($recv) == 0)
  1481.       return $players;
  1482.  
  1483.     $data = explode("\n", $recv);
  1484.     foreach ($data as $line)
  1485.     {
  1486.       if (strlen($line) == 0)
  1487.         continue;
  1488.  
  1489.       if (preg_match("/^([-0-9]+) ([-0-9]+) \"(.*)\"$/i", $line, $player))
  1490.         array_push($players, array("frags" => $player[1], "ping" => $player[2], "name" => $player[3]));
  1491.       elseif (preg_match("/^([-0-9]+) ([-0-9]+) ([-0-9]+) \"(.*)\"$/i", $line, $player))
  1492.         array_push($players, array("frags" => $player[1], "ping" => $player[2], "deaths" => $player[3], "name" => $player[4]));
  1493.       else
  1494.         $this->_SoftError("Unknown players data format received in Protocol: \"".$this->_protocol."\"");
  1495.     }
  1496.     return $players;
  1497.   }
  1498.   // }}}
  1499.  
  1500.   // {{{ _Quake3AutoDetect() - Query Protocol: Quake3 - Type: AutoDetect Methode
  1501.   // @return bool  always TRUE
  1502.   // @access protected
  1503.   function _Quake3AutoDetect()
  1504.   {
  1505.     $this->_queryport = $this->_port;
  1506.     return TRUE;
  1507.   }
  1508.   // }}}
  1509.  
  1510.   // {{{ _Quake3FullInfo() - Query Protocol: Quake3 - Type: Request Full Server Info
  1511.   // @return array  decoded data received from gameserver
  1512.   // @access protected
  1513.   function _Quake3FullInfo()
  1514.   {
  1515.     $this->SetRequestData(array("Details", "Players"));
  1516.     return $this->_Quake3Main();
  1517.   }
  1518.   // }}}
  1519.   // }}}
  1520.  
  1521.   // {{{ Query Protocol: Doom3
  1522.   // {{{ _Doom3Main() - Query Protocol: Doom3 - Type: Main Methode
  1523.   // @return array  decoded data received from gameserver
  1524.   //         bool   FALSE if an error occur
  1525.   // @access protected
  1526.   function _Doom3Main($protocol = 1)
  1527.   {
  1528.     $recv   = "";
  1529.     $prefix = "";
  1530.     $tmp    = array();
  1531.     $data   = array();
  1532.  
  1533.     $this->_CreateUDPSocket();
  1534.     $this->_SendSocket("\xFF\xFFgetInfo\x00\x00\x00\x00\x00");
  1535.     $recv = implode("", $this->_GetSocketDataNr(5));
  1536.  
  1537.     if (!$this->_CheckQueryHeader($recv, "\xFF\xFFinfoResponse\x00", $prefix))
  1538.       return FALSE;
  1539.  
  1540.     /* dirty hack to determine protocol version */
  1541.     if ($tmp2 = strstr($recv, "si_version\x00"))
  1542.     {
  1543.       /* strip off si_version */
  1544.       $this->_GetCharacterTerminatedString($tmp2, "\x00");
  1545.       $version = $this->_GetCharacterTerminatedString($tmp2, "\x00");
  1546.       if (strpos(strtolower($version), "doom") !== false)
  1547.         $protocol = 1;
  1548.       elseif (strpos(strtolower($version), "pray") !== false)
  1549.         $protocol = 2;
  1550.       elseif (strpos(strtolower($version), "quake4") !== false)
  1551.         $protocol = 3;
  1552.       elseif (strpos(strtolower($version), "etqw") !== false)
  1553.         $protocol = 4;
  1554.     }
  1555.  
  1556.     if ($protocol == 4) /* ETQW */
  1557.       $taskid = $this->_GetLongAsLong($recv);
  1558.     $challenge = $this->_GetLongAsLong($recv);
  1559.     $this->_protoversion = $this->_GetLongAsLong($recv);
  1560.     $this->_protoversion = sprintf("%u.%u", $this->_protoversion >> 16, $this->_protoversion & 0xFFFF);
  1561.     if ($protocol == 4) /* ETQW */
  1562.       $this->_infosize = $this->_GetLongAsLong($recv);
  1563.  
  1564.     $tmp["Details"] = $this->_Doom3Details($recv, $protocol);
  1565.     if (!isset($tmp["Details"]["queryprotocol"]))
  1566.       $tmp["Details"]["queryprotocol"] = $this->_protoversion;
  1567.  
  1568.     $tmp["Players"] = $this->_Doom3Players($recv, $protocol);
  1569.  
  1570.     $tmp["Details"]["osmask"] = $this->_GetLongAsLong($recv);
  1571.     if ($protocol == 4) /* ETQW */
  1572.     {
  1573.       $tmp["Details"]["ranked"]     = $this->_GetByteAsAscii($recv);
  1574.       $tmp["Details"]["timeleft"]   = $this->_GetInt32AsInt($recv);
  1575.       $tmp["Details"]["gamestate"]  = $this->_GetByteAsAscii($recv);
  1576.       $tmp["Details"]["servertype"] = $this->_GetByteAsAscii($recv);
  1577.       if ($tmp["Details"]["servertype"] == 0) /* regular server */
  1578.         $tmp["Details"]["interested_clients"] = $this->_GetByteAsAscii($recv);
  1579.       elseif ($tmp["Details"]["servertype"] == 0) /* tv server */
  1580.       {
  1581.         $tmp["Details"]["tv_numClients"] = $this->_GetByteAsAscii($recv);
  1582.         $tmp["Details"]["tv_maxClients"] = $this->_GetByteAsAscii($recv);
  1583.       }
  1584.     }
  1585.     if ($this->ERROR)
  1586.       return FALSE;
  1587.     $this->_CloseUDPSocket();
  1588.  
  1589.     foreach ($this->_gettypes as $type)
  1590.       $data[$type] = $tmp[$type];
  1591.  
  1592.     return $data;
  1593.   }
  1594.   // }}}
  1595.  
  1596.   // {{{ _Doom3Details() - Query Protocol: Doom3 - Type: Server Details
  1597.   // @return array  decoded data received from gameserver
  1598.   // @access protected
  1599.   function _Doom3Details(&$recv, $protocol = 1)
  1600.   {
  1601.     $key  = "";
  1602.     $data = array();
  1603.  
  1604.     while (($key = $this->_GetCharacterTerminatedString($recv, "\x00")) !== FALSE)
  1605.     {
  1606.       $value = $this->_GetCharacterTerminatedString($recv, "\x00");
  1607.       if ($key == "" && $value == "")
  1608.           break;
  1609.       $data[$key] = $value;
  1610.     }
  1611.  
  1612.     if ($protocol == 4) /* ETQW */
  1613.     {
  1614.       if (isset($data["si_map"]) && strpos($data["si_map"], ".entities") !== FALSE)
  1615.         $data["si_map"] = substr($data["si_map"], 0, -9);
  1616.     }
  1617.  
  1618.     return $data;
  1619.   }
  1620.   // }}}
  1621.  
  1622.   // {{{ _Doom3Players() - Query Protocol: Doom3 - Type: Players
  1623.   // @return array  decoded data received from gameserver
  1624.   // @access protected
  1625.   function _Doom3Players(&$recv, $protocol = 1)
  1626.   {
  1627.     $tmp     = "";
  1628.     $players = array();
  1629.  
  1630.     if (strlen($recv) == 0)
  1631.       return $players;
  1632.  
  1633.     while (($number = $this->_GetByteAsAscii($recv)) != 32)
  1634.     {
  1635.       $players[$number]["Ping"] = $this->_GetByteAsAscii($recv) + $this->_GetByteAsAscii($recv) * 256;
  1636.       if ($protocol != 4) /* ETQW */
  1637.         $players[$number]["Rate"] = $this->_GetLongAsLong($recv);
  1638.       $players[$number]["Name"] = $this->_GetCharacterTerminatedString($recv, "\x00");
  1639.       if ($protocol == 4) /* ETQW */
  1640.       {
  1641.         $players[$number]["ClanTagPos"] = ($this->_GetByteAsAscii($recv) == 1) ? 1 : 0;
  1642.         $players[$number]["ClanTag"] = $this->_GetCharacterTerminatedString($recv, "\x00");
  1643.       }
  1644.  
  1645.       if ($protocol == 3) /* Quake4 */
  1646.         $players[$number]["Clantag"] = $this->_GetCharacterTerminatedString($recv, "\x00");
  1647.       elseif ($protocol == 4) /* ETQW */
  1648.         $players[$number]["Bot"] = ($this->_GetByteAsAscii($recv) == 1) ? 1 : 0;
  1649.     }
  1650.  
  1651.     return $players;
  1652.   }
  1653.   // }}}
  1654.  
  1655.   // {{{ _Doom3AutoDetect() - Query Protocol: Doom3 - Type: AutoDetect Methode
  1656.   // @return bool  always TRUE
  1657.   // @access protected
  1658.   function _Doom3AutoDetect()
  1659.   {
  1660.     $this->_queryport = $this->_port;
  1661.     return TRUE;
  1662.   }
  1663.   // }}}
  1664.  
  1665.   // {{{ _Doom3FullInfo() - Query Protocol: Doom3 - Type: Request Full Server Info
  1666.   // @return array  decoded data received from gameserver
  1667.   // @access protected
  1668.   function _Doom3FullInfo($protocol = 1)
  1669.   {
  1670.     $this->SetRequestData(array("Details", "Players"));
  1671.     return $this->_Doom3Main($protocol);
  1672.   }
  1673.   // }}}
  1674.   // }}}
  1675.  
  1676.   // {{{ Query Protocol: GameSpy
  1677.   // {{{ _GameSpyMain() - Query Protocol: GameSpy - Type: Main Methode
  1678.   // @return array  decoded data received from gameserver
  1679.   //         bool   FALSE if an error occur
  1680.   // @access protected
  1681.   function _GameSpyMain()
  1682.   {
  1683.     $data = array();
  1684.     $this->_CreateUDPSocket();
  1685.     foreach ($this->_gettypes as $type)
  1686.     {
  1687.       $data[$type] = call_user_func(array(&$this, "_".$this->_protocol.$type));
  1688.       if ($this->ERROR)
  1689.         return FALSE;
  1690.     }
  1691.     $this->_CloseUDPSocket();
  1692.  
  1693.     return $data;
  1694.   }
  1695.   // }}}
  1696.  
  1697.   // {{{ _GameSpyDetails() - Query Protocol: GameSpy - Type: Server Details
  1698.   // @return array  decoded data received from gameserver
  1699.   //         bool   FALSE if an error occur
  1700.   // @access protected
  1701.   function _GameSpyDetails()
  1702.   {
  1703.     $recv   = "";
  1704.     $suffix = "";
  1705.     $data   = array();
  1706.  
  1707.     $this->_SendSocket("\\info\\");
  1708.     $recv = implode("", $this->_GetSocketDataNr(1));
  1709.  
  1710.     if (!$this->_CheckQueryFooter($recv, "final\\", $suffix))
  1711.       return FALSE;
  1712.  
  1713.     $data = $this->_GetDelimitedVariables($recv, "\\");
  1714.     return $data;
  1715.   }
  1716.   // }}}
  1717.  
  1718.   // {{{ _GameSpyRules() - Query Protocol: GameSpy - Type: Server Rules
  1719.   // @return array  decoded data received from gameserver
  1720.   //         bool   FALSE if an error occur
  1721.   // @access protected
  1722.   function _GameSpyRules()
  1723.   {
  1724.     $recv   = "";
  1725.     $suffix = "";
  1726.     $data   = array();
  1727.  
  1728.     $this->_SendSocket("\\rules\\");
  1729.     $recv = implode("", $this->_GetSocketDataNr(1));
  1730.  
  1731.     if (!$this->_CheckQueryFooter($recv, "final\\", $suffix))
  1732.       return FALSE;
  1733.  
  1734.     $data = $this->_GetDelimitedVariables($recv, "\\");
  1735.     return $data;
  1736.   }
  1737.   // }}}
  1738.  
  1739.   // {{{ _GameSpyPlayers() - Query Protocol: GameSpy - Type: Players
  1740.   // @return array  decoded data received from gameserver
  1741.   //         bool   FALSE if an error occur
  1742.   // @access protected
  1743.   function _GameSpyPlayers()
  1744.   {
  1745.     $recv    = "";
  1746.     $suffix  = "";
  1747.     $type    = "";
  1748.     $tmp     = "";
  1749.     $counter = 0;
  1750.     $key     = 0;
  1751.     $data    = array();
  1752.  
  1753.     $this->_SendSocket("\\players\\");
  1754.     $recv = implode("", $this->_GetSocketDataNr(1));
  1755.     while ($counter < 4)
  1756.     {
  1757.       if (!$this->_CheckQueryFooter($recv, "final\\", $suffix))
  1758.         $recv .= implode("", $this->_GetSocketDataNr(1));
  1759.       else
  1760.       {
  1761.         $recv .= "final\\";
  1762.         break;
  1763.       }
  1764.       $counter++;
  1765.     }
  1766.     $recv = substr($recv, 1);
  1767.  
  1768.     if (!$this->_CheckQueryFooter($recv, "final\\", $suffix))
  1769.       return FALSE;
  1770.  
  1771.     while(strlen($recv) > 0)
  1772.     {
  1773.       $tmp = $this->_GetCharacterTerminatedString($recv, "\\");
  1774.       if (($counter = strrpos($tmp, "_")) !== FALSE)
  1775.       {
  1776.         $type = substr($tmp, 0, $counter);
  1777.         $key  = intval(substr($tmp, $counter+1));
  1778.         $data[$key][$type] = $this->_GetCharacterTerminatedString($recv, "\\");
  1779.       }
  1780.     }
  1781.  
  1782.     return $data;
  1783.   }
  1784.   // }}}
  1785.  
  1786.   // {{{ _GameSpyAutoDetect() - Query Protocol: GameSpy - Type: AutoDetect Methode
  1787.   // @return bool  always TRUE
  1788.   // @access protected
  1789.   function _GameSpyAutoDetect($arg = 1)
  1790.   {
  1791.     $this->_queryport = $this->_port + 1;
  1792.     return TRUE;
  1793.   }
  1794.   // }}}
  1795.  
  1796.   // {{{ _GameSpyFullInfo() - Query Protocol: GameSpy - Type: Request Full Server Info
  1797.   // @return array  decoded data received from gameserver
  1798.   // @access protected
  1799.   function _GameSpyFullInfo()
  1800.   {
  1801.     $this->SetRequestData(array("Details", "Rules", "Players"));
  1802.     return $this->_GameSpyMain();
  1803.   }
  1804.   // }}}
  1805.  
  1806.   // {{{ _GameSpyPortPlus10Main() - Query Protocol: GameSpy Port+10 - Type: Main Methode
  1807.   // @return array  decoded data received from gameserver
  1808.   //         bool   FALSE if an error occur
  1809.   // @access protected
  1810.   function _GameSpyPortPlus10Main()
  1811.   {
  1812.     return $this->_GameSpyMain();
  1813.   }
  1814.   // }}}
  1815.  
  1816.   // {{{ _GameSpyPortPlus10Details() - Query Protocol: GameSpy Port+10 - Type: Server Details
  1817.   // @return array  decoded data received from gameserver
  1818.   //         bool   FALSE if an error occur
  1819.   // @access protected
  1820.   function _GameSpyPortPlus10Details()
  1821.   {
  1822.     return $this->_GameSpyDetails();
  1823.   }
  1824.   // }}}
  1825.  
  1826.   // {{{ _GameSpyPortPlus10Rules() - Query Protocol: GameSpy Port+10 - Type: Server Rules
  1827.   // @return array  decoded data received from gameserver
  1828.   //         bool   FALSE if an error occur
  1829.   // @access protected
  1830.   function _GameSpyPortPlus10Rules()
  1831.   {
  1832.     return $this->_GameSpyRules();
  1833.   }
  1834.   // }}}
  1835.  
  1836.   // {{{ _GameSpyPortPlus10Players() - Query Protocol: GameSpy Port+10 - Type: Players
  1837.   // @return array  decoded data received from gameserver
  1838.   //         bool   FALSE if an error occur
  1839.   // @access protected
  1840.   function _GameSpyPortPlus10Players()
  1841.   {
  1842.     return $this->_GameSpyPlayers();
  1843.   }
  1844.   // }}}
  1845.  
  1846.   // {{{ _GameSpyPortPlus10AutoDetect() - Query Protocol: GameSpy Port+10 - Type: AutoDetect Methode
  1847.   // @return bool  always TRUE
  1848.   // @access protected
  1849.   function _GameSpyPortPlus10AutoDetect()
  1850.   {
  1851.     $this->_queryport = $this->_port + 10;
  1852.     return TRUE;
  1853.   }
  1854.   // }}}
  1855.  
  1856.   // {{{ _GameSpyPortPlus10FullInfo() - Query Protocol: GameSpy Port+10 - Type: Request Full Server Info
  1857.   // @return array  decoded data received from gameserver
  1858.   // @access protected
  1859.   function _GameSpyPortPlus10FullInfo()
  1860.   {
  1861.     return $this->_GameSpyFullInfo();
  1862.   }
  1863.   // }}}
  1864.   // }}}
  1865.  
  1866.   // {{{ Query Protocol: GameSpy2
  1867.   // {{{ _GameSpy2Main() - Query Protocol: GameSpy2 - Type: Main Methode
  1868.   // @return array  decoded data received from gameserver
  1869.   //         bool   FALSE if an error occur
  1870.   // @access protected
  1871.   function _GameSpy2Main()
  1872.   {
  1873.     $recv   = "";
  1874.     $prefix = "";
  1875.     $tosend = "";
  1876.     $data   = array();
  1877.  
  1878.     $tosend  = "\xFE\xFD\x00\x04\x05\x06\x07";
  1879.     $tosend .= (array_search("Details", $this->_gettypes) !== FALSE) ? "\xFF" : "\x00";
  1880.     $tosend .= (array_search("Players", $this->_gettypes) !== FALSE) ? "\xFF" : "\x00";
  1881.     $tosend .= (array_search("Teams",   $this->_gettypes) !== FALSE) ? "\xFF" : "\x00";
  1882.     $tosend .= "\x00\x00\x00";
  1883.  
  1884.     $this->_CreateUDPSocket();
  1885.     $this->_SendSocket($tosend);
  1886.     $recv = implode("", $this->_GetSocketDataNr(1));
  1887.  
  1888.     if (!$this->_CheckQueryHeader($recv, "\x00\x04\x05\x06\x07", $prefix))
  1889.       return FALSE;
  1890.  
  1891.     if (substr($recv, 0, 8) == "splitnum")
  1892.       $recv = substr($recv, 11);
  1893.  
  1894.     foreach ($this->_gettypes as $type)
  1895.     {
  1896.       $data[$type] = call_user_func_array(array(&$this, "_".$this->_protocol.$type), array(&$recv));
  1897.       if ($this->ERROR)
  1898.         return FALSE;
  1899.     }
  1900.     $this->_CloseUDPSocket();
  1901.  
  1902.     return $data;
  1903.   }
  1904.   // }}}
  1905.  
  1906.   // {{{ _GameSpy2Details() - Query Protocol: GameSpy2 - Type: Server Details
  1907.   // @return array  decoded data received from gameserver
  1908.   //         bool   FALSE if an error occur
  1909.   // @access protected
  1910.   function _GameSpy2Details(&$recv)
  1911.   {
  1912.     $key  = "";
  1913.     $data = array();
  1914.  
  1915.     while (($key = $this->_GetCharacterTerminatedString($recv, "\x00")) != "")
  1916.       $data[$key] = $this->_GetCharacterTerminatedString($recv, "\x00");
  1917.  
  1918.     if ($recv{0} == "\x00")
  1919.       $recv = substr($recv, 1);
  1920.  
  1921.     return $data;
  1922.   }
  1923.   // }}}
  1924.  
  1925.  
  1926.   // {{{ _GameSpy2Players() - Query Protocol: GameSpy2 - Type: Players
  1927.   // @return array  decoded data received from gameserver
  1928.   //         bool   FALSE if an error occur
  1929.   // @access protected
  1930.   function _GameSpy2Players(&$recv)
  1931.   {
  1932.     $tmp     = "";
  1933.     $item    = 0;
  1934.     $counter = 0;
  1935.     $keys    = array();
  1936.     $data    = array();
  1937.  
  1938.     if (strlen($recv) == 0)
  1939.       return $data;
  1940.  
  1941.     $data["PlayerCount"] = $this->_GetByteAsAscii($recv);
  1942.     $tmp = $this->_GetByteAsAscii($recv);
  1943.     if ($tmp == ord("p"))
  1944.       $recv = chr($tmp).$recv;
  1945.     else
  1946.       $data["PlayerCount"] += $tmp;
  1947.  
  1948.     while (($tmp = $this->_GetCharacterTerminatedString($recv, "\x00")) != "")
  1949.     {
  1950.       if (substr($tmp, strlen($tmp) - 1) == "_")
  1951.         $tmp = substr($tmp, 0, strlen($tmp) - 1);
  1952.       array_push($keys, $tmp);
  1953.     }
  1954.  
  1955.     while (($tmp = $this->_GetCharacterTerminatedString($recv, "\x00")) != "")
  1956.     {
  1957.       $data[$counter][$keys[$item]] = $tmp;
  1958.       $item++;
  1959.       if ($item == count($keys))
  1960.       {
  1961.         $item = 0;
  1962.         $counter++;
  1963.       }
  1964.     }
  1965.  
  1966.     return $data;
  1967.   }
  1968.   // }}}
  1969.  
  1970.   // {{{ _GameSpy2Teams() - Query Protocol: GameSpy2 - Type: Teams
  1971.   // @return array  decoded data received from gameserver
  1972.   //         bool   FALSE if an error occur
  1973.   // @access protected
  1974.   function _GameSpy2Teams(&$recv)
  1975.   {
  1976.     $tmp     = "";
  1977.     $item    = 0;
  1978.     $counter = 0;
  1979.     $keys    = array();
  1980.     $data    = array();
  1981.  
  1982.     if (strlen($recv) == 0)
  1983.       return $data;
  1984.  
  1985.     $numrules = $this->_GetByteAsAscii($recv);
  1986.     while (($tmp = $this->_GetCharacterTerminatedString($recv, "\x00")) != "")
  1987.     {
  1988.       if (substr($tmp, strlen($tmp) - 1) == "_")
  1989.         $tmp = substr($tmp, 0, strlen($tmp) - 1);
  1990.       array_push($keys, $tmp);
  1991.     }
  1992.  
  1993.     while (($tmp = $this->_GetCharacterTerminatedString($recv, "\x00")) != "")
  1994.     {
  1995.       $data[$counter][$keys[$item]] = $tmp;
  1996.       $item++;
  1997.       if ($item == count($keys))
  1998.       {
  1999.         $item = 0;
  2000.         $counter++;
  2001.       }
  2002.     }
  2003.  
  2004.     return $data;
  2005.   }
  2006.   // }}}
  2007.  
  2008.   // {{{ _GameSpy2AutoDetect() - Query Protocol: GameSpy2 - Type: AutoDetect Methode
  2009.   // @return bool  always TRUE
  2010.   // @access protected
  2011.   function _GameSpy2AutoDetect()
  2012.   {
  2013.     $this->_queryport = 23000;
  2014.     return TRUE;
  2015.   }
  2016.   // }}}
  2017.  
  2018.   // {{{ _GameSpy2FullInfo() - Query Protocol: GameSpy2 - Type: Request Full Server Info
  2019.   // @return array  decoded data received from gameserver
  2020.   function _GameSpy2FullInfo()
  2021.   {
  2022.     $this->SetRequestData(array("Details", "Players", "Teams"));
  2023.     return $this->_GameSpy2Main();
  2024.   }
  2025.   // }}}
  2026.   // }}}
  2027.  
  2028.   // {{{ Query Protocol: GameSpy3
  2029.   // {{{ _GameSpy3Main() - Query Protocol: GameSpy3 - Type: Main Methode
  2030.   // @return array  decoded data received from gameserver
  2031.   //         bool   FALSE if an error occur
  2032.   // @access protected
  2033.   function _GameSpy3Main($challenge = false)
  2034.   {
  2035.     $recv       = "";
  2036.     $recv_arr   = array();
  2037.     $recv_arr2  = array();
  2038.     $prefix     = "";
  2039.     $tosend     = "";
  2040.     $data       = array();
  2041.     $end        = 0;
  2042.     $identifier = "\x04\x05\x06\x07";
  2043.     $chall_str  = "";
  2044.  
  2045.     $this->_CreateUDPSocket();
  2046.  
  2047.     if ($challenge)
  2048.     {
  2049.       $tosend = "\xFE\xFD\x09" . $identifier;
  2050.       $this->_SendSocket($tosend);
  2051.       $recv = implode("", $this->_GetSocketDataNr(1));
  2052.       if (!$this->_CheckQueryHeader($recv, "\x09" . $identifier, $prefix))
  2053.         return FALSE;
  2054.       $chall_str = pack("N", (int)$recv);
  2055.     }
  2056.  
  2057.     $tosend  = "\xFE\xFD\x00" . $identifier . $chall_str;
  2058.     $tosend .= (array_search("Details", $this->_gettypes) !== FALSE) ? "\xFF" : "\x00";
  2059.     $tosend .= (array_search("Players", $this->_gettypes) !== FALSE) ? "\xFF" : "\x00";
  2060.     $tosend .= (array_search("Teams",   $this->_gettypes) !== FALSE) ? "\xFF" : "\x00";
  2061.     $tosend .= "\x01";
  2062.     $this->_SendSocket($tosend);
  2063.  
  2064.     while(!$end)
  2065.     {
  2066.       $recv = implode("", $this->_GetSocketDataNr(1));
  2067.       if (!$this->_CheckQueryHeader($recv, "\x00" . $identifier, $prefix))
  2068.         return FALSE;
  2069.  
  2070.       $index = 0;
  2071.       if (substr($recv, 0, 8) != "splitnum")
  2072.       {
  2073.         $end = 1;
  2074.       }
  2075.       else
  2076.       {
  2077.         $recv = substr($recv, 9);
  2078.         $index = ord($recv{0});
  2079.         if (ord($recv{0}) > ord("\x7F"))
  2080.         {
  2081.           $end = 1;
  2082.           $index = count($recv_arr);
  2083.         }
  2084.       }
  2085.  
  2086.       $recv_arr[$index] = substr($recv, 1);
  2087.     }
  2088.  
  2089.     $recv = "";
  2090.     for ($i = 0; $i < count($recv_arr); $i++)
  2091.     {
  2092.       # we currently ignore the first byte
  2093.      $recv_arr[$i] = substr($recv_arr[$i], 1);
  2094.       $start = 0;
  2095.       $end   = strlen($recv_arr[$i]);
  2096.  
  2097.       $recv_tmp = $recv_arr[$i];
  2098.  
  2099.       # check head
  2100.      $starttmp = $this->_GetCharacterTerminatedString($recv_tmp, "\x00");
  2101.       if (substr($starttmp, -1) == "_")
  2102.         $start = strlen($starttmp) + 2;
  2103.  
  2104.       # check body
  2105.      if (substr($recv_tmp, -2) != "\x00\x00")
  2106.       {
  2107.         $j = 0;
  2108.         for($j = 2; (substr($recv_tmp, strlen($recv_tmp) - $j, 1) != "\x00" || $j == strlen($recv_tmp)); $j++);
  2109.         $end = -$j + 1;
  2110.       }
  2111.  
  2112.       $recv .= substr($recv_arr[$i], $start, $end);
  2113.     }
  2114.  
  2115.     foreach ($this->_gettypes as $type)
  2116.     {
  2117.       $data[$type] = call_user_func_array(array(&$this, "_".$this->_protocol.$type), array(&$recv));
  2118.       if ($this->ERROR)
  2119.         return FALSE;
  2120.     }
  2121.     $this->_CloseUDPSocket();
  2122.  
  2123.     return $data;
  2124.   }
  2125.   // }}}
  2126.  
  2127.   // {{{ _GameSpy3Details() - Query Protocol: GameSpy2 - Type: Server Details
  2128.   // @return array  decoded data received from gameserver
  2129.   //         bool   FALSE if an error occur
  2130.   // @access protected
  2131.   function _GameSpy3Details(&$recv)
  2132.   {
  2133.     return $this->_GameSpy2Details($recv);
  2134.   }
  2135.   // }}}
  2136.  
  2137.   // {{{ _GameSpy3Players() - Query Protocol: GameSpy3 - Type: Players
  2138.   // @return array  decoded data received from gameserver
  2139.   //         bool   FALSE if an error occur
  2140.   // @access protected
  2141.   function _GameSpy3Players(&$recv)
  2142.   {
  2143.     $data = $this->_GameSpy2Players($recv);
  2144.     unset($data["PlayerCount"]);
  2145.     return $data;
  2146.   }
  2147.   // }}}
  2148.  
  2149.   // {{{ _GameSpy3Teams() - Query Protocol: GameSpy3 - Type: Teams
  2150.   // @return array  decoded data received from gameserver
  2151.   //         bool   FALSE if an error occur
  2152.   // @access protected
  2153.   function _GameSpy3Teams(&$recv)
  2154.   {
  2155.     $tmp     = "";
  2156.     $item    = 0;
  2157.     $counter = 0;
  2158.     $data    = array();
  2159.  
  2160.     if (strlen($recv) == 0)
  2161.       return $data;
  2162.  
  2163.     while(strlen($recv))
  2164.     {
  2165.       $key = $this->_GetCharacterTerminatedString($recv, "\x00");
  2166.       $this->_GetCharacterTerminatedString($recv, "\x00");
  2167.       if (substr($key, -1) == "_")
  2168.         $key = substr($key, 0, -1);
  2169.  
  2170.       $counter = 0;
  2171.       while (($tmp = $this->_GetCharacterTerminatedString($recv, "\x00")) != "")
  2172.       {
  2173.         $data[$counter][$key] = $tmp;
  2174.         $counter++;
  2175.       }
  2176.     }
  2177.  
  2178.     return $data;
  2179.   }
  2180.   // }}}
  2181.  
  2182.   // {{{ _GameSpy3AutoDetect() - Query Protocol: GameSpy3 - Type: AutoDetect Methode
  2183.   // @return bool  always TRUE
  2184.   // @access protected
  2185.   function _GameSpy3AutoDetect()
  2186.   {
  2187.     $this->_queryport = $this->_port + 13333;
  2188.     return TRUE;
  2189.   }
  2190.   // }}}
  2191.  
  2192.   // {{{ _GameSpy3FullInfo() - Query Protocol: GameSpy3 - Type: Request Full Server Info
  2193.   // @return array  decoded data received from gameserver
  2194.   // @access protected
  2195.   function _GameSpy3FullInfo()
  2196.   {
  2197.     $this->SetRequestData(array("Details", "Players", "Teams"));
  2198.     return $this->_GameSpy3Main(false);
  2199.   }
  2200.   // }}}
  2201.   // }}}
  2202.  
  2203.   // {{{ Query Protocol: GameSpy4
  2204.   // {{{ _GameSpy4Main() - Query Protocol: GameSpy4 - Type: Main Methode
  2205.   // @return array  decoded data received from gameserver
  2206.   //         bool   FALSE if an error occur
  2207.   // @access protected
  2208.   function _GameSpy4Main()
  2209.   {
  2210.     return $this->_GameSpy3Main(true);
  2211.   }
  2212.   // }}}
  2213.  
  2214.   // {{{ _GameSpy4Details() - Query Protocol: GameSpy2 - Type: Server Details
  2215.   // @return array  decoded data received from gameserver
  2216.   //         bool   FALSE if an error occur
  2217.   // @access protected
  2218.   function _GameSpy4Details(&$recv)
  2219.   {
  2220.     return $this->_GameSpy3Details($recv);
  2221.   }
  2222.   // }}}
  2223.  
  2224.   // {{{ _GameSpy4Players() - Query Protocol: GameSpy4 - Type: Players
  2225.   // @return array  decoded data received from gameserver
  2226.   //         bool   FALSE if an error occur
  2227.   // @access protected
  2228.   function _GameSpy4Players(&$recv)
  2229.   {
  2230.     return $this->_GameSpy3Players($recv);
  2231.   }
  2232.   // }}}
  2233.  
  2234.   // {{{ _GameSpy4Teams() - Query Protocol: GameSpy4 - Type: Teams
  2235.   // @return array  decoded data received from gameserver
  2236.   //         bool   FALSE if an error occur
  2237.   // @access protected
  2238.   function _GameSpy4Teams(&$recv)
  2239.   {
  2240.     return $this->_GameSpy3Teams($recv);
  2241.   }
  2242.   // }}}
  2243.  
  2244.   // {{{ _GameSpy4AutoDetect() - Query Protocol: GameSpy4 - Type: AutoDetect Methode
  2245.   // @return bool  always TRUE
  2246.   // @access protected
  2247.   function _GameSpy4AutoDetect()
  2248.   {
  2249.     return $this->_GameSpy3AutoDetect();
  2250.   }
  2251.   // }}}
  2252.  
  2253.   // {{{ _GameSpy4FullInfo() - Query Protocol: GameSpy4 - Type: Request Full Server Info
  2254.   // @return array  decoded data received from gameserver
  2255.   // @access protected
  2256.   function _GameSpy4FullInfo()
  2257.   {
  2258.     $this->SetRequestData(array("Details", "Players", "Teams"));
  2259.     return $this->_GameSpy3Main(true);
  2260.   }
  2261.   // }}}
  2262.   // }}}
  2263.   // }}}
  2264. }
  2265.  
  2266. /* {{{ Description
  2267.  * RCon Query Protocol Class
  2268.  *
  2269.  * Adds RCon Support to the Gameserver Query Class
  2270.  *
  2271.  * Supported Protocols:
  2272.  *   - Half-Life ("HalfLife")
  2273.  *
  2274.  * Users:
  2275.  *   $this->SetRConPassword("rconpassword")
  2276.  *     ... rcon password to use for query
  2277.  *
  2278.  *   $this->SetRConCommand("command")
  2279.  *     ... rcon command to send
  2280.  *
  2281.  *   $this->SetRequestData(array("RCon"))
  2282.  *     ... "RCon" is the only available requestdata type
  2283.  *
  2284.  * Developers:
  2285.  *   This class extends the gameserver query protocol
  2286.  *   If you want to add your own rcon query, the only needed method must be named like:
  2287.  *     _RConYourNameMain() ... methode will be called automatically from engine
  2288.  *
  2289.  }}} */
  2290.  
  2291. class RCon extends GSQuery
  2292. {
  2293.   // {{{ global variable definitions
  2294.   var $_rconcommand;
  2295.   var $_rconpassword;
  2296.   // }}}
  2297.  
  2298.   // {{{ RCon() - main class constructor
  2299.   function RCon()
  2300.   {
  2301.     $_rconcommand  = "";
  2302.     $_rconpassword = "";
  2303.     $this->GSQuery();
  2304.     return TRUE;
  2305.   }
  2306.   // }}}
  2307.  
  2308.   // {{{ SetProtocol() - sets query protocol to use
  2309.   // @param  string $arg1  protocol to use for gameserver query
  2310.   // @return bool          always TRUE
  2311.   // @access public
  2312.   function SetProtocol($string)
  2313.   {
  2314.     GSQuery::SetProtocol("RCon".$string);
  2315.     return TRUE;
  2316.   }
  2317.   // }}}
  2318.  
  2319.   // {{{ SetRConCommand() - sets rcon command to send
  2320.   // @param  string $arg1  rcon command to send to the gameserver
  2321.   // @return bool          always TRUE
  2322.   // @access public
  2323.   function SetRconCommand($string)
  2324.   {
  2325.     $this->_rconcommand = $string;
  2326.     trigger_error("<b>Set RCon Command</b>: ".$string);
  2327.     return TRUE;
  2328.   }
  2329.   // }}}
  2330.  
  2331.   // {{{ SetRConPassword() - sets rcon password
  2332.   // @param  string $arg1  rcon password to use for rcon query
  2333.   // @return bool          always TRUE
  2334.   // @access public
  2335.   function SetRConPassword($string)
  2336.   {
  2337.     $this->_rconpassword = $string;
  2338.     trigger_error("<b>Set RCon Password</b>: ".$string);
  2339.     return TRUE;
  2340.   }
  2341.   // }}}
  2342.  
  2343.   // {{{ _CheckSettings() - check for valid settings
  2344.   // @return bool  FALSE if an error occur
  2345.   //               TRUE otherwise
  2346.   // @access protected
  2347.   function _CheckSettings()
  2348.   {
  2349.     GSQuery::_CheckSettings();
  2350.  
  2351.     if ($this->_rconcommand == "")
  2352.       $this->_SoftError("No RCon Command set");
  2353.     if ($this->_rconpassword == "")
  2354.       $this->_SoftError("No RCon Password set");
  2355.  
  2356.     if ($this->ERROR)
  2357.       return FALSE;
  2358.  
  2359.     return TRUE;
  2360.   }
  2361.   // }}}
  2362.  
  2363.   // {{{ RCon Protocol: HalfLife
  2364.   // {{{ _RConHalfLifeMain() - RCon Protocol: HalfLife
  2365.   // @return array  decoded data received from gameserver
  2366.   //         bool   FALSE if an error occur
  2367.   // @access protected
  2368.   function _RConHalfLifeMain()
  2369.   {
  2370.     $recv  = "";
  2371.     $chnum = 0;
  2372.     $data  = array();
  2373.  
  2374.     $this->_CreateUDPSocket();
  2375.     $this->_SendSocket("\xFF\xFF\xFF\xFFchallenge rcon\x00");
  2376.     $recv = implode("", $this->_GetSocketDataNr(1));
  2377.  
  2378.     if (!$this->_CheckQueryHeader($recv, "\xFF\xFF\xFF\xFFchallenge rcon ", $prefix))
  2379.       return FALSE;
  2380.  
  2381.     $chnum = substr($recv, 0, strlen($recv) - 2);
  2382.     $this->_SendSocket("\xFF\xFF\xFF\xFFrcon $chnum ".$this->_rconpassword." ".$this->_rconcommand."\n");
  2383.     $recv = implode("", $this->_GetSocketDataNr(1));
  2384.  
  2385.     if (!$this->_CheckQueryHeader($recv, "\xFF\xFF\xFF\xFF", $prefix))
  2386.       return FALSE;
  2387.  
  2388.     $data["RCon"] = substr($recv, 1, strlen($recv) - 3);
  2389.  
  2390.     if ($data["RCon"] == "Bad rcon_password." || $data["RCon"] == "Bad challenge.")
  2391.     {
  2392.       $this->_SoftError("RCon Protocol: Half-Life - ".$data["RCon"]);
  2393.       return FALSE;
  2394.     }
  2395.  
  2396.     $this->_CloseUDPSocket();
  2397.  
  2398.     return $data;
  2399.   }
  2400.   // }}}
  2401.   // }}}
  2402. }
  2403.  
  2404. //echo "<pre>\n";
  2405. define("DEBUG", FALSE);
  2406. $query = new GSQuery();
  2407. #$query->SetProtocol("AutoDetect");
  2408. $query->SetProtocol("GameSpy4");
  2409. #$query->SetProtocol("Doom3");
  2410. #$query->SetProtocols(array("HalfLife", "Quake2", "Quake3", "GameSpy", "GameSpyPortPlus10", "GameSpy2", "GameSpy3", "GameSpy4", "AllSeeingEye", "Doom3"));
  2411. #$query->SetProtocols(array("Doom3"));
  2412. #$query->SetProtocols(array("Quake4"));
  2413. if (isset($_GET["queryport"]) && $_GET["queryport"] != "")
  2414.   $query->SetIpPort($_GET["ip"].":".$_GET["port"].":".$_GET["queryport"]);
  2415. else
  2416.   $query->SetIpPort($_GET["ip"].":".$_GET["port"]);
  2417.  
  2418. // Set default value to Anzus War Games if no IP and PORT supplied
  2419. if (!isset($_GET["ip"]))
  2420.   $query->SetIpPort("216.189.8.183:2302");
  2421. // done setting default
  2422.  
  2423. $query->SetRequestData(array("FullInfo"));
  2424. $query->SetSocketTimeOut(0, 100000);
  2425. $query->SetSocketLoopTimeOut(1000);
  2426. $data = $query->GetData();
  2427.  
  2428. //print_r($data);
  2429. ?>
  2430.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement