/[svn]/web/madquery.php
ViewVC logotype

Contents of /web/madquery.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 19 - (show annotations) (download)
Sun Sep 21 02:27:07 2008 UTC (15 years, 6 months ago) by cstrike
File size: 17153 byte(s)
madquery.php from http://wiki.joe.to/index.php/MadQuery_Script
1 <?php
2
3 /***************************************************
4 * Copyright (C) 2002 madCoder *
5 * http://www.utdallas.edu/~madcoder/ *
6 * COMMENTS (NO support requests)may be sent to: *
7 * madCoder@student.utdallas.edu *
8 ***************************************************
9 * Use of this class assumes agreement to all *
10 * of the following terms of use: *
11 ***************************************************
12 * 1) This class is provided as-is, with no *
13 * offering of technical support, or help *
14 * in any way with setting up this class. *
15 * 2) madCoder will not, in any way, take *
16 * responsibility for what you do with this *
17 * script. *
18 * 3) This class may not be reproduced, or *
19 * altered, without prior authoriazation from *
20 * madCoder. *
21 * 4) ALL Copyright and credit notices MUST remain *
22 * intact, as released. *
23 ***************************************************/
24
25
26 define("ERROR_NOERROR" ,0);
27 define("ERROR_NOSERVER",-1);
28 define("ERROR_INSOCKET",-2);
29 //define("DEBUG",1);
30 define("OLDQUERIES",0);
31
32 function get_float32($fourchars) {
33 $bin='';
34 for($loop = 0; $loop <= 3; $loop++) {
35 $bin = str_pad(decbin(ord(substr($fourchars, $loop, 1))), 8, '0', STR_PAD_LEFT).$bin;
36 }
37 $exponent = bindec(substr($bin, 1, 8));
38 $exponent = ($exponent)? $exponent - 127 : $exponent;
39 if($exponent) {
40 $int = bindec('1'.substr($bin, 9, $exponent));
41 $dec = bindec(substr($bin, 9 + $exponent));
42 $time = "$int.$dec";
43 return number_format($time / 60, 2);
44 } else {
45 return 0.0;
46 }
47 }
48
49 /******
50 * getmicrotime()
51 * as provided in the PHP manual
52 ******/
53 function getmicrotime(){
54 list($usec, $sec) = explode(" ",microtime());
55 return ((float)$usec + (float)$sec);
56 }
57
58 function dodebug($dbgstr="") {
59 if(defined('DEBUG')) echo "<!-- [DEBUG] " . $dbgstr . " -->\n";
60 }
61 /***********************************************
62 * madQuery Class
63 ***********************************************/
64 class madQuery {
65 var $_arr=array();
66 var $_ip="";
67 var $_port=0;
68 var $_isconnected=0;
69 var $_players=array();
70 var $_rules=array();
71 var $_errorcode=ERROR_NOERROR;
72 var $_seed="madQuery for server (%s:%d)";
73 var $_sk; //socket
74 var $_challengenum;
75 var $_type;
76
77 //Constructor
78 function madQuery($serverip, $serverport=27015)
79 {
80 $this->_ip=$serverip;
81 $this->_port=$serverport;
82 $this->_seed="\x0a\x3c\x21\x2d\x2d\x20\x20\x20\x20\x20\x20\x20\x53\x65\x72\x76\x65\x72\x20\x6d\x61\x64\x51\x75\x65\x72\x79\x20\x43"
83 ."\x6c\x61\x73\x73\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x3e\x0a\x3c\x21\x2d\x2d\x20\x20\x20\x20\x43\x6f\x70\x79\x72\x69"
84 ."\x67\x68\x74\x20\x28\x43\x29\x20\x32\x30\x30\x32\x20\x6d\x61\x64\x43\x6f\x64\x65\x72\x20\x20\x20\x20\x2d\x2d\x3e\x0a"
85 ."\x3c\x21\x2d\x2d\x20\x20\x20\x6d\x61\x64\x63\x6f\x64\x65\x72\x40\x73\x74\x75\x64\x65\x6e\x74\x2e\x75\x74\x64\x61\x6c"
86 ."\x6c\x61\x73\x2e\x65\x64\x75\x20\x20\x20\x2d\x2d\x3e\x0a\x3c\x21\x2d\x2d\x20\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77"
87 ."\x2e\x75\x74\x64\x61\x6c\x6c\x61\x73\x2e\x65\x64\x75\x2f\x7e\x6d\x61\x64\x63\x6f\x64\x65\x72\x20\x2d\x2d\x3e\x0a\x0a";
88 $this->_arr=array_pad($this->_arr, 22, 0);
89 $errno=0;$errstr='';
90 $this->_sk = fsockopen("udp://" . $this->_ip, $this->_port, $errno, $errstr, 3);
91 socket_set_timeout($this->_sk, 2,0);
92 if($tmp=$this->_sockstate()) {
93 //echo $tmp;
94 if(!$this->_sk)
95 echo "ERROR #" .$errno.": ".$errstr;
96 //exit;
97 }
98 if (!OLDQUERIES) {
99 $this->_send("\xFF\xFF\xFF\xFF\x57"); //get challenge
100 $tmp=$this->_getmore();
101 $this->_challengenum=substr($tmp, 5, 4);
102 }
103 dodebug("[Initialized]");
104 // $this->_brand_seed();
105 return !(!$this->_sk);
106 }
107
108 //Sets error code
109 function seterror($code) {
110 dodebug("[Setting Error Code (".$code.")]<BR>\n");
111 $this->_errorcode=$code;
112 }
113
114 //Obtains ping value to server
115 function _ping()
116 {
117 dodebug("[Getting Ping]");
118 if($tmp=$this->_sockstate()){
119 //echo $tmp;
120 dodebug("[Error in Socket]");
121 $this->seterror(ERROR_INSOCKET);
122 return -1; //Error in socket
123 } else {
124 $tmp="";
125 $start = getmicrotime()*1000;
126 if (OLDQUERIES) $this->_send("ÿÿÿÿping".chr(0));
127 else $this->_send("ÿÿÿÿi".chr(0));
128 while(strlen($tmp)<4 && (getmicrotime()*1000-$start)<1000) {
129 $tmp=$this->_getmore();
130 }
131 if(strlen($tmp)>=4 && substr($tmp,4,1)=='j') {
132 $end=getmicrotime()*1000;
133 if($end<$start) echo $end .'\n'.$start;
134 return ($end-$start); //($end-$start)>=0 ? ($end-$start) : -1; //Will be numeric ping
135 } else {
136 //echo "Server didn't respond!";
137 //exit;
138 $this->seterror(ERROR_NOSERVER);
139 dodebug("[ERROR: No pong from server]");
140 return -1; //Server isn't responding...
141 }
142 }
143 return 0;
144 }
145
146 //Populates details array
147 function getdetails()
148 {
149 dodebug("[Getting Details]");
150 if($tmp=$this->_sockstate()) {
151 //echo $tmp;
152 $this->seterror(ERROR_INSOCKET);
153 return -1;
154 } else {
155 if (OLDQUERIES) $this->_send("ÿÿÿÿdetails".chr(0));
156 else $this->_send("\xFF\xFF\xFF\xFF\x54Source Engine Query\x00");
157 $buffer=$this->_getmore();
158 /*echo $buffer;
159 for ($i=0; $i < strlen($buffer); $i++) {
160 echo '['.substr($buffer,$i,1).'='.ord(substr($buffer,$i,1)).'] ';
161 }
162 exit;*/
163 $tmp=substr($buffer,0,5);
164 $this->_type=substr($tmp,4,1);
165 $buffer=substr($buffer,5);
166 $text="";
167 $count=0;
168 $arr=array();
169 if ($this->_type == "\x6D" || OLDQUERIES ) {
170 do {
171 $tmp=substr($buffer,0,1);$buffer=substr($buffer,1);
172 if (!ord($tmp)) { $this->_arr[$count++]=$text; $text=""; }
173 else { $text.=$tmp; }
174 } while ($count<5);
175 for($i=0;$i<=6;$i++, $count++) {
176 $tmp=substr($buffer,0,1);$buffer=substr($buffer,1);
177 if($count==8 || $count==9)
178 $this->_arr[$count]=$tmp;
179 else
180 $this->_arr[$count]=ord($tmp);
181 } //count = 12
182 if($this->_arr[$count-1]) { //if ismod
183 do {
184 $tmp=substr($buffer,0,1);$buffer=substr($buffer,1);
185 $this->_arr[$count]="";
186 if (ord($tmp)!=0)
187 $this->_arr[$count].=$tmp; // mod website [12]
188 } while(ord($tmp)!=0);
189 $count++;
190 do {
191 $tmp=substr($buffer,0,1);$buffer=substr($buffer,1);
192 $this->_arr[$count]="";
193 if (ord($tmp)!=0)
194 $this->_arr[$count].=$tmp; // mod FTP [13]
195 } while(ord($tmp)!=0);
196 $count++; //[14]==Not Used
197 $this->_arr[$count++]=ord(substr($buffer,0,1)); $buffer=substr($buffer,1);
198 $tmp=substr($buffer,0,4);$buffer=substr($buffer,4);
199 for($j=0;$j<4;$j++) {
200 $this->_arr[$count]+=(pow(256,$j) * ord(substr($tmp,$j,1))); //Ver [15]
201 } $count++;
202 $tmp=substr($buffer,0,4);$buffer=substr($buffer,4);
203 for($j=0;$j<4;$j++) {
204 $this->_arr[$count]+=(pow(256,$j) * ord(substr($tmp,$j,1))); //Size [16]
205 } $count++;
206 $this->_arr[$count++]=ord(substr($buffer,0,1));$buffer=substr($buffer,1); //server-only [17]
207 $this->_arr[$count++]=ord(substr($buffer,0,1));$buffer=substr($buffer,1); //custom client.dll [18]
208 $this->_arr[$count++]=ord(substr($buffer,0,1));$buffer=substr($buffer,1); //Secure! [19]
209 $this->_arr[$count++]=ord(substr($buffer,0,1));$buffer=substr($buffer,1); //Num of bots [20]
210 } else {
211 for($i=0;$i<8;$i++)
212 $this->_arr[$count++]="\0";
213 }
214 } elseif ($this->_type == "\x49") {
215 $tmp=substr($buffer,0,1);$buffer=substr($buffer,1);
216 $this->_arr[$count++] = $tmp;
217 do {
218 $tmp=substr($buffer,0,1);$buffer=substr($buffer,1);
219 if (!ord($tmp)) { $this->_arr[$count++]=$text; $text=""; }
220 else { $text.=$tmp; }
221 } while ($count<5);
222 $tmp_lower = substr($buffer, 0, 1);
223 $tmp_higher = substr($buffer, 1, 1);
224 $buffer=substr($buffer,2);
225 $this->_arr[$count++] = ($tmp_higher << 8) | $tmp_lower;
226 for($i=0;$i<=6;$i++, $count++) {
227 $tmp=substr($buffer,0,1);$buffer=substr($buffer,1);
228 if($count==9 || $count==10)
229 $this->_arr[$count]=$tmp;
230 else
231 $this->_arr[$count]=ord($tmp);
232 } //count = 13
233 }
234 }
235 $this->_arr[$count]=round($this->_ping(),1);
236 //print_r($this->_arr);
237 return 0;
238 }
239
240 // Sets players array
241 function getplayers()
242 {
243 dodebug("[Getting Players]");
244 //$fp = fsockopen("udp://" . $this->_ip, $this->_port);
245 if($tmp=$this->_sockstate()) {
246 //echo $tmp;
247 $this->seterror(ERROR_INSOCKET);
248 return -1;
249 } else {
250 if (OLDQUERIES) $this->_send("ÿÿÿÿplayers".chr(0));
251 else $this->_send("\xFF\xFF\xFF\xFF\x55".$this->_challengenum);
252 $buffer=$this->_getmore();
253 $buffer=substr($buffer,5);
254 $count=ord(substr($buffer,0,1)); //Num active players
255 $buffer=substr($buffer,1);
256 $tfrags="";
257 $ttime=0;
258 $arr=array();
259 for($i=0;$i<$count;$i++)
260 {
261 $rfrags=0.0;
262 $rtime=0;
263 $stime=0;
264 $tind=ord(substr($buffer,0,1));
265 $buffer=substr($buffer,1);
266 $tname="";
267 do {
268 $tmp=substr($buffer,0,1);
269 $buffer=substr($buffer,1);
270 if(ord($tmp)!=0) $tname.=$tmp;
271 }while(ord($tmp)!=0);
272 $tfrags=substr($buffer,0,4);
273 $buffer=substr($buffer,4);
274 for($j=0;$j<4;$j++) {
275 $rfrags+=(pow(256,$j) * ord(substr($tfrags,$j,1)));
276 }
277 if($rfrags > 2147483648) {
278 $rfrags-=4294967296;
279 }
280 $tmp=substr($buffer,0,4);
281 $buffer=substr($buffer,4);
282 $rtime=get_float32($tmp);
283 $arr[$i]=array("Index" => $tind,"Name" => $tname,"Frags" => $rfrags, "Time" => $rtime);
284 }
285 }
286 $this->_players=$arr;
287 return 0;
288 }
289
290 function getrules() {
291 dodebug("[Getting Rules]");
292 $multi=0;
293 //$cvars=array();
294 if($tmp=$this->_sockstate()) {
295 $this->seterror(ERROR_INSOCKET);
296 return -1;
297 }
298 if (OLDQUERIES) $this->_send("ÿÿÿÿrules".chr(0));
299 else $this->_send("\xFF\xFF\xFF\xFF\x56".$this->_challengenum);
300 $buffer=$this->_getmore();
301 if(strlen($buffer)==0) $buffer=$this->_getmore();
302 $tmp=substr($buffer,0,5);
303 $buffer=substr($buffer,5);
304 if(substr($tmp,0,4)==chr(254).chr(255).chr(255).chr(255)) {
305 //Now, 5 more bytes to look at..
306 $multi=1;
307 for($ti=0;$ti<4;$ti++) {
308 $tmp=substr($buffer,0,1);
309 $buffer=substr($buffer,1);
310 }
311 $tmp=substr($buffer,0,5); //yyyyE = Rules Response
312 $buffer=substr($buffer,5);
313 }
314 $count=ord(substr($buffer,0,1));$buffer=substr($buffer,2); //Num rules
315 $i=0;
316 $svar="";
317 while($i<$count) {
318 if(strlen($buffer)==0 && $multi==1) {
319 $buffer=$this->_getmore();
320 $tmp=substr($buffer,0,5); //pyyy_
321 $buffer=substr($buffer,5);
322 $buffer=substr($buffer,4);
323 }
324 $tmp=substr($buffer,0,1);
325 $buffer=substr($buffer,1);
326 if(ord($tmp)==0)
327 $i+=0.5;
328 $svar=$svar.$tmp;
329 }
330 $vars=explode(chr(0),$svar);
331 for($i=0;$i<(int)(count($vars))-1;$i+=2) {
332 $cvars[$vars[$i]]=$vars[$i+1];
333 }
334 if(sizeof($cvars)>0) ksort($cvars);
335 $this->_rules=$cvars;
336 return 0;
337 }
338
339 function _sockstate() {
340 if(!$this->_sk)
341 return 8;
342 $stat=socket_get_status($this->_sk);
343 $ret=0;
344 if($stat["timed_out"]) {
345 //echo "ERROR: Socket timed out.<BR>\n";
346 $ret|=1;
347 }
348 if($stat["eof"]) {
349 //echo "ERROR: Socket closed by remote host.<BR>\n";
350 $ret|=2;
351 }
352 if($stat["blocked"]) {
353 //echo "PORT BLOCKED!";
354 //exit;
355 //$ret|=4;
356 }
357 return $ret;
358 //return (!$stat["timed_out"] && !$stat["eof"] && !(!$this->_sk));
359 }
360
361 function _send($outstr) {
362 if(!$this->_sockstate()) {
363 fwrite($this->_sk,$outstr,strlen($outstr));
364 } else
365 return "\0";
366 }
367
368 function _getmore() {
369 if(!$this->_sockstate()) {
370 $tmp=fread($this->_sk,1);
371 $stat=socket_get_status($this->_sk);
372 $tmp.=fread($this->_sk, $stat["unread_bytes"]);
373 return $tmp;
374 } else
375 return "\0";
376 }
377
378 function _brand_seed() {
379 /*************************************************************************************************************************
380 * Do not edit this function!*//*print(* /$this->_seed/*//*);//*print($this->_seed/*);*//**/print(/**/$this->_seed /**/);/*
381 *************************************************************************************************************************/
382 $this->_seed="\x0a\x3c\x21\x2d\x2d\x20\x20\x20\x20\x20\x20\x20\x53\x65\x72\x76\x65\x72\x20\x6d\x61\x64\x51\x75\x65\x72\x79\x20\x43"
383 ."\x6c\x61\x73\x73\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x3e\x0a\x3c\x21\x2d\x2d\x20\x20\x20\x20\x43\x6f\x70\x79\x72\x69"
384 ."\x67\x68\x74\x20\x28\x43\x29\x20\x32\x30\x30\x32\x20\x6d\x61\x64\x43\x6f\x64\x65\x72\x20\x20\x20\x20\x2d\x2d\x3e\x0a"
385 ."\x3c\x21\x2d\x2d\x20\x20\x20\x6d\x61\x64\x63\x6f\x64\x65\x72\x40\x73\x74\x75\x64\x65\x6e\x74\x2e\x75\x74\x64\x61\x6c"
386 ."\x6c\x61\x73\x2e\x65\x64\x75\x20\x20\x20\x2d\x2d\x3e\x0a\x3c\x21\x2d\x2d\x20\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77"
387 ."\x2e\x75\x74\x64\x61\x6c\x6c\x61\x73\x2e\x65\x64\x75\x2f\x7e\x6d\x61\x64\x63\x6f\x64\x65\x72\x20\x2d\x2d\x3e\x0a\x0a";
388 // print($this->_seed);
389 }
390
391 //Returns current errorcode
392 function geterror() {
393 return $this->_errorcode;
394 }
395
396 function isup()
397 /************************************
398 * int isup(char * ip, long port);
399 * Return values:
400 * 0 = No response - probably down
401 * 1 = HL Responded - Server is up
402 * -1 = Error in socket
403 ************************************/
404 {
405 if($ret=$this->_sockstate()) {
406 //echo $ret;
407 return -1;
408 } else {
409 if($ret & 2) {
410 return 0;
411 }
412 $myping=$this->_ping();
413 if($myping>0)
414 return $myping;
415 else
416 return 0;
417 }
418 }
419
420 function JoinLink(){
421 if ($this->_type == "\x6D"){
422 return "'steam: \" -applaunch 70 ".($this->mModName()?'-game '.$this->mModName():'')." +connect ".$this->_ip.($this->_ip?':'.$this->_port:27015)." ;\"'";
423 } elseif ($this->_type == "\x49"){
424 return "'steam: \" -applaunch ".$this->mAppID()." +connect ".$this->_ip.($this->_ip?':'.$this->_port:27015)." ;\"'";
425 }
426 }
427
428 function mAddress (){if($this->_type == "\x6D")return $this->_arr[ 0]; elseif($this->_type == "\x49") return '';}
429 function mHostname (){if($this->_type == "\x6D")return $this->_arr[ 1]; elseif($this->_type == "\x49") return $this->_arr[ 1];}
430 function mMap (){if($this->_type == "\x6D")return $this->_arr[ 2]; elseif($this->_type == "\x49") return $this->_arr[ 2];}
431 function mModName (){if($this->_type == "\x6D")return $this->_arr[ 3]; elseif($this->_type == "\x49") return $this->_arr[ 3];}
432 function mDescr (){if($this->_type == "\x6D")return $this->_arr[ 4]; elseif($this->_type == "\x49") return $this->_arr[ 4];}
433 function mAppID (){if($this->_type == "\x6D")return ''; elseif($this->_type == "\x49") return $this->_arr[ 5];}
434 function mActive (){if($this->_type == "\x6D")return $this->_arr[ 5]; elseif($this->_type == "\x49") return $this->_arr[ 6];}
435 function mMax (){if($this->_type == "\x6D")return $this->_arr[ 6]; elseif($this->_type == "\x49") return $this->_arr[ 7];}
436 function mProtocol (){if($this->_type == "\x6D")return $this->_arr[ 7]; elseif($this->_type == "\x49") return $this->_arr[ 0];}
437 function mSvrType (){if($this->_type == "\x6D")return $this->_arr[ 8]; elseif($this->_type == "\x49") return $this->_arr[ 9];}
438 function mSvrOS (){if($this->_type == "\x6D")return $this->_arr[ 9]; elseif($this->_type == "\x49") return $this->_arr[10];}
439 function mPass (){if($this->_type == "\x6D")return $this->_arr[10]; elseif($this->_type == "\x49") return $this->_arr[11];}
440 function mIsMod (){if($this->_type == "\x6D")return $this->_arr[11]; elseif($this->_type == "\x49") return '';}
441 function mModWeb (){if($this->_type == "\x6D")return $this->_arr[12]; elseif($this->_type == "\x49") return '';}
442 function mModFTP (){if($this->_type == "\x6D")return $this->_arr[13]; elseif($this->_type == "\x49") return '';}
443 function mNotUsed (){if($this->_type == "\x6D")return $this->_arr[14]; elseif($this->_type == "\x49") return '';}
444 function mModVer (){if($this->_type == "\x6D")return $this->_arr[15]; elseif($this->_type == "\x49") return '';}
445 function mModSize (){if($this->_type == "\x6D")return $this->_arr[16]; elseif($this->_type == "\x49") return '';}
446 function mSvrOnly (){if($this->_type == "\x6D")return $this->_arr[17]; elseif($this->_type == "\x49") return '';}
447 function mCustom (){if($this->_type == "\x6D")return $this->_arr[18]; elseif($this->_type == "\x49") return '';}
448 function mIsSecure (){if($this->_type == "\x6D")return $this->_arr[19]; elseif($this->_type == "\x49") return $this->_arr[12];}
449 function mNumBots (){if($this->_type == "\x6D")return $this->_arr[20]; elseif($this->_type == "\x49") return $this->_arr[ 8];}
450 function mPing (){if($this->_type == "\x6D")return $this->_arr[21]; elseif($this->_type == "\x49") return $this->_arr[13];}
451 function mPlayerData(){if($this->_type == "\x6D")return $this->_players; elseif($this->_type == "\x49") return $this->_players;}
452 function mRules (){if($this->_type == "\x6D")return $this->_rules ; elseif($this->_type == "\x49") return $this->_rules ;}
453
454 };
455
456 /*
457 $myserver=new madQuery("63.99.222.178",27015);
458 $myserver->getdetails();
459 $myserver->getplayers();
460 echo $myserver->mHostname().": ".$myserver->mActive()." / ".$myserver->mMax();
461 echo "Server is ".($myserver->mIsSecure() ? "" : "NOT ")."secure!\n";
462 */
463 ?>

Contact webmaster
ViewVC Help
Powered by ViewVC RSS 2.0 feed