Location: PHPKode > scripts > SourceQuery > yannickcr-SourceQuery-857c404/src/SourceQuery.php
<?php
class SourceQuery {

	public function __construct($ip, $port=27015) {
		$this->ip = $ip;
		$this->port = $port;
	}

	protected function query($query) {
		$fp = fsockopen('udp://' . $this->ip, $this->port, $errno, $errstr, 2);
		if (!$fp) {
			trigger_error('The server does not respond', E_USER_NOTICE);
			return false;
		} else {
			fwrite($fp, $query);
			stream_set_timeout($fp, 2);
			$result = '';
			do {
				$result .= fread ($fp, 1);
				$fpstatus = socket_get_status($fp);
			} while ($fpstatus['unread_bytes']);
			fclose($fp);
			return $result;
		}
	}

	protected function getChallenge() {
		$challenge = $this->query("\xFF\xFF\xFF\xFFU\xFF\xFF\xFF\xFF");
		return substr($challenge, 5);
	}
	
	// Hex to Signed Dec http://fr2.php.net/manual/en/function.hexdec.php#97172
	private function hexdecs($hex){
	    $dec = hexdec($hex);
	    $max = pow(2, 4 * (strlen($hex) + (strlen($hex) % 2)));
	    $_dec = $max - $dec;
	    return $dec > $_dec ? -$_dec : $dec;
	}
	
	public function getInfos() {
		$infos = $this->query("\xFF\xFF\xFF\xFFTSource Engine Query\x00");

		//  Détermine le protocole utilisé
		$protocol = hexdec(substr(bin2hex($infos), 8, 2));
			
		if($protocol == 109) return $this->getInfos1($infos);
		else if($protocol == 73) return $this->getInfos2($infos);
		
		trigger_error('Unknown server type', E_USER_NOTICE);
		return false;
	}
	
	protected function getInfos1($infos) {
		// Split informations
		$infos = chunk_split(substr(bin2hex($infos), 10), 2, '\\');
		@list($serveur['ip'], $serveur['name'], $serveur['map'], $serveur['mod'], $serveur['modname'], $serveur['params']) = explode('\\00', $infos);
		
		// Split parameters
		$serveur['params'] = substr($serveur['params'],0,18);
		
		$serveur['params'] = chunk_split(str_replace('\\', '', $serveur['params']), 2, ' ');
		list($params['players'], $params['places'], $params['protocol'], $params['dedie'], $params['os'], $params['pass']) = explode(' ', $serveur['params']);
		$params = array(
			'id'		=>	0, // Unsupported
			'bots'		=>	0, // Unsupported
			'ip'		=>	$this->ip,
			'port'		=>	$this->port,
			'players'	=>	hexdec($params['players']),
			'places'	=>	hexdec($params['places']),
			'protocol'	=>	hexdec($params['protocol']),
			'dedie'		=>	chr(hexdec($params['dedie'])),
			'os'		=>	chr(hexdec($params['os'])),
			'pass'		=>	hexdec($params['pass'])
		);
		unset($serveur['ip']);
		unset($serveur['params']);
		
		$serveur = array_map(function($item){
			return pack("H*", str_replace('\\', '', $item));
		}, $serveur);
		
		$infos = ($params + $serveur);
		return $infos;
	}
	
	protected function getInfos2($infos) {
		// Split informations
		$infos = chunk_split(substr(bin2hex($infos), 12), 2, '\\');
		@list($serveur['name'], $serveur['map'], $serveur['mod'], $serveur['modname'], $serveur['params']) = explode('\\00', $infos, 5);
		
		// Split parameters
		$serveur['params'] = substr($serveur['params'], 0);
		
		$serveur['params'] = chunk_split(str_replace('\\', '', $serveur['params']), 2, ' ');
		list($params['id1'], $params['id2'], $params['players'], $params['places'], $params['bots'], $params['dedie'], $params['os'], $params['pass']) = explode(' ', $serveur['params']);
		$params=array(
			'id'		=>  hexdec($params['id2'] . $params['id1']),
			'ip'		=>	$this->ip,
			'port'		=>	$this->port,
			'players'	=>	hexdec($params['players']),
			'places'	=>	hexdec($params['places']),
			'bots'		=>	hexdec($params['bots']),
			'protocol'	=>	73,
			'dedie'		=>	chr(hexdec($params['dedie'])),
			'os'		=>	chr(hexdec($params['os'])),
			'pass'		=>	hexdec($params['pass'])
		);
		unset($serveur['params']);
		
		$serveur = array_map(function($item){
			return pack("H*", str_replace('\\', '', $item));
		}, $serveur);
		
		$infos = ($serveur + $params);	
		return $infos;
	}
	
	public function getPlayers() {
		$challenge = $this->getChallenge();
	
		$infos = $this->query("\xFF\xFF\xFF\xFFU" . $challenge);
		
		$infos = chunk_split(substr(bin2hex($infos), 12), 2, '\\');
		
		$infos = explode('\\', $infos);
		
		$players = array();
		for ($i = 0; isset($infos[$i + 1]); $i = $j + 9) {
			
			// Player name
			$name = '';
			for ($j = $i + 1; isset($infos[$j]) && $infos[$j] != '00'; $j++) $name .= chr(hexdec($infos[$j]));
			
			if (!isset($infos[$j + 8])) break;
			
			// Gametime
			eval('$time="\x'.trim(chunk_split($infos[$j + 5] . $infos[$j + 6] . $infos[$j + 7] . $infos[$j + 8], 2,"\x"), "\x") . '";');
			list(,$time) = unpack('f', $time);
			
			// Score
			$score = ltrim($infos[$j + 4] . $infos[$j + 3] . $infos[$j + 2] . $infos[$j + 1], '0');
			
			$players[] = array(
				'id'	=>	hexdec($infos[$i]),
				'name'	=>	$name,
				'score'	=>	empty($score)? 0 : $this->hexdecs($score),
				'time'	=>	$time
			);
		}
		return $players;
	}
}
?>
Return current item: SourceQuery