| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- <?php
- /**
- * Murmur Query Class
- *
- * Based on GT MURMUR PLUGIN, which allows us to query a Murmur server
- * without having to install PHP ICE on the web server.
- * @link http://www.gametracker.com/downloads/gtmurmurplugin.php
- *
- * The response is constructed using Channel Viewer Protocol.
- * @link http://mumble.sourceforge.net/Channel_Viewer_Protocol
- *
- * @author Edmundas Kondrašovas <[email protected]>
- * @license http://www.opensource.org/licenses/MIT
- * @copyright Copyright (c) 2011 Edmundas Kondrašovas <[email protected]>
- * @version 0.6
- *
- */
- class MurmurQuery
- {
- /* Packets */
- const Q_XML = "\x78\x6D\x6C";
- const Q_JSON = "\x6A\x73\x6F\x6E";
- private $users = array();
- private $channels = array();
- private $socket;
- private $host;
- private $port;
- private $timeout;
- private $format;
- private $response;
- private $status;
- private $raw;
- private $online = false;
- /**
- * Constructor
- *
- * @access public
- * @param string hostname
- * @param integer port (optional)
- * @param integer timeout in miliseconds (optional)
- * @param string format (optional)
- * @return void
- */
- public function __construct($host = '', $port = 27800, $timeout = 200, $format = 'json')
- {
- if(!empty($host))
- {
- $this->setup($host, $port, $timeout, $format);
- $this->query();
- }
- }
- /**
- * Set the parameters
- *
- * @access public
- * @param string/array hostname or settings array
- * @param integer port (optional)
- * @param integer timeout in miliseconds (optional)
- * @param string format (optional)
- * @return void
- */
- public function setup($host, $port = 27800, $timeout = 200, $format = 'json')
- {
- if(is_array($host))
- {
- $this->host = array_key_exists('host', $host) ? $host['host'] : '';
- $this->port = array_key_exists('port', $host) ? $host['port'] : $port;
- $this->timeout = array_key_exists('timeout', $host) ? $host['timeout'] : $timeout;
- $this->format = array_key_exists('format', $host) ? $host['format'] : $format;
- }
- else
- {
- $this->host = $host;
- $this->port = $port;
- $this->timeout = $timeout;
- $this->format = $format;
- }
- }
- /**
- * Set data format
- *
- * @access public
- * @param string data format
- * @return void
- */
- public function set_format($format = 'json')
- {
- $this->format = $format;
- }
- /**
- * Query the server
- *
- * @access public
- * @return void
- */
- public function query()
- {
- $this->_connect();
- $this->_send_query($this->format);
- $this->_catch_response();
- if(!empty($this->response)) $this->online = true;
- $this->_close();
- }
- /**
- * Get server status
- *
- * @access public
- * @param boolean return raw response
- * @return mixed json/xml if set to return raw response or array otherwise
- */
- public function get_status($raw = false)
- {
- return ($raw) ? $this->raw : $this->status;
- }
- /**
- * Get users
- *
- * @access public
- * @return array
- */
- public function get_users()
- {
- return $this->users;
- }
- /**
- * Get channels
- *
- * @access public
- * @return array
- */
- public function get_channels()
- {
- return $this->channels;
- }
- /**
- * Check if the server is online
- *
- * @access public
- * @return bool
- */
- public function is_online()
- {
- return $this->online;
- }
- /**
- * Establish a socket connection
- *
- * @access private
- * @return bool
- */
- private function _connect()
- {
- // We need timeout in seconds for fsockopen()
- $timeout = ($this->timeout < 1000) ? 1 : ceil($this->timeout / 1000);
- $this->socket = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
- if(!$this->socket) return false;
- return true;
- }
- /**
- * Send query to the server
- *
- * @access private
- * @param string query (should be one the constants defined)
- * @return void
- */
- private function _send_query($format)
- {
- $data = '';
- switch($format)
- {
- case 'json':
- $data = self::Q_JSON;
- break;
- case 'xml':
- $data = self::Q_XML;
- break;
- default:
- $data = self::Q_JSON;
- break;
- }
- if($this->socket)
- {
- @fwrite($this->socket, $data);
- stream_set_timeout($this->socket, 0, $this->timeout * 1000);
- }
- }
- /**
- * Receive response from the server
- *
- * @access private
- * @return void
- */
- private function _catch_response()
- {
- if($this->socket)
- {
- while($resp = @fread($this->socket, 1024)) $this->response .= $resp;
- stream_set_timeout($this->socket, 0, $this->timeout * 1000);
- $this->raw = $this->response;
- $this->status = $this->parse_response($this->response, $this->format);
- }
- }
- /**
- * Close socket connection
- *
- * @access private
- * @return void
- */
- private function _close()
- {
- if($this->socket) fclose($this->socket);
- $this->response = NULL;
- $this->data = NULL;
- $this->socket = NULL;
- }
- /**
- * Parse data returned from the server
- *
- * @access public
- * @param string xml/json
- * @param string format
- * @return array parsed data
- */
-
- public function parse_response($data, $format = 'json')
- {
- switch($format)
- {
- case 'json':
- $parsed_data = $this->_parse_json($data);
- break;
- case 'xml':
- $parsed_data = $this->_parse_xml($data);
- break;
- default:
- $parsed_data = $this->_parse_json($data);
- break;
- }
- return $parsed_data;
- }
- /**
- * Parse JSON
- *
- * @access private
- * @param string json
- * @return array parsed data
- */
- private function _parse_json($data)
- {
- $parsed_data = array();
- $decoded = json_decode($data, true);
- $this->_parse_channels($decoded);
- $parsed_data['channels'] = $this->channels;
- $parsed_data['users'] = $this->users;
- $parsed_data['original'] = $decoded;
- return $parsed_data;
- }
- /**
- * Parse XML
- *
- * @access private
- * @param string xml
- * @return array parsed data
- */
- // Does not work properly yet.
- private function _parse_xml($data)
- {
- $parsed_data = array();
- $decoded = simplexml_load_string($data);
- $this->_parse_channels($decoded);
- $parsed_data['channels'] = $this->channels;
- $parsed_data['users'] = $this->users;
- $parsed_data['original'] = $decoded;
- return $parsed_data;
- }
- /**
- * Parse the channels
- *
- * @access private
- * @param array channels
- * @return void
- */
- private function _parse_channels($channels)
- {
- if(array_key_exists('x_gtmurmur_error', $channels))
- return;
- // We'll have to deal with the root channel separately
- if(array_key_exists('root', $channels))
- {
- if(count($channels['root']['users']) > 0)
- {
- foreach($channels['root']['users'] as $user) $this->users[] = $user;
- }
- $tmp = $channels['root']['channels'];
- unset($channels['root']['users']);
- unset($channels['root']['channels']);
- $this->_parse_channels($tmp);
- }
- else
- {
- if(count($channels) > 0)
- {
- foreach($channels as $channel)
- {
- if(count($channel['users']) > 0)
- {
- foreach($channel['users'] as $user) $this->users[] = $user;
- }
- if($channel['users'] > 0) unset($channel['users']);
- $this->_parse_channels($channel['channels']);
- if($channel['channels'] > 0) unset($channel['channels']);
-
- $this->channels[] = $channel;
- }
- }
- }
- }
- }
- ?>
|