-------------------------
tsinfo.inc.php
-------------------------

<?php

error_reporting(0);

/*
*
* @file: tsinfo.inc.php
* @version: 3.21.06-06-06
* @auteur: Boaz den Besten
* @contact: www.n3rd.nl
* @omschrijving:
*  - Constructor Function
*  void		n3rd_tsinfo	( string IP, integer Port [ , integer Query Port ] )
*
*  - Intern Functions
*  mixed	ts_get	( [ integer Type ] )
*  string	serverinfo ( string Name )
*  mixed	channelinfo ( )
*  array	playerinfo ( )
*  string	pl_flags ( integer Pprivs, integer Cprivs )
*  string	ch_flags ( integer ChannelFlags )
*
*  - User Functions
*  string	tsinfo ( )
*
*/

define('USER_TSINFO_SI', 1);
define('USER_TSINFO_PL', 2);
define('USER_TSINFO_CL', 4);

class n3rd_tsinfo{

	//--- Constructor ---\\
	function n3rd_tsinfo($p_sIp, $p_iPort, $p_iQueryport=51234){
		$this->m_sIp = $p_sIp;
		$this->m_iPort = $p_iPort;
		$this->m_iQueryport = $p_iQueryport;
		
		$this->m_sVersion = 'TeamSpeak Info v3.21<br />Powered by N3RD.nl';
	}
	
	//--- Private Functions ---\\
	function ts_get($p_iCmd=USER_TSINFO_SI){
		$l_aReturn = array();
		
		$fp = fsockopen($this->m_sIp, $this->m_iQueryport, $l_iErrno, $l_sErrstr, 1);
		
		if(!$fp){
			return false;
		}
		
		switch($p_iCmd){
			case USER_TSINFO_PL:
				$l_sCmd = "pl ".$this->m_iPort."\nquit\n";
				break;
			case USER_TSINFO_CL:
				$l_sCmd = "cl ".$this->m_iPort."\nquit\n";
				break;
			default:
				$l_sCmd = "si ".$this->m_iPort."\nquit\n";
		}
		
		fputs($fp, $l_sCmd);
		
		while($l_sData = fgets($fp, 4096)){
			$l_aReturn[] = $l_sData;
		}
		
		fclose($fp);
		
		return $l_aReturn;
	}
	
	function serverinfo($p_sInfo){
		$l_sInfo = implode('=', $this->ts_get(USER_TSINFO_SI));
		$l_aInfo = explode('=', $l_sInfo);
		
		$l_iInfo = array_search($p_sInfo, $l_aInfo);
		return htmlentities($l_aInfo[$l_iInfo+1], ENT_QUOTES);
	}
	
	function channelinfo(){
		$l_aReturn = array();
	
		$l_aInfo = $this->ts_get(USER_TSINFO_CL);
		
		if(trim($l_aInfo[0]) !== '[TS]'){
			return false;
		}
		
		$l_aNames = explode(chr(9), $l_aInfo[1]);
		
		for($i=2;$i<count($l_aInfo)-1;$i++){
			$l_aChannel = explode(chr(9), $l_aInfo[$i]);
			for($f=0;$f<count($l_aChannel);$f++){
				$l_aReturn[$l_aChannel[3].trim($l_aChannel[5], "\x22\x27")][trim($l_aNames[$f])] = htmlentities(trim($l_aChannel[$f], "\x22\x27"), ENT_QUOTES);
			}	
		}
		
		ksort($l_aReturn);
		
		return $l_aReturn;
	}
	
	function playerinfo(){
		$l_aReturn = array();
		
		$l_aInfo = $this->ts_get(USER_TSINFO_PL);
		
		$l_aNames = explode(chr(9), $l_aInfo[1]);
		
		for($i=2;$i<count($l_aInfo)-1;$i++){
			$l_aPlayer = explode(chr(9), $l_aInfo[$i]);
			for($f=0;$f<count($l_aPlayer)-1;$f++){
				$l_aReturn[$l_aPlayer[11].$l_aPlayer[10].trim($l_aPlayer[14], "\x22\x27")][trim($l_aNames[$f])] = htmlentities(trim($l_aPlayer[$f], "\x22\x27"), ENT_QUOTES);
			}	
		}
		
		krsort($l_aReturn);
		
		return $l_aReturn;
	}
	
	function pl_flags($p_iPprivs, $p_iCprivs){
		$a  = (($p_iPprivs & 4) == 4) ? 'R' : 'U';
		$a .= (($p_iPprivs & 1) == 1) ? ' SA' : '';
		  
		$b  = (($p_iCprivs & 1) == 1) ? ' CA' : '';
		
		return ' ('.$a.$b.')';
 	}
	
	function ch_flags($p_iFlags){
		$l_aFlags[0] = ' (R)';
		$l_aFlags[1] = ' (U)';
		$l_aFlags[2] = ' (RM)';
		$l_aFlags[3] = ' (UM)';
		$l_aFlags[4] = ' (RP)';
		$l_aFlags[5] = ' (UP)';
		$l_aFlags[6] = ' (RMP)';
		$l_aFlags[7] = ' (UMP)';
		$l_aFlags[8] = ' (RS)';
		$l_aFlags[9] = ' (US)';
		$l_aFlags[10] = ' (RMS)';
		$l_aFlags[11] = ' (UMS)';
		$l_aFlags[12] = ' (RPS)';
		$l_aFlags[13] = ' (UPS)';
		$l_aFlags[14] = ' (RMPS)';
		$l_aFlags[15] = ' (UMPS)';
		$l_aFlags[16] = ' (RD)';
		$l_aFlags[18] = ' (RMD)';
		$l_aFlags[20] = ' (RPD)';
		$l_aFlags[22] = ' (RMPD)';
		$l_aFlags[24] = ' (RSD)';
		$l_aFlags[26] = ' (RMSD)';
		$l_aFlags[28] = ' (RPSD)';
		$l_aFlags[30] = ' (RMPSD)';

		return $l_aFlags[$p_iFlags];
	}
	
	//--- Public Function ---\\
	function tsinfo(){
		$server = $this->serverinfo('server_name');
		$channels = $this->channelinfo();
		$players = $this->playerinfo();
		
		if(!$server || !$channels){
			$l_sReturn = 'Error while connecting to the server.'.PHP_EOL;
		}else{
		
			$l_sReturn = '<img alt="server" src="image/bullet_server.gif" /> '.$server.'<br />'.PHP_EOL;
			
			foreach($channels as $channel){
				if($channel['parent'] == -1){
					
					// Channel:
					$l_sReturn .= '<img alt="channel" src="image/bullet_channel.gif" /> '.$channel['name'].$this->ch_flags($channel['flags']).'<br />'.PHP_EOL;
					
					foreach($channels as $subchannel){
						if($channel['id'] == $subchannel['parent']){
							
							// Sub Channel:
							$l_sReturn .= '<img alt="subchannel" src="image/bullet_subchannel.gif" /> '.$subchannel['name'].'<br />'.PHP_EOL;
							
							foreach($players as $player){
								if($player['c_id'] == $subchannel['id']){
								
									// Members Of Sub Channel:
									$l_sReturn .= '<img alt="sub" src="image/bullet_sub.gif" /><img alt="'.$player['pflags'].'" src="image/bullet_'.$player['pflags'].'.gif" /> '.$player['nick'].$this->pl_flags($player['pprivs'], $player['cprivs']).'<br />'.PHP_EOL;
								}
							}
							
						}
					}
					
					foreach($players as $player){
						if($player['c_id'] == $channel['id']){
						
							// Member Of Channel:
							$l_sReturn .= '<img alt="'.$player['pflags'].'" src="image/bullet_'.$player['pflags'].'.gif" /> '.$player['nick'].$this->pl_flags($player['pprivs'], $player['cprivs']).'<br />'.PHP_EOL;
						}
					}
					
				}
			}
		
		}
		
		$l_sReturn .= '<p><sub>'.$this->m_sVersion.'</sub></p>'.PHP_EOL;
		
		return $l_sReturn;
	}

}

?>