<?php
//This class connects PHP with SA:MP Servers (v0.1)
//Original file: http://team.sa-mp.com/sampqry.php.txt
class SAMP_Socket{
//By jose.rob.jr
//Set the address to connect, can be IP or Host
var $addr="";
//Set The port to connect
var $port=0;
//Generate or not XML Document
var $xml=false;
//Give the last result
var $last=array();
//Try to get the IP/Host (may be slow)
var $getHost=false;
//Private variables
private $give=1;
private $fp;
private $ini="";
private $Txml=false;
//Read an address, you can call without parameters if you have set $addr has the exemple in the bottom
function read($addr=null,$port=null,$xml=null){
//This function sets a time limit to complete the page
//the connection will never ends if the server is down without this.
//This function changes the Content-Type header to application/xml if xml is set to true
//If you don't want it, you can print anything (a blank space for exemple) before calling read()
//or setting returnXml instead and reading the array from $last
//This function won't show PHP Erros when xml is set to true
set_time_limit(20);
$last=&$this->last;
$fp=&$this->fp;
$this->Txml=&$xml;
if(!$addr&&!$this->addr) $this->erro("Called ".__CLASS__."::open() without setting an address.",true);
if(!$addr&&$this->addr) $addr=$this->addr;
elseif($addr&&!$this->addr) $this->addr=$addr;
if(preg_match('/^.*\:[0-9]+$/',$addr)){
$port=substr(strrchr($addr,":"),1);
$this->port=$port;
$addr=preg_replace('/^(.*):[0-9]+$/','\1',$addr);
$this->addr=$addr;
}
elseif(!$port&&$this->port) $port=$this->port;
elseif($port&&!$this->port) $this->port=$port;
else{
$port=7777;
$this->port=$port;
}
if(preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/',$addr)){
if($this->getHost){
$host=getHostByAddr($addr);
if($host==getHostByName($host)) $host=$addr;
}
else{
$host="ignored";
}
$ip=$addr;
}
else{
if($this->getHost) $ip=getHostByName($addr);
else $ip=$addr;
$host=$addr;
}
if($xml===null) $xml=$this->xml;
if($xml){
@header("Content-Type: application/xml");
$this->ini=@ini_get('display_errors');
@ini_set('display_errors','0');
}
if($this->give==2){
ob_start();
if($xml===true) $xml=2;
else $xml=1;
}
if($xml) echo "<"."?xml version='1.0' encoding='iso-8859-1'?"."><server>";
$fp = @fsockopen('udp://' . $ip, $port, $errno, $errstr,3) or $this->erro($errstr,__LINE__,__FILE__,$errno);
if($fp){
$packet = 'SAMP';
$packet .= chr(strtok($ip, '.'));
$packet .= chr(strtok('.'));
$packet .= chr(strtok('.'));
$packet .= chr(strtok('.'));
$packet .= chr($port & 0xFF);
$packet .= chr($port >> 8 & 0xFF);
fwrite($fp, $packet.'i');
stream_set_timeout($fp,10);
fread($fp, 11);
$conInfo=stream_get_meta_data($fp);
if($conInfo['timed_out']){
$this->erro("Connection timed out!");
}
else{
$is_passworded = ord(fread($fp, 1));
$plr_count = ord(fread($fp, 2));
$max_plrs = ord(fread($fp, 2));
$strlen = ord(fread($fp, 4));
$hostname = fread($fp, $strlen);
$strlen = ord(fread($fp, 4));
$gamemode = fread($fp, $strlen);
$strlen = ord(fread($fp, 4));
$mapname = fread($fp, $strlen);
$last['server']['ip']=$ip;
$last['server']['host']=$host;
$last['server']['hostname']=$hostname;
$last['server']['mode']=$gamemode;
$last['server']['mapa']=$mapname;
$last['server']['passworded']=(bool)$is_passworded;
$last['server']['players']['atual']=$plr_count;
$last['server']['players']['maximo']=$max_plrs;
if(!preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/',$ip)) $ip="ignored";
if($xml){
echo '<hostname>' . htmlentities($hostname) . '</hostname>';
echo '<ip>' . $ip.($ip!='ignored'?":$port":'') . "</ip>";
echo '<host>'. $host.($host!='ignored'?":$port":'') . '</host>';
echo '<mode>' . htmlentities($gamemode) . '</mode>';
echo '<mapa>' . htmlentities($mapname) . '</mapa>';
echo '<passworded>';
if ($is_passworded){
echo 'yes';
} else {
echo 'no';
}
echo '</passworded>';
echo '<players><atual>' . htmlentities($plr_count) . '</atual><max>' . htmlentities($max_plrs) . '</max>';
}
fwrite($fp, $packet.'c');
fread($fp, 11);
$plr_count = ord(fread($fp, 2));
if($xml) echo '<lista>';
if ($plr_count > 0)
{
for ($i=0; $i<$plr_count; $i++)
{
$strlen = ord(fread($fp, 1));
$plrname = fread($fp, $strlen);
$score = $this->samp_getLong(fread($fp, 4));
$last['server']['players']['lista'][$i]['nick']=$plrname;
$last['server']['players']['lista'][$i]['score']=$score;
if($xml) echo '<player><nick>' . htmlentities($plrname) . '</nick><score>' . htmlentities($score) . '</score></player>';
}
}
if($xml) echo '</lista></players>';
}
fclose($fp);
}
if($xml) echo "</server>";
if($xml){
@ini_set("display_errors",$this->ini);
$this->ini="";
}
if($xml===1){
$ret=ob_get_contents();
ob_end_clean();
$this->Txml=false;
return $ret;
}
elseif($xml===2){
$ret=ob_get_contents();
ob_end_flush();
$this->Txml=false;
return $ret;
}
$this->Txml=false;
return $last;
}
//This function does the read function print an XML File when called
function xml(){
$this->xml=true;
}
//This does the inverse of xml()
function notXml(){
$this->xml=false;
}
//This function does the read function return an array
function returnArray(){
$this->give=1;
}
//This function does the read function return an XML File
function returnXml(){
$this->give=2;
}
//This function does the read function trys to get IP/Host address (may be slow)
function getHost(){
$this->getHost=true;
}
//This function does the read function just get the information without trying to get the IP/Host Address
function notGetHost(){
$this->getHost=false;
}
//Private functions
private function erro($string,$line=null,$file=null,$number=null,$die=false){
if($line===true){
$line=null;
$die=true;
}
if($this->Txml) echo "<erros><fatal>Socket Error: ".htmlentities($string).($number!==null?" (#".htmlentities($number).")":'').($file?" in $file":'').($line?" on line $line":'')."</fatal></erros>";
else echo "<br/>\r\n<b>Socket Error:</b> ".htmlentities($string).($number!==null?" (#".htmlentities($number).")":'').($file?" in <b>$file</b>":'').($line?" on line <b>$line</b>":'')."<br/>\r\n";
if($die) die();
}
private function samp_getLong($dat) {
$num=0;
if((ord(substr($dat,3,1)) & 128) > 0) {
for ($i=0; $i<strlen($dat); $i++) {
$num-=((255-ord(substr($dat,$i,1))) << 8*$i);
}
$num--;
}
else {
for ($i=0; $i<strlen($dat); $i++) {
$num+=(ord(substr($dat,$i,1)) << 8*$i);
}
}
return $num;
}
}
//Exemples:
/*
$samp=new SAMP_Socket;
$info=$samp->read("66.197.126.19:7777");
@header("Content-Type: text/plain");
print_r($info);
*/ /*
$samp=new SAMP_Socket;
$info=$samp->read("66.197.126.19",7777,true);
*/ /*
$samp=new SAMP_Socket;
$samp->xml();
$samp->read("66.197.126.19",7777);
*/ /*
$samp=new SAMP_Socket;
$samp->xml();
$samp->getHost();
$samp->read("66.197.126.19");
*/ /*
$samp=new SAMP_Socket;
$samp->addr="66.197.126.19";
$samp->port=7777;
$samp->xml();
$samp->read();
*/ /*
$samp=new SAMP_Socket;
$samp->returnXml();
$xml=$samp->read("66.197.126.19:7777");
echo
"<html><head><title>Exemple -- SAMP Socket</title></head>
<body style='text-align: center;'><form><textarea rows='10' cols='100'>$xml</textarea>
</form></body></html>"
*/
?>
|