[code]<?php

/**
*
* Serverstatus class
*
* Tested and working in PHP5, PHP6
* Only tested with Call of Duty serie.
* Connects to a server an retrieves the data.
*
* @throws ServerException
*
* Known bugs:
*  - Sometimes (random) the server returns 'disconnect' as data.
*    Then the script just dies for unknown reasons (???)*
*
* Version 2.0
*   Class implementation
*
*   CHANGELOG
*     1.0      - 5 May 2004
*                Made by =(.T.T.B.)= Spikey (http://www.phphulp.nl/php/scripts/7/145/)
*     1.1, 1.2 - 13 May 2004
*                http://www.phphulp.nl/php/scripts/7/146/
*     2.0      - 1 March 2008
*                Class implementation. Totally rewritten 1.2 version.
*                http://www.phphulp.nl/php/scripts/7/1293/
*
*                       Mark van Seventer
*
*/
class ServerException extends Exception { }

class ServerStatus {

	/* Server address */
	private $ip;
	private $port;

	/* Server data */
	private $cvar   = array();
	private $player = array();
	private $score  = array();
	private $ping   = array();

	/**
	* Constructor, saves IP and port
	* Note that the IP does not has to be syntaxed as
	* XXX.XXX.XXX.XXX. A host can also be entered.
	*
	* @param String $ip
	* @param String $port
	* @param boolean $autoConnect
	*/
	public function __construct($ip, $port = '28960', $autoConnect = true) {
		if(!isset($ip)) {
			throw new ServerException('IP cannot be left empty!');
		}
		$this->ip   = $ip;
		$this->port = $port;

		if($autoConnect) {
			$this->connect();
		}
	}

	/**
	* Connects to server
	*/
	public function connect() {
		if(!empty($this->player)) {
			throw new ServerException('No need to connect to the same server twice!');
		}

		$con = fsockopen('udp://' . $this->ip, $this->port);
		if(!$con) {
			throw new ServerException('Failed connecting to the server!');
		}

		fwrite($con, chr(255) . chr(255) . chr(255) . chr(255) . chr(0x02) . 'getstatus' . chr(0x00));
		fread($con, 4);

		$status = socket_get_status($con);
		if($status['unread_bytes'] == 0) {
			throw new ServerException('Failed retrieving data from the server!');
		}

		$data = fread($con, $status['unread_bytes']);
		//do {
		//	$data .= fread($con, 1); 
		//	$status = socket_get_status($con);
		//} 
		//while($status['unread_bytes'] != 0);

		fclose($con);

		$this->_handle($data);
	}

	/**
	* Handles retrieved data
	* @param String $data
	*/
	private function _handle($data) {
		if($data == 'disconnect') {
			throw new ServerException('Unknown error retrieving data!');
		}

		$playerData = explode("\n", $data);

		/* Remove unnecessary items */
		array_shift($playerData);//statusResponse
		array_pop($playerData);//empty

		$cvars = array_shift($playerData);
		$cvars = explode('\\', $cvars);
		array_shift($cvars);//empty

		$this->_parseCvar($cvars);
		$this->_parsePlayer($playerData);
	}

	/**
	* Parses cvars
	* @param Array $cvar
	*/
	private function _parseCvar($cvar) {
		/**
		* We want to achieve an array with:
		* $cvar => $cvar-value
		*/
		$cvarCount = count($cvar);
		for($i = 0; $i < $cvarCount; $i++) {
			$cvarValueIndex = $i + 1;
			$this->cvar[$cvar[$i]] = $this->_colorize($cvar[$cvarValueIndex]);
			$i += 1;//skip cvarvalue
		}
	}

	/**
	* Parses player information
	* @param Array $player
	*/
	private function _parsePlayer($players) {
		$regex = '#([0-9]+) ([0-9]+) "(.*)"#';
		foreach($players as $player) {
			preg_match($regex, $player, $info);
			$this->score[]  = $info[1];
			$this->ping[]   = $info[2];
			$this->player[] = $info[3];
		}

		/* Sort players */
		array_multisort($this->score, SORT_DESC, SORT_NUMERIC,
						$this->ping,  SORT_ASC,  SORT_NUMERIC,
						$this->player);

		/* Colorize after sort to avoid sorting on <span> */
		$this->player = array_map(array($this, '_colorize'), $this->player);
	}

	/**
	* Colorizes according to Call of Duty format
	* @param String $string
	* @return String $string
	*/
	private function _colorize($string) {
		$string = htmlentities($string);

		$colorcodes = array(
			'^1' => '</span><span style="color: red">',
			'^2' => '</span><span style="color: green">',
			'^3' => '</span><span style="color: yellow">',
			'^4' => '</span><span style="color: blue">',
			'^5' => '</span><span style="color: cyan">',
			'^6' => '</span><span style="color: purple">',
			'^7' => '</span><span style="color: #CCC">',//white is unreadable
			'^8' => '</span><span style="color: black">',//team color
			'^9' => '</span><span style="color: gray">',
			'^0' => '</span><span style="color: black">',
		);
		$string = str_replace(array_keys($colorcodes), $colorcodes, $string);

		/* Fix the </span> in the beginning and add one at the end */
		$pos = strpos($string, '</span>');
		if($pos !== false) {
			$length = strlen('</span>');
			$string = substr($string, 0, $pos) . substr($string, $pos + $length);//remove first </span>
			$string .= '</span>';//add trailing </span>
		}
		
		return $string;
	}

	/**
	* Allow access to private variables
	* @param String $var
	* @return String private $var
	*/
	public function __get($var) {
		return isset($this->$var) ? $this->$var : false;
	}

}
?>[/code]
[code]<?php

try {
	$status = new ServerStatus('85.131.237.222', '28960', false);
	$status->connect();//optional

	/**
	* The above is the same as
	* $status = new ServerStatus('85.131.237.222');
	*/

	/* EXAMPLE */
	echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">' . "\n" .
         '<html xmlns="http://www.w3.org/1999/xhtml">' . "\n" .
         '<head>' . "\n" .
         '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />' . "\n" .
         '<title>Agirre ServerStatus</title>' . "\n" .
         '</head>' . "\n" .
         '<body>' . "\n";

	/* EXAMPLE: printing example header */
	echo '<p style="font-weight: bold">Server status: ' . $status->ip . ':' . $status->port . '</p>' . "\n";

	/* EXAMPLE: printing cvars */
	echo '<table>' . "\n" .
	     '  <tr>' . "\n" .
	     '    <td style="font-style: italic">Cvar</td>' . "\n" .
	     '    <td style="font-style: italic">Value</td>' . "\n" .
	     '  </tr>' . "\n";

	foreach($status->cvar as $cvar => $value) {
		echo '  <tr>' . "\n" .
		     '    <td>' . $cvar . '</td>' . "\n" .
		     '    <td>' . $value . '</td>' . "\n" .
		     '  </tr>' . "\n";
	}
	echo '</table>' . "\n";

	/* EXAMPLE: printing player table */
	echo '<table>' . "\n" .
	     '  <tr>' . "\n" .
	     '    <td style="font-style: italic">Player</td>' . "\n" .
	     '    <td style="font-style: italic">Score</td>' . "\n" .
	     '    <td style="font-style: italic">Ping</td>' . "\n" .
	     '  </tr>' .  "\n";

	$playerCount = count($status->player);
	for($i = 0; $i < $playerCount; $i++) {
		echo '  <tr>' . "\n" .
		     '    <td>' . $status->player[$i] . '</td>' . "\n" .
		     '    <td>' . $status->score[$i] . '</td>' . "\n" .
		     '    <td>' . $status->ping[$i] . '</td>' . "\n" .
		     '  </tr>' .  "\n";
	}
	echo '</table>' . "\n";

	echo '</body>' . "\n" . '</html>';

}
catch(ServerException $e) {
	echo 'Error: ' . $e->getMessage();
}

?>[/code]