Просмотр файла v0.01a/icqlib.php

Размер файла: 36.35Kb
<? 
// Wapmess, originally developed by Gцran (depeh) Johansson, Sweden
//
// Feel free to improve this program in any way you can, but please share your version!
// More info and the latest version is avaiable at:
// http://sourceforge.net/projects/wapmess/

require_once("config.php");
require_once("rtfclass.php");


function icqimage2smiley($data)
{
	$sea  = array ('&lt;##icqimage0000&gt;',
								 '&lt;##icqimage0001&gt;',
								 '&lt;##icqimage0002&gt;',
								 '&lt;##icqimage0003&gt;',
								 '&lt;##icqimage0004&gt;',
								 '&lt;##icqimage0005&gt;',
								 '&lt;##icqimage0006&gt;',
								 '&lt;##icqimage0007&gt;',
								 '&lt;##icqimage0008&gt;',
								 '&lt;##icqimage0009&gt;',
								 '&lt;##icqimage000a&gt;',
								 '&lt;##icqimage000b&gt;',
								 '&lt;##icqimage000c&gt;',
								 '&lt;##icqimage000d&gt;',
								 '&lt;##icqimage000e&gt;',
								 '&lt;##icqimage000f&gt;'); 
								
//:-):-O:-|:-/:-(:-{}:*):'-(;-):-@:-<:-X:-P8-)O-):-D				

				

	$repl = array (":)",
								 ":o",
								 ":|",
								 ":/",
								 ":(",
								 ":*",
								 ":}",
								 ";(",
								 ";)",
								 ">:o",
								 ":C",
								 ":X",
								 ":p",
								 "8)",
								 "0:)",
								 ":D");
								 
	return str_replace($sea,$repl,$data);
}

function rtf2txt($data)
{
	$sea  = array ("\'e5","\'e4","\'f6","\'c5","\'c4","\'d6"); 
	$repl = array ("е","д","ц","Е","Д","Ц");
	
	if (substr($data,2,4)=="rtf1")
		{
			$data=str_replace($sea,$repl,$data);
			$r = new rtf($data);
			$r->output("html");
			$r->parse();
			$data=$r->out;
			$data=strip_tags($data);
	
		}
		
	return $data;
}

function wml_header()
{
header("Content-type: text/vnd.wap.wml");  
}

function xml_header()
{
print "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>";  
print "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\">"; 
}

function no_cache_header()
{
#header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
#header("Last-Modified: DD. month YYYY HH:MM:SS GMT");
#header("Cache-Control: no-cache, must-revalidate");
#header("Pragma: no-cache");
}

function send_status_list($uin_status)
{
global $my_uin;

if (count($uin_status)==0)
	{
		return;
	}
$status_str="";
foreach ($uin_status as $key => $value)
	{
		$status_str.="$key=$value,";
	}
	$status_str=substr($status_str,0,-1);

	$query="SELECT uin FROM uinstatus WHERE uin='".$my_uin."'";
	if ($debug)print "sql = $query\n";
	
	$sqlres=mysql_query($query) or die("send_status Invalid query: " . mysql_error());
	$num_rows = mysql_num_rows($sqlres);
	
	if ($num_rows>0)
		{
			$query="UPDATE uinstatus SET statusstr='".$status_str."' WHERE uin=".$my_uin."";
			$updres=mysql_query($query) or die("send_status Invalid query: " . mysql_error());
		}
	else
		{
			$query="INSERT INTO uinstatus (uin,statusstr) VALUES ('".$my_uin."','".$status_str."')";
			$insres=mysql_query($query) or die("send_status Invalid query: " . mysql_error());
		}
}

function send_data($fp,$datastr)
{
	// Skicka request
	if (fwrite($fp, $datastr, strlen($datastr)))
		{
			return $datastr;
		}
	else
		{
			return "CANT SEND ERROR!";
		}
}

function recieve_data($fp)
{
	// Ta emot request
	$str="";
	$data_empty=1;
	
	while ($data_empty==1)
		{
   		$str = fread($fp,32767);
   		//print $data;

			if ($str!="")
				{
					#print "rec datalen:".strlen($str)."\n";
					$data_empty=0;
				}
					//$data_empty=0;
					
		}
		
	return $str;	
}

function parse_srv_cookie($str)
{

$srv_cookie_a = Array();	

$ps=0;

$uin_len=bsubword2d($str,ps+8);
$srv_cookie_a["uin"]=substr($str,ps+10,$uin_len);

$ps+=6+4+$uin_len;

$ip_len=bsubword2d($str,$ps+2);
$ip_addr=substr($str,$ps+4,$ip_len);

//print "substr =".$ip_addr."=\n";

// Om vi fеr ett http:// - svar sе har fцrmodligen nеgot gеtt fel
if (substr(($ip_addr),0,7) == "http://")
	{
		$srv_cookie_a["ip"]=$ip_addr;
		$srv_cookie_a["port"]="";
	}
else
	{
		$ip_split=split(":",$ip_addr,2);

		$srv_cookie_a["ip"]=$ip_split[0];
		$srv_cookie_a["port"]=$ip_split[1];
	}

//print "ip ".$ip."\n";

$ps+=4+$ip_len;

$cookie_len=bsubword2d($str,$ps+2);
$srv_cookie_a["cookie"]=substr($str,$ps+4,$cookie_len);

//print "cookie ".b2rh($cookie)."\n";

return $srv_cookie_a;
}

function is_disconnect($str)
{
$ps=0;

if (ord($str[$ps+0])==42 && // Flap header
				ord($str[$ps+1])==4 && // Channel 4
				ord($str[$ps+7])==9 && // SNAC ($9,$2)
				ord($str[$ps+9])==2)
					{
						return ord($str[$ps+11]);
					}
				else
					{
						return false;
					}
					
}

function is_msgs($str)
{
$ps=0;
		if ((ord($str[$ps+0])==42 && // Flap header
				ord($str[$ps+1])==2 && // Channel 2
				ord($str[$ps+7])==21 && // SNAC
				ord($str[$ps+9])==3) // $15,$3
				||
		    (ord($str[$ps+0])==42 && // Flap header
				ord($str[$ps+1])==2 && // Channel 2
				ord($str[$ps+7])==4 && // SNAC
				ord($str[$ps+9])==7))  // 
					{
						return true;
					}
			else
				{
					return false;
				}
}

function parse_msgs($str)
{
global $my_uin,$debug,$fp,$cli_seq;
#print "parse_msgs \n";

$msgs_a = Array();	

$mcount=0;
$ps=0;

$str_len=strlen($str);

#print "str_len=$str_len \n";

while ($ps<$str_len)
	{
		$flap_len=bsubword2d($str,$ps+4)+6;
		#print "flap_len=$flap_len \n";
		
		// Kolla att flap'en дr ett offline-server-mess
		if (ord($str[$ps+0])==42 && // Flap header
				ord($str[$ps+1])==2 && // Channel 2
				ord($str[$ps+7])==21 && // SNAC
				ord($str[$ps+9])==3 && // $15,$3
				ord($str[$ps+11])==1)  // Tror det betyder att meddelande finns.
					{
						#print "FLAP:".b2rh(substr($str,$ps,$flap_len))."\n\n";
						$from_uin=bsubdwordflip2d($str,$ps+30);
						$from_year=bsubwordflip2d($str,$ps+34);
						
						$from_month=sprintf("%02d",ord($str[$ps+36]));
						$from_day=sprintf("%02d",ord($str[$ps+37]));
						$from_hour=sprintf("%02d",ord($str[$ps+38]));
						$from_minute=sprintf("%02d",ord($str[$ps+39]));
						
						$msg_type=bsubwordflip2d($str,$ps+40);
						$msg_len=bsubwordflip2d($str,$ps+42)-1;
						$msg_text=substr($str,$ps+44,$msg_len);
						
						$msg_text=icqimage2smiley($msg_text);
						
						// Meddelandet дr tomt, avbryt
						if (trim($msg_text)=="")break;
						
						$when="$from_year-$from_month-$from_day $from_hour:$from_minute";
						if ($debug)print "OFFLINE-MSG:\nfrom: $from_uin\n";
						if ($debug)print "time: $when\n";
						if ($debug)print "mess: $msg_text\n\n";
						
													
						/*					
						$msgs_a[$mcount]["from"]=$from_uin;
						$msgs_a[$mcount]["time"]=$when;
						$msgs_a[$mcount]["msg"]=$msg_text;
						*/

						// (fromuin,touin,msg,when)
						$query = "INSERT INTO incoming ( `id` , `fromuin` , `touin` , `msg` , `msgtime` , `online` ) VALUES (0,'".$from_uin."','".$my_uin."','".$msg_text."','".$when."',0)";
						if ($debug)print "sql=$query\n";
						mysql_query($query);
						
						$mcount++;
					}

		// Kolla om flap'en дr ett offline-mess READY mess
		if (ord($str[$ps+0])==42 && // Flap header
				ord($str[$ps+1])==2 && // Channel 2
				ord($str[$ps+7])==21 && // SNAC
				ord($str[$ps+9])==3 && // $15,$3,$0,$1
				ord($str[$ps+11])==0 && //
				ord($str[$ps+13])==1)  // Tror det betyder att meddelande finns.
					{
						if ($debug)print "OFFLINE-READY!\n";

						cli_sendoffline_ack();						

					}

		// Kolla om flap'en дr ett SRV-ROOSTER meddelande
		if (ord($str[$ps+0])==42 && // Flap header
				ord($str[$ps+1])==2 && // Channel 2
				ord($str[$ps+7])==19 && // SNAC
				ord($str[$ps+9])==6) // $13,$6
					{
						if ($debug)print "SRV-ROOSTER!\n";
						
						$query="DELETE FROM contactlist WHERE uin='".$my_uin."'";
		   			$delres=mysql_query($query);
					
						
						$tps=$ps;
						
						// Flytta pekaren 17 steg framеt
						$tps+=17;
						$num_items=bsubword2d($str,$tps);
						if ($debug)print "num items=".$num_items."\n";
						
						// Flytta pekaren 9 steg framеt
						$tps+=9;
						if ($debug)print "roster type=".ord($str[$tps])."\n";		
						
						// Kolla lдngden pе nдstfцljande TLV
						$tlv_len=bsubword2d($str,$tps+1);
						
						if ($debug)print "TLV =".dechex(bsubword2d($str,$tps+3))."\n";
						
						// Rдkna ut hur mеnga olika grupper vi har
						$roster_groups=$tlv_len/2-2;
						if ($debug)print "roster_groups=".$roster_groups."\n";
						
						// Hдmta upp roster idn
						for ($i=0;$i<$roster_groups;$i++)
							{
								$roster_id[$i]=bsubword2d($str,$tps+7+2*$i);
								if ($debug)print "roster_id $i =".dechex($roster_id[$i])."\n";
							}
						
						
						// Flytta pekaren fцrbi tlvn
						$tps+=$tlv_len+3;
						
						/*
						if ($roster_groups>1)
							{
								$tps+=6;
									
								if(bsubword2d($str,$tps)==4)
									{
										$tps+=bsubword2d($str,$tps+2)+4;
										$tps+=bsubword2d($str,$tps)+6;
									}

								if(bsubword2d($str,$tps)==9)
									{
										$tps+=bsubword2d($str,$tps+2)+4;
									}
								
							}
							
							
							$groupname_len=bsubword2d($str,$tps);
							if ($debug)print "groupname_len=".$groupname_len."\n";
							
							// Flytta pekaren fцrbi gruppnamnet
							$tps+=$groupname_len+8;
							*/
							
							// Flytta pekaren tills man stцter pе 00 00 00 01
							while (!(bsubword2d($str,$tps)==0 && bsubword2d($str,$tps+2)==1 && bsubword2d($str,$tps+6)==200))
								{
									$tps+=1;
								}
								
							$tps+=4;
							
							// Kolla hur lеngt man ska gе
							$dist=bsubword2d($str,$tps);
							#print "Dist: $dist\n";
							
							#print b2rh(substr($str,$tps,16));
							
							// Flytta pekaren fцrbi grupp info fram till fцrsta UIN
							$tps+=$dist+2;


							// Gе igenom hela flapen
							while ($tps<($flap_len+$ps))
								{

									$uin=get_uinstr($str,$tps);
									
									// Om uin дr tom sе avbryter vi loopen
									if ($uin=="")break;
										
									// Flytta pekaren fцrbi uin
									$tps+=strlen($uin)+2;
		
									// Gе till nдrmaste 00 00 -word
									$tps=scan_zeroword($str,$tps);
				
									$tlv_len=bsubword2d($str,$tps+2);
		
									// tlvs lдngd дr 1 sе дr detta en grupp header?
									if ($tlv_len==1)
										{ 
											// Hдmta lдngden frеn nдsta WORD
											$tlv_len=bsubword2d($str,$tps+4);
											// Flytta pekaren fцrbi tlvn
											$tps+=$tlv_len+6;
											
											// Lдs in UIN igen
											$uin=get_uinstr($str,$tps);
		   								// Flytta pekaren fцrbi uin
				    					$tps+=strlen($uin)+2;
		
											$tps=scan_zeroword($str,$tps);
											
											$tlv_len=bsubword2d($str,$tps+2);
		
										}
		
									// Flytta pekaren fцrbi tlv-header
									$tps+=4;
									
									//Kolla efter 01 31 (Nick header)
									if (ord($str[$tps])==1 && ord($str[$tps+1])==49)
										{
											// Hдmta lдngd pе nick
											$nick_len=bsubword2d($str,$tps+2);
											#if ($debug)print "nick_len=".$nick_len."\n";
											
											$nick=utf8_decode(substr($str,$tps+4,$nick_len));
											#if ($debug)print "nick=".$nick."\n";
											
											if ($debug)print $nick." ($uin)\n";
											
											if ($nick!="")
												{
													$query = "INSERT INTO contactlist ( `id` , `uin` , `cnick` , `cuin` ) VALUES (0,'".$my_uin."','".$nick."','".$uin."')";
													if ($debug)print "sql=$query\n";
													mysql_query($query);
												}
												

										}
									
									$tps+=$tlv_len;
							
								}







						
					}

		// Kolla om flap'en дr ett ONLINE mess!
		if (ord($str[$ps+0])==42 && // Flap header
				ord($str[$ps+1])==2 && // Channel 2
				ord($str[$ps+7])==4 && // SNAC
				ord($str[$ps+9])==7 &&  // Tror det betyder att meddelande finns.
				ord($str[$ps+25])==1) // Type 1 meddelande = Gammal typ
					{
						#print "FLAP:".b2rh(substr($str,$ps,$flap_len))."\n\n";
						
						$uin_len=ord($str[$ps+26]);
						$from_uin=substr($str,$ps+27,$uin_len);

						#print "uin_len = $uin_len \n";
						#print "from_uin = $from_uin \n";
						
						// Flytta pekaren framеt tills efter UIN'en och efter 2 tomma bytes
						$tmp_ps=$ps+27+$uin_len+2;
						
						// 
						#print "tmp_ps = $tmp_ps \n";
						
						// Hдmta antalet tlver som fцljer
						$tlv_num=bsubword2d($str,$tmp_ps);
						
						#print "tlv_num = $tlv_num \n";
						
						// Flytta pekaren framеt
						$tmp_ps+=2;
						
						while ($tlv_num>0)
							{
								$tlv_id=ord($str[$tmp_ps+1]);
								
								if ($tlv_id==1)$tmp_ps+=6;
								if ($tlv_id==4)$tmp_ps+=6;
								if ($tlv_id==6)$tmp_ps+=8;
								if ($tlv_id==15)$tmp_ps+=8;
								if ($tlv_id==2)$tmp_ps+=8;
								if ($tlv_id==3)$tmp_ps+=8;
							
								#print "tlv_id = $tlv_id (".$tmp_ps.") \n";
								$tlv_num--;
							}

						#print "tmp_ps = $tmp_ps \n";
						
						// Flytta pekaren
						$stlv_len=bsubword2d($str,$tmp_ps+6);
						
						// flytta fцrbi pekare fцrbi sista tlvn
						$tmp_ps+=10+$stlv_len;
						
						#print "tmp_ps = $tmp_ps \n";
						#print "STLV_LEN = $stlv_len \n";
						
						$msg_len=bsubword2d($str,$tmp_ps)-4;
						$msg_text=substr($str,$tmp_ps+6,$msg_len);

						$when=date("Y-m-d H:i"); 
						
						if ($debug)print "ONLINE-MSG1 :\nfrom: $from_uin\n";
						if ($debug)print "time: $when\n";
						if ($debug)print "mess: (".$msg_len.") $msg_text\n\n";

						$msg_text=icqimage2smiley($msg_text);

						// Meddelandet дr tomt, avbryt
						if (trim($msg_text)=="")break;
						
						
						/*						
						$msgs_a[$mcount]["from"]=$from_uin;
						$msgs_a[$mcount]["time"]=$when;
						$msgs_a[$mcount]["msg"]=$msg_text;
						*/
						
												
						// (fromuin,touin,msg,when)
						$query = "INSERT INTO incoming ( `id` , `fromuin` , `touin` , `msg` , `msgtime` , `online` ) VALUES (0,'".$from_uin."','".$my_uin."','".$msg_text."','".$when."',1)";
						if ($debug)print "sql=$query\n";
						mysql_query($query);
						
						$mcount++;
					}
		
		// Kolla om flap'en дr ett ONLINE mess!
		if (ord($str[$ps+0])==42 && // Flap header
				ord($str[$ps+1])==2 && // Channel 2
				ord($str[$ps+7])==4 && // SNAC
				ord($str[$ps+9])==7 &&  // Tror det betyder att meddelande finns.
				ord($str[$ps+25])==2) // Type 2 meddelande = Ny typ
					{
						#print "FLAP:".b2rh(substr($str,$ps,$flap_len))."\n\n";
						
						$uin_len=ord($str[$ps+26]);
						$from_uin=substr($str,$ps+27,$uin_len);

						#print "uin_len = $uin_len \n";
						#print "from_uin = $from_uin \n";
						
						// Flytta pekaren framеt tills efter UIN'en och efter 2 tomma bytes
						$tmp_ps=$ps+27+$uin_len+2;
						
						// 
						#print "tmp_ps = $tmp_ps \n";
						
						// Hдmta antalet tlver som fцljer
						$tlv_num=bsubword2d($str,$tmp_ps);
						
						#print "tlv_num = $tlv_num \n";
						
						// Flytta pekaren framеt
						$tmp_ps+=2;
						
						while ($tlv_num>0)
							{
								$tlv_id=ord($str[$tmp_ps+1]);
								
								if ($tlv_id==1)$tmp_ps+=6;
								if ($tlv_id==4)$tmp_ps+=6;
								if ($tlv_id==6)$tmp_ps+=8;
								if ($tlv_id==15)$tmp_ps+=8;
								if ($tlv_id==2)$tmp_ps+=8;
								if ($tlv_id==3)$tmp_ps+=8;
							
								#print "tlv_id = $tlv_id (".$tmp_ps.") \n";
								$tlv_num--;
							}

						#print "tmp_ps = $tmp_ps \n";
						
						// Om det INTE дr ett meddelande..
						if (ord($str[$tmp_ps+5])!=0 || ord($str[$tmp_ps+48])!=0)
							{ // avbryt 
								break;
							}
						
						// flytta pekaren 111 steg!
						$tmp_ps+=95; // 5F
						
						print "tmp_ps = $tmp_ps \n";
						
						$msg_len=bsubwordflip2d($str,$tmp_ps)-1;
						$msg_text=substr($str,$tmp_ps+2,$msg_len);
						
						$msg_text=rtf2txt($msg_text);

						$msg_text=icqimage2smiley($msg_text);	

						// Meddelandet дr tomt, avbryt
						if (trim($msg_text)=="")break;
						
						$when=date("Y-m-d H:i"); 
						
						if ($debug)print "ONLINE-MSG2 :\nfrom: $from_uin\n";
						if ($debug)print "time: $when\n";
						if ($debug)print "mess: (".$msg_len.") $msg_text\n\n";
						
						/*
						$msgs_a[$mcount]["from"]=$from_uin;
						$msgs_a[$mcount]["time"]=$when;
						$msgs_a[$mcount]["msg"]=$msg_text;
						*/
						
											
						// (fromuin,touin,msg,when)
						$query = "INSERT INTO incoming ( `id` , `fromuin` , `touin` , `msg` , `msgtime` , `online` ) VALUES (0,'".$from_uin."','".$my_uin."','".$msg_text."','".$when."',1)";
						if ($debug)print "sql=$query\n";
						mysql_query($query);
						
						$mcount++;
					}
		$ps+=$flap_len;

	}

// Strunta i att returnera messen och returnera enbart antalet
return $mcount;
}


function parse_onoffline($str)
{
global $uin_status;
#print "parse_msgs \n";

$mcount=0;
$ps=0;

$str_len=strlen($str);


#print "str_len=$str_len \n";

while ($ps<$str_len)
	{
		$flap_len=bsubword2d($str,$ps+4)+6;
		#print "flap_len=$flap_len \n";
		
		// Kolla att flap'en дr en user_online
		if (ord($str[$ps+0])==42 && // Flap header
				ord($str[$ps+1])==2 && // Channel 2
				ord($str[$ps+7])==3 && // SNAC
				ord($str[$ps+9])==12) // $3,$C
					{
						$uin_len=ord($str[$ps+16]);
						$uin=substr($str,$ps+17,$uin_len);
						
						$uin_status[$uin]=0;
						print "USER: $uin is OFFLINE!\n";
					}

		// Kolla att flap'en дr en user_online
		if (ord($str[$ps+0])==42 && // Flap header
				ord($str[$ps+1])==2 && // Channel 2
				ord($str[$ps+7])==3 && // SNAC
				ord($str[$ps+9])==11) // $3,$B
					{
						$uin_len=ord($str[$ps+16]);
						$uin=substr($str,$ps+17,$uin_len);

						$uin_status[$uin]=1;
						print "USER: $uin is ONLINE!\n";					
					}
		
		$ps+=$flap_len;

	}


}


function cli_keepalive($seq_no)
{
return			(
						flap(5,$seq_no,"")
						);
	
}

function cli_dis($seq_no)
{
return			(
						flap(4,$seq_no,"")
						);
	
}

function cli_toicqsrv($seq_no,$icq_cmd)
{
return			(
						flap(2,$seq_no, // CHANNEL 2 SNAC (15,2)
						  h2b("00 15 00 02 00 00 00 01 00 02"). // SNAC (15,2)
						  h2b("00 01 00 0A").$icq_cmd
							)
						);
}

function cli_sendoffline_ack()
{
	global $cli_seq,$my_uin,$fp;
	// Skicka CLI_TOICQSRV  ACK_OFFLINEMSGS (Svara att meddelandena дr mottagna)
	$icq_cmd=h2b("08 00").
					 d2bdwordflip($my_uin). // IPadressen hex-baklдnges
					 h2b("3E 00").
					 h2b("02 00");
					 
	$cli_seq++;
	$res=b2rh(send_data($fp,cli_toicqsrv($cli_seq,$icq_cmd)))."\n";
}

function cli_sendmsg($seq_no,$uin,$mess)
{
return		(
				flap(2,$seq_no, // CHANNEL 2 SNAC (4,6)
						  h2b("00 04 00 06 00 00 00 00 00 00"). // SNAC (4,6)
						  h2b("00 00 00 00 01 02 03 04"). //Message cookie
						  h2b("00 01"). //Msg format
						  chr(strlen($uin)).$uin. // Mottagare UIN
						  h2b("00 02").tlvstr
						  	(
						  		h2b("05 01 00 01 01").
						  		h2b("01 01").
						  		tlvsendstr($mess)
								).
						  h2b("00 06 00 00")
						)
					);
}

//h2b("00 01").tlvstr("52874461")


function cli_setuserinfo($seq_no,$vers)
{
$vers=3;
// 2001
$cap[0]=			  	h2b("09 46 13 49 4C 7F 11 D1 82 22 44 45 53 54 00 00").
									h2b("97 B1 27 51 24 3C 43 34 AD 22 D6 AB F7 3F 14 92").
									h2b("2E 7A 64 75 FA DF 4D C8 88 6F EA 35 95 FD B6 DF").
									h2b("09 46 13 44 4C 7F 11 D1 82 22 44 45 53 54 00 00");
				
// 2002a					
$cap[1]=			  	h2b("09 46 13 49 4c 7f 11 d1 82 22 44 55 53 54 00 00").
									h2b("09 46 13 4e 4c 7f 11 d1 82 22 44 45 53 54 00 00").
									h2b("97 b1 27 51 24 3c 43 34 ad 22 d6 ab f7 3f 14 92").
									h2b("09 46 13 44 4c 7f 11 d1 82 22 44 45 53 54 00 00");
									
// Trillian									
$cap[2]=			  	h2b("09 46 13 49 4C 7F 11 D1 82 22 44 45 53 54 00 00").
									h2b("09 46 13 44 4C 7F 11 D1 82 22 44 45 53 54 00 00").
									h2b("97 B1 27 51 24 3C 43 34 AD 22 D6 AB F7 3F 14 09").
									h2b("2E 7A 64 75 FA DF 4D C8 88 6F EA 35 95 FD B6 DF").
									h2b("F2 E7 C7 F4 FE AD 4D FB B2 35 36 79 8B DF 00 00");
									
$cap[3]=			  	h2b("09 46 13 49 4C 7F 11 D1 82 22 44 45 53 54 00 00").
									h2b("09 46 13 4E 4C 7F 11 D1 82 22 44 45 53 54 00 00").
									h2b("97 B1 27 51 24 3C 43 34 AD 22 D6 AB F7 3F 14 92").
									h2b("09 46 13 44 4C 7F 11 D1 82 22 44 45 53 54 00 00");
return			(
						flap(2,$seq_no, // CHANNEL 2 SNAC (2,4)
						  h2b("00 02 00 04 00 00 00 00 00 00"). // SNAC (2,4)
						  h2b("00 05").tlvstr
						  	(
								  $cap[$vers]
								)
							)
						);
}


function cli_ready($seq_no)
{
return			(
						flap(2,$seq_no, // CHANNEL 2 SNAC (1,2)
						  h2b("00 01 00 02 00 00 00 00 00 00"). // SNAC (1,2)
						  h2b("00 01 00 03 01 10 04 7B").
      				h2b("00 13 00 02 01 10 04 7B").
      				h2b("00 02 00 01 01 01 04 7B").
      				h2b("00 03 00 01 01 10 04 7B").
      				h2b("00 15 00 01 01 10 04 7B").
      				h2b("00 04 00 01 01 10 04 7B").
      				h2b("00 06 00 01 01 10 04 7B").
      				h2b("00 09 00 01 01 10 04 7B").
      				h2b("00 0A 00 01 01 10 04 7B").
      				h2b("00 0B 00 01 01 10 04 7B")
							)
						);
}

function cli_seticbm($seq_no)
{
return			(
						flap(2,$seq_no, // CHANNEL 2 SNAC (4,2)
						  h2b("00 04 00 02 00 00 00 00 00 00"). // SNAC (4,2)
						  h2b("00 00").
						  h2b("00 00").
						  h2b("00 03").
						  h2b("1F 40").
						  h2b("03 E7").
						  h2b("03 E7").
						  h2b("00 00").
						  h2b("00 00")
							)
						);
}

function cli_unknown1($seq_no)
{
return			(
						flap(2,$seq_no, // CHANNEL 2 SNAC (13,7)
						  h2b("00 13 00 07 00 00 00 00 00 00") // SNAC (13,7)
							)
						);
}

function cli_reqlocation($seq_no)
{
return			(
						flap(2,$seq_no, // CHANNEL 2 SNAC (2,2)
						  h2b("00 02 00 02 00 00 00 00 00 00") // SNAC (2,2)
							)
						);
}

function cli_reqbuddy($seq_no)
{
return			(
						flap(2,$seq_no, // CHANNEL 2 SNAC (3,2)
						  h2b("00 03 00 02 00 00 00 00 00 00") // SNAC (3,2)
							)
						);
}


function cli_reqbos($seq_no)
{
return			(
						flap(2,$seq_no, // CHANNEL 2 SNAC (9,2)
						  h2b("00 09 00 02 00 00 00 00 00 00") // SNAC (9,2)
							)
						);
}


function cli_reqicbm($seq_no)
{
return			(
						flap(2,$seq_no, // CHANNEL 2 SNAC (4,4)
						  h2b("00 04 00 04 00 00 00 00 00 00") // SNAC (4,4)
							)
						);
}

function cli_reqroster($seq_no)
{
return			(
						flap(2,$seq_no, // CHANNEL 2 SNAC (13,4)
						  h2b("00 13 00 05 00 00 00 01 00 04"). // SNAC (13,4)
						  h2b("01 02 03 04").
						  h2b("00 ff")
							)
						);
}

function cli_reqroster2($seq_no)
{
return			(
						flap(2,$seq_no, // CHANNEL 2 SNAC (13,4)
						  h2b("00 13 00 04 00 00 00 01 00 04") // SNAC (13,4)
							)
						);
}

function cli_requnknown($seq_no)
{
return			(
						flap(2,$seq_no, // CHANNEL 2 SNAC (13,2)
						  h2b("00 13 00 02 00 00 00 00 00 00") // SNAC (13,2)
							)
						);
}

function cli_reqinfo($seq_no)
{
return			(
						flap(2,$seq_no, // CHANNEL 2 SNAC (1,E)
						  h2b("00 01 00 0E 00 00 00 00 00 00") // SNAC (1,E)
							)
						);
}

function cli_ackrates($seq_no)
{
return			(
						flap(2,$seq_no, // CHANNEL 2 SNAC (1,8)
						  h2b("00 01 00 08 00 00 00 00 00 00"). // SNAC (1,8)
						  h2b("00 01").
						  h2b("00 02").
						  h2b("00 03").
						  h2b("00 04").
						  h2b("00 05")
							)
						);
}

function cli_ratesrequest($seq_no)
{
return			(
						flap(2,$seq_no, // CHANNEL 2 SNAC (1,6)
						  h2b("00 01 00 06 00 00 00 00 00 00") // SNAC (1,6)
							)
						);
}


function cli_snac1_11($seq_no)
{
return			( // CHANNEL 2 SNAC (1,11)
						flap(2,$seq_no,
							h2b("00 01 00 11 00 00 00 00 00 11"). // SNAC (1,11)
							h2b("00 00 00 3C")
							)
						);
}

function cli_setstatus($seq_no)
{
return			( // CHANNEL 2 SNAC (1,1E)
						flap(2,$seq_no,
							h2b("00 01 00 1E 00 00 00 00 00 00"). // SNAC (1,1E)
						  h2b("00 06 00 04").
						  h2b("20 00 00 00"). // Sдtt STATUS
						  h2b("00 08 00 02 00 00"). // Error code?
						  h2b("00 0C 00 25").
						  h2b("7F 00 00 01"). // Sдtt intern ip-adress
						  h2b("00 00 2E 44"). // Sдtt port
						  h2b("04 00 08"). // Sдtt vanlig koppling + version 8
						  h2b("B5 87 DF 58"). // Direct connect cookie
						  h2b("00 00 00 50 00 00 00 03"). // okдnda params + 3 items
						  h2b("3B A8 DB AF"). // 3B A8 DB AF
						  h2b("3B A8 DB AF").
						  h2b("3B A8 DB AF").
						  h2b("00 00")
							)
						);
}

/*
This sets the client's online status and some flags:
00xxxxxx = allow direct connection with everyone
10xxxxxx = allow direct connection upon authorization
20xxxxxx = allow direct connection with users in contact list
xx02xxxx = show IP
xx03xxxx = webaware
xxxx0000 = online
xxxx0100 = invisible
xxxx0001 = away
xxxx0005 = NA
xxxx0011 = Occupied
xxxx0013 = DND
xxxx0020 = Free for chat

STATUS_OFFLINE 0xffffffff The user is offline. / Set status to offline. 
STATUS_ONLINE 0x00000000 The user is online. / Set status to online. 
STATUS_INVISIBLE 0x00000100 Set status to invisible. 
STATUS_DND 0x00000013 Set status to do not disturb. 
STATUS_OCCUPIED 0x00000011 Set status to occupied. 
STATUS_NA 0x00000005 Set status to not available. 
STATUS_AWAY 0x00000001 Set status to away. 
STATUS_FFC 0x00000020 Set status to free for chat. 
STATUSF_WEBAWARE 0x00010000 The user is web-aware. 
STATUSF_IP 0x00020000 The user allows his IP to be shown. (that must actually be wrong) 
STATUSF_BIRTH 0x00080000 The user's birthday is today. 
STATUSF_UNK 0x00100000 Unknown. 
STATUSF_DCAUTH 0x10000000 The user allows direct connections only upon authorization. 
STATUSF_DCCONTACT 0x20000000 The user allows direct connections only with contacts. 
STATUSF_UNUSED 0xcfe4fec8 As of yet unused flags. 

*/


function cli_families($seq_no)
{
return			( // CHANNEL 2 SNAC (1,17)
						flap(2,$seq_no,
							h2b("00 01 00 17 00 00 00 00 00 00"). // SNAC (1,17)
						  h2b("00 01 00 03").
						  h2b("00 13 00 02").
						  h2b("00 02 00 01").
						  h2b("00 03 00 01").
						  h2b("00 15 00 01").
						  h2b("00 04 00 01").
						  h2b("00 06 00 01").
						  h2b("00 09 00 01").
						  h2b("00 0A 00 01").
						  h2b("00 0B 00 01")
							)
						);
}


function cli_cookie($seq_no,$cookie)
{
return			(
						flap(1,$seq_no,
						  h2b("00 00 00 01"). // HELLO
							h2b("00 06").tlvstr($cookie)
							)
						);
}

function cli_ident($seq_no,$uin,$pass)
{
return			(
						flap(1,$seq_no,
						  h2b("00 00 00 01"). // HELLO
							h2b("00 01").tlvstr($uin). // UIN
							h2b("00 02").tlvstr(icqcrypt($pass)). // PW
							h2b("00 03").tlvstr("ICQ Inc. - Product of ICQ (TM).2003a.5.47.1.3800.85"). // Client version
							h2b("00 16 00 02 01 0A").
							h2b("00 17 00 02 00 05"). //5 //4 //5 // 5
							h2b("00 18 00 02 00 2F"). //15 //55 //55 // 17 // 47
							h2b("00 19 00 02 00 01"). //1 //1 // 1 // 1 //
							h2b("00 1A 00 02 0E D8"). //3728 //3264 //3800 //3800
							h2b("00 14 00 04 00 00 00 55"). // 85 // 85
							h2b("00 0F"). tlvstr("en"). // Language
							h2b("00 0E"). tlvstr("us")  // Country
							)
						);
						// ICQ Inc. - Product of ICQ (TM).2002a.5.37.1.3728.85
}

function icqcrypt($instr)
{
$icqcrypt_s = "f32681c43986db9271a3b9e6537a957c";
$outstr="";
for ($i=0;$i<strlen($instr);$i++)
	{
		$iccount=$i % 16;
		$f1b=ord(substr($instr,$i,1));		
		$f2b=ord(h2b(substr($icqcrypt_s,$iccount*2,2)));
		#print $iccount;
		#print $f1b." - ".$f2b."\n";
		$f3b = $f1b ^ $f2b;
		$outstr.=chr($f3b);
		
	}	
return $outstr;

}

function smart_utf8_decode($in_str)
{
// Replace ? with a unique string
$new_str = str_replace("?", "q0u0e0s0t0i0o0n", $in_str);
// Try the utf8_decode
$new_str=utf8_decode($in_str);
// if it contains ? marks
if (strpos($new_str,"?")>0)
	{
		// Something went wrong, set new_str to the original string.
		$new_str=$in_str;
	}
else
	{
		// If not then all is well, put the ?-marks back where is belongs
		$new_str = str_replace("q0u0e0s0t0i0o0n", "?", $new_str);
	}
return $new_str;
}

function amp($str)
{
return str_replace("&","&amp;",$str);
}

function to_wml($str)
{
$str=htmlspecialchars($str,ENT_QUOTES);

return $str;
}

function h2b($hexdata) 
{
  
  $hexdata = str_replace(" ","",$hexdata);
  
  for ($i=0;$i<strlen($hexdata);$i+=2) {
     $bindata.=chr(hexdec(substr($hexdata,$i,2)));
  }
  
  return $bindata;
}


function b2h($bindata)
{
	$hexdata="";
	
	for ($i=0;$i<strlen($bindata);$i++)
		{
			$hexdata.=sprintf("%02X",ord($bindata[$i]));
		}		
	
	return $hexdata;
}



function b2rh($bindata)
{
	$ss="";
	$hexdata="\n";
	for ($i=0;$i<strlen($bindata);$i++)
		{
			//$hexdata.=
			
			//print dechex(ord(substr($bindata,$i,1)));
			$subst=substr($bindata,$i,1);
			$hexdata.=sprintf("%02X ",ord($subst));
			
			
			if (ord($subst)<30)
				{
					$subst=" ";
				}
			$ss.=$subst;
			
			if (($i%16)==15)
				{
					$hexdata.=" ".$ss." <br>\n";
					$ss="";
				}
			
				
			//sprintf("%02X%02X%02X",$color,$color1,$color2)
		}		
	
$hexdata.=" ".$ss."\n";

return $hexdata;
}

function scan_zeroword($str,$tps)
{
	// Flytta pekaren tills man stцter pе 00 00
	while (bsubword2d($str,$tps)!=0)
		{
			$tps+=2;
		}

	return $tps;
}

function bsubword2d($str,$p)
{
	return (ord(substr($str,$p,1))*256)+ord(substr($str,$p+1,1));
}

//bsubdwordflip2d
function bsubdwordflip2d($str,$p)
{
	return (ord($str[$p+0])+(ord($str[$p+1])*256)+(ord($str[$p+2])*65536)+(ord($str[$p+3])*16777216));
}

function bsubwordflip2d($str,$p)
{
	return (ord($str[$p+0])+(ord($str[$p+1])*256));
}

function d2bword($number)
{
	return h2b(sprintf("%04X",$number));
}

function d2bwordflip($number)
{
	$txtret=h2b(sprintf("%04X",$number));
	return ($txtret[1].$txtret[0]);
}

function d2bdwordflip($number)
{
	$txtret=h2b(sprintf("%08X",$number));
	return ($txtret[3].$txtret[2].$txtret[1].$txtret[0]);
}

function get_uinstr($str,$ps)
{
global $debug;

	// Lдs fцrsta UIN-lдngd och UIN
	$str_len=bsubword2d($str,$ps);
	
	// Om str_len дr mer дn 32 returnera tom strдng
	if ($str_len>32)
		{
			return "";
		}
	
	if ($debug)print "uin_len=".$str_len."\n";
	$outstr=substr($str,$ps+2,$str_len);
	if ($debug)print "uin str=".$outstr."\n";
	return $outstr;
}

function tlvstr($str)
{
	 $strln=strlen($str);
	 return d2bword($strln).$str;
	 //print dechex($strln);
}

function tlvsendstr($str)
{
	 $strln=strlen($str)+4;
	 return d2bword($strln).h2b("00 00 00 00").$str;
	 //print dechex($strln);
}

function flap($channel,$seq_no,$str)
{
	$strln=strlen($str);
	return h2b("2a").chr($channel).d2bword($seq_no).d2bword($strln).$snac.$str;
	
}


function icq_login($my_uin,$my_pwd)
{
global $debug;

	// Skapa ett klient-sequence nummer
	$cli_seq=rand(1, 65000); 
	
	// ********** LOGIN-SERVERN *************
	
	// Цppna connection
	$fp = fsockopen ("login.icq.com", 5190, $errno, $errstr, 30);
	if (!$fp)
		{
			return false;
			//die ($errstr."\n"."Could not connect to: login.icq.com:5190");
		}
	stream_set_blocking($fp, false);
	
	// Ta emot SRV_HELLO
	$res=recieve_data($fp);
	if ($debug)print "rec srv_hello:".b2rh($res)."\n";
	
	// Skicka CLI_IDENT
	$res=b2rh(send_data($fp,cli_ident($cli_seq,$my_uin,$my_pwd)))."\n";
	
	// Ta emot SRV_COOKIE frеn login-servern
	$res=recieve_data($fp);
	if ($debug)print "rec srv_cookie:".b2rh($res)."\n";
	
	$srv_cookie_a=parse_srv_cookie($res);
	
	// Stдng ner fцrsta kopplingen
	fclose ($fp);

	return $srv_cookie_a;	
	// ********** LOGIN-SERVERN *************

}

function icq_login_cookie($srv_cookie_a)
{
	global $cli_seq,$fp;

	// Connecta mot angiven ip och port
	$fp = fsockopen ($srv_cookie_a["ip"], $srv_cookie_a["port"], $errno, $errstr, 3000);
					
	if (!$fp)
		{
			die ($errstr."\n"."Could not connect to: ".$srv_cookie_a["ip"].":".$srv_cookie_a["port"]);
		}
							
	stream_set_blocking($fp, false);
					
	// Ta emot SRV_HELLO
	$res=recieve_data($fp);

	// Skapa nytt klient-sequence nummer
	$cli_seq=rand(1, 65000); 

	// Skicka CLI_COOKIE
	$res=b2rh(send_data($fp,cli_cookie($cli_seq,$srv_cookie_a["cookie"])))."\n";
	
	// Ta emot SRV_FAMILIES
	$res=recieve_data($fp);
	print "rec srv_fam:".b2rh($res)."\n"; 
	
	// цka seq-rдknaren
	$cli_seq++;
	// Skicka CLI_FAMILIES
	$res=b2rh(send_data($fp,cli_families($cli_seq)))."\n";
	
	// Ta emot SRV_FAMILIES2 + MOTD
	$res=recieve_data($fp);
	print "rec srv_fam2+motd:".b2rh($res)."\n";
	
	// цka seq-rдknaren
	$cli_seq++;
	// Skicka CLI_RATESREQUEST
	$res=b2rh(send_data($fp,cli_ratesrequest($cli_seq)))."\n";
	
	// Ta emot SRV_RATES
	$res=recieve_data($fp);
	print "rec srv_rates:".b2rh($res)."\n";
	
	// Skicka CLI_ACKRATES
	$cli_seq++;
	$res=b2rh(send_data($fp,cli_ackrates($cli_seq)))."\n";
	$cli_seq++;
	$res=b2rh(send_data($fp,cli_reqinfo($cli_seq)))."\n";
	$cli_seq++;
	$res=b2rh(send_data($fp,cli_requnknown($cli_seq)))."\n";
	$cli_seq++;
	$res=b2rh(send_data($fp,cli_reqroster($cli_seq)))."\n";
	$cli_seq++;
	$res=b2rh(send_data($fp,cli_reqlocation($cli_seq)))."\n";
	$cli_seq++;
	$res=b2rh(send_data($fp,cli_reqbuddy($cli_seq)))."\n";
	$cli_seq++;
	$res=b2rh(send_data($fp,cli_reqicbm($cli_seq)))."\n";
	$cli_seq++;
	$res=b2rh(send_data($fp,cli_reqbos($cli_seq)))."\n";
	
	// Ta emot svar
	$res=recieve_data($fp);
	print "rec svar:".b2rh($res)."\n";
	
	$res=recieve_data($fp);
	parse_msgs($res);
	print "rec svar:".b2rh($res)."\n";
	
	
	$cli_seq++;
	$res=b2rh(send_data($fp,cli_unknown1($cli_seq)))."\n";
	
	$cli_seq++;
	$res=b2rh(send_data($fp,cli_setuserinfo($cli_seq,1)))."\n";
	
	$cli_seq++;
	$res=b2rh(send_data($fp,cli_seticbm($cli_seq)))."\n";
	
	$cli_seq++;
	$res=b2rh(send_data($fp,cli_setstatus($cli_seq)))."\n";
	
	$cli_seq++;
	$res=b2rh(send_data($fp,cli_ready($cli_seq)))."\n";
	
	$res=recieve_data($fp);
	#print "rec svar:".b2rh($res)."\n";

}

function cli_unknown2($my_uin)
{
global $cli_seq;

	// Skicka CLI_TOICQSRV  REQ_OFFLINEMSGS (Hдmta meddelanden)
	$icq_cmd=h2b("5A 00").
					 d2bdwordflip($my_uin). // IPadressen hex-baklдnges
					 h2b("D0 07").
					 h2b("0f 00").
					 h2b("be 0a").
					 h2b("05 00"). // Client Major v
					 h2b("0f 00"). // Minor v
					 h2b("01 00"). // lesser v
					 h2b("36 0e"). // Build
					 h2b("55 00 00 00"). // sub-build
					 h2b("90 7c 21 21").
					 h2b("91 4d d3 11").
					 h2b("ad eb 00 04").
					 h2b("ac 96 aa b2").
					 h2b("00 00").
					 h2b("03 00 00 00").
					 h2b("2c 00").
					 h2b("01 00").
					 h2b("00 01").
					 h2b("00 00 00 00").
					 h2b("01 00 00 00").
					 h2b("00 00 00 00 00 00 00 00").
					 h2b("00 00 00 00 00 00 00 00").
					 h2b("00 00 00 00 00 00 00 00").
					 h2b("00 00 00 00 00 00 00 00")
					 ;

	$cli_seq++;
	$res=b2rh(send_data($fp,cli_toicqsrv($cli_seq,$icq_cmd)))."\n";
	
}

function icq_get_msgs($my_uin)
{ 
	global $cli_seq,$fp,$debug;
	
	// Hдmta offline meddelanden och sдtt flagga att dom дr hдmtade
	
	
	// Skicka CLI_TOICQSRV  REQ_OFFLINEMSGS (Hдmta meddelanden)
	$icq_cmd=h2b("08 00").
					 d2bdwordflip($my_uin). // IPadressen hex-baklдnges
					 h2b("3C 00").
					 h2b("02 00");
					 
	$cli_seq++;
	$res=b2rh(send_data($fp,cli_toicqsrv($cli_seq,$icq_cmd)))."\n";
	
	// Hдmta ev. meddelande-data
	$res=recieve_data($fp);
	if ($debug)print "REQOFFLINE svar:".b2rh($res)."\n";
	
	// Parsa ev. meddelanden och lagra in en array ($msgs)
	$msgs=parse_msgs($res);
	
	//cli_unknown2($my_uin);
		
  return $msgs;
}

function icq_send_msg($rec_uin,$msg_text)
{
global $cli_seq,$fp;

	//$msg_text=$msg_text;

	$cli_seq++;
	$res=b2rh(send_data($fp,cli_sendmsg($cli_seq,$rec_uin,$msg_text)))."\n";
	
}

function icq_send_msgs()
{
global $my_uin,$timeout_seconds,$timeend,$ltimeleft,$debug;

		// Sцk fram meddelanden som ska skickas TILL ICQ-servern
		$query="SELECT * FROM outgoing WHERE fromuin='".$my_uin."' AND seen=0 ORDER BY msgtime";
		if ($debug)print "sql = $query\n";
		
		$sqlres=mysql_query($query) or die("send_msgs Invalid query: " . mysql_error());

		// Gе igenom varje meddelande och skicka
		while ($row = mysql_fetch_array($sqlres))
			{
				icq_send_msg($row["touin"],$row["msg"]);
				
				#$query="DELETE FROM outgoing WHERE id=".$row["id"];
   			#$delres=mysql_query($query);

				$query="UPDATE outgoing SET seen=1 WHERE id=".$row["id"];
				$updres=mysql_query($query) or die("send_alive Invalid query: " . mysql_error());


				// Resetta timern
				$nowtime=time();
				$timeend = $nowtime+$timeout_seconds;
				$ltimeleft=-1;   			

    	}

}

function icq_receive_incoming()
{
global $cli_seq,$my_uin,$fp,$timeout_seconds,$debug,$nowtime,$timeend,$ltimeleft;

		$str="";
		$str = fread($fp,32768);
		
		if ($str)
			{
				print "Incoming...\n";
				
				$msgs=parse_msgs($str);

				if ($msgs>0)
					{
						// Resetta timern
						$nowtime=time();
						$timeend = $nowtime+$timeout_seconds;
						$ltimeleft=-1;
					}
				
				parse_onoffline($str);

				$dis_id=is_disconnect($str);
				
				if ($dis_id>0)
					{ 
						cli_sendoffline_ack();
						fclose($fp);
						print "DISCONNECT: Reason $dis_id !!";
						exit;
					}
				
				if ($debug)print b2rh($str);	
				
			}

}


function send_alive($my_uin)
{

		$query="SELECT lifesign FROM alive WHERE uin='".$my_uin."'";
		if ($debug)print "sql = $query\n";
		
		$sqlres=mysql_query($query) or die("send_alive Invalid query: " . mysql_error());
		$num_rows = mysql_num_rows($sqlres);
		
		$now=time();
		
		if ($num_rows>0)
			{
				$query="UPDATE alive SET lifesign='".$now."' WHERE uin=".$my_uin."";
				$updres=mysql_query($query) or die("send_alive Invalid query: " . mysql_error());
			}
		else
			{
				$query="INSERT INTO alive (uin,lifesign) VALUES ('".$my_uin."',".$now.")";
				$insres=mysql_query($query) or die("send_alive Invalid query: " . mysql_error());
			}
	
}

?>