Location: PHPKode > scripts > PHP TOC Library > php-toc-library/aimclassw.php
<?php
/*
	PHPTOCLIB: A library for AIM connectivity through PHP using the TOC protocal.

	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 of the License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/
include ("errors.php");

set_time_limit(0);

//06-07-04: pickle- Added some more types to be used

define("AIM_TYPE_WARN",74);
define("AIM_TYPE_MSG",75);
define("AIM_TYPE_UPDATEBUDDY",76);
define("AIM_TYPE_SIGNON",77);
define("AIM_TYPE_NICK",78);
define("AIM_TYPE_ERROR",79);
define("AIM_TYPE_CHATJ",80);
define("AIM_TYPE_CHATI",81);
define("AIM_TYPE_CHATUPDBUD",82);
define("AIM_TYPE_CHATINV",83);
define("AIM_TYPE_CHATLE",84);
define("AIM_TYPE_URL",85);
define("AIM_TYPE_NICKSTAT",86);
define("AIM_TYPE_PASSSTAT",87);
define("AIM_TYPE_NOT_IMPLEMENTED",666);


define("MAX_PACKLENGTH",2048);

define("SFLAP_TYPE_SIGNON",1);
define("SFLAP_TYPE_DATA",2);
define("SFLAP_TYPE_ERROR",3);
define("SFLAP_TYPE_SIGNOFF",4);
define("SFLAP_TYPE_KEEPALIVE",5);
define("SFLAP_MAX_LENGTH",1024);

define("SFLAP_SUCCESS",0);
define("SFLAP_ERR_UNKNOWN",1);
define("SFLAP_ERR_ARGS",2);
define("SFLAP_ERR_LENGTH",3);
define("SFLAP_ERR_READ",4);
define("SFLAP_ERR_SEND",5);

define("SFLAP_FLAP_VERSION",1);
define("SFLAP_TLV_TAG",1);
define("SFLAP_HEADER_LEN",6);

$Silent = false; //True means nothing should be printed (Use sEcho instead of echo)

class Aim
{
	var $myScreenName;  //Screen name of the bot(normalized)
	var $myPassword;    //Password for the bot (plain text)
	var $sql_user;      //The user for the sql database
	var $sql_pass;      //The password for the sql database
	var $sql_db;        //The database that the bots info is in
	var $sql_server;    //The sql server/The database that the bots info is in

	var $myServer="toc.oscar.aol.com";      //The server to connect on
	var $myPort="5190";        //The servers port
	var $myProfile="Powered by phpTOCLib. Please visit http://sourceforge.net/projects/phptoclib for more information";     //The profile of the bot
	var $myLogging=0;     //Put messages and commands into a log file
	var $myDebugOut=0;    //Show most commands in the console window

	var $myConnection;  //Connection resource ID
	var $myRoastedPass; //The password. roasted
	var $myLastReceived;//The last message received from the server
	var $mySeqNum;      //The currecnt seq number used to communicate with the server
	var $myLogHandler;  //THe handler for the log file, is 0 if logging is off
	var $mySQLHandle;
	var $myWarnLevel;   //Warning Level of the bot
	var $myAuthCode;
	var $myBuddyList;
	var $myBlockedList;
	var $myPermitList;
	var $myPdMode; //Permit deny mode
	
	//Below variables added 4-29 by Jeremy: Implementing chat
	var $acceptchat;  //Should we accept chat invitations?
	var $chatrooms;   //Array containing chat romm info $chatrooms['roomid'] = people in room
	var $numchats=0;    //How many chats are we in?
	var $chatqueue;   //Make a queue for which chats to join when we leave one
	
	//End of chat implementation
	
	var $signonrcv = false; //This will be set to true when we receive the SIGN_ON message
					//This should keep other functions from being called that
					//aren't related to signon
	
	//Below are event handlers Added for beta 1 by Jeremy
	var $onSignOnf="none";
	var $onConfigf="none";
	var $onNickf="none";
	var $onImInf="none";
	var $onUpdateBuddyf="none";
	var $onErrorf="none";
	var $onWarnf="none";
	var $onChatJoinf="none";
	var $onChatUpdatef="none";
	var $onChatInvitef="none";
	var $onChatLeftf="none";
	var $onGotoURLf="none";
	var $onDirStatusf="none";
	var $onAdminNickf="none";
	var $onAdminPasswdf="none";
	var $onPausef="none";
	var $onRvousf="none";
	var $CatchAllf="none";
	
	//End of event handler block
	
	
	
	
	

    //Constructor
	function Aim($sn,$password,$pdmode, $silent=false)
    {
        //Constructor assignment
		$this->myScreenName=$this->normalize($sn);
		$this->myPassword=$password;
		$this->myRoastedPass=$this->roast_pass($password);
		$this->mySeqNum=1;
		$this->myConnection=0;
		$this->myWarnLevel=0;
		$this->myAuthCode=$this->make_code();
		$this->myPdMode=$pdmode;
		
		$GLOBALS["Silent"] = $silent;
		
		if($silent){
			error_reporting(E_ERROR);
		}
		//else
			//error_reporting(E_ALL);
		
		sEcho("PHPTOCLIB v0.4 Object Created");
		
	}

	function roast_pass($password)
	{
		$roaststring = 'Tic/Toc';
		$roasted_password = '0x';
		for ($i = 0; $i < strlen($password); $i++)
			$roasted_password .= bin2hex($password[$i] ^ $roaststring[($i % 7)]);
		return $roasted_password;
	}
	
	function make_code()
	{
		$sn=base_convert(bin2hex($this->myScreenName[0]),16,10) - 96;
		$pw=base_convert(bin2hex($this->myPassword[0]),16,10) - 96;
		$a= $sn * 7696 + 738816;
		$b= $sn * 746512;
		$c= $pw * $a;

		return $c-$a+$b+71665152;
	}

	//Public function designed to set the sql information
	function sql_connect($host,$username,$password,$database)
	{
			@$this->mySQLHandle=mysql_connect($host,$username,$password) or die("Could not connect to the database. The host may not exist, or the supplied username and password were incorrect");
			@mysql_select_db($database) or die("Error selecting database. It is possible it does not exist, or you may bot have permission to access it");
			$this->sql_user=$username;
			$this->sql_pass=$password;
			$this->sql_server=$host;
			$this->sql_db=$database;
			sEcho("Connected to MySQL Database: " . $this->sql_db . " by " . $this->sql_user . "@" . $this->sql_server);
	}

	function sflap_read()
	{
		if(socketcheck($this->myConnection))
		{
			sEcho("Disconnected.... Reconnecting in 60 seconds");
			sleep(60);
			$this->signon();
		}
		
		$sockinfo=socket_get_status($this->myConnection);
		//sEcho($sockinfo['unread_bytes'] . "     " . $sockinfo['blocked']);
		//if($sockinfo['unread_bytes'] < SFLAP_HEADER_LEN && !$sockinfo['blocked'])
		//if(feof($this->myConnection) && $sockinfo['blocking'])
		//	return "";

		$header=fread($this->myConnection,SFLAP_HEADER_LEN);
		//or $this->derror("Could not read header");
		//if(strlen($header)<SFLAP_HEADER_LEN && $sockinfo['blocked'])
		//{
			//fclose($this->myConnection);
		//	$this->derror("Error reading header.. attempting to reconnect");
			//sleep(60);
			//$this->signon();
		//}
		//else 
		if(strlen($header)==0)
		{
			$this->myLastReceived="";
			return "";
		}
		$header_data=unpack("aast/Ctype/nseq/ndlen", $header);
		//print_r($header_data);
		sEcho(" . ", false);
		$packet=fread($this->myConnection,$header_data['dlen']);
		if(strlen($packet)<=0 && $sockinfo['blocked'])
			$this->derror("Could not read data");
		
		if($header_data['type']==SFLAP_TYPE_SIGNON)
		{
			$packet_data=unpack("Ndecoded",$packet);
		}
		
		if($header_data['type']==SFLAP_TYPE_KEEPALIVE)
		{
			$this->myLastReceived='';
			return 0;
		} 
		else if(strlen($packet)>0)
		{
			$packet_data=unpack("a*decoded",$packet);
		}
		sEcho("socketcheck check now");
		if(socketcheck($this->myConnection))
		{
			$this->derror("Connection ended unexpectedly");
		}
		
		$data=array_merge($header_data,$packet_data);
		$this->myLastReceived=$data;
		//SEcho("data "  . $data);
		return $data;
    }

	function sflap_send($sflap_type,$sflap_data,$no_null,$formatted)
	{
		$packet="";
		
		if(strlen($sflap_data)>=MAX_PACKLENGTH)
			$sflap_data=substr($sflap_data,0,MAX_PACKLENGTH);
			
		if($formatted)
		{
			$len=strlen($sflap_len);
			$sflap_header=pack("aCnn",'*',$sflap_type,$this->mySeqNum,$len);
			$packet=$sflap_header . $sflap_data;
		} else {
			if(!$no_null)
			{
				$sflap_data=str_replace("\0","",$sflap_data);
				$sflap_data.="\0";
			}
			$data=pack("a*",$sflap_data);
			$len=strlen($sflap_data);
			$header=pack("aCnn","*",$sflap_type,$this->mySeqNum,$len);
			$packet=$header . $data;
		}
		
		//Make sure we are still connected
		if(socketcheck($this->myConnection))
		{
			sEcho("Disconnected.... reconnecting in 60 seconds");
			sleep(60);
			$this->signon();
		}
		$sent=fputs($this->myConnection,$packet) or $this->derror("Error sending packet to AIM");
		$this->mySeqNum++;
		sleep(ceil($this->myWarnLevel/10));
	}

    //Escape the thing that TOC doesn't like,that would be
    //",',$,{,},[,]
	function encode_data($data)
	{
		$data=str_replace('"','\"',$data);
		$data=str_replace('$','\$',$data);
		$data=str_replace("'","\'",$data);
		$data=str_replace('{','\{',$data);
		$data=str_replace('}','\}',$data);
		$data=str_replace('[','\[',$data);
		$data=str_replace(']','\]',$data);
		return $data;
	}

	function decode($data)
	{
		$data=str_replace('\"','"',$data);
		$data=str_replace('\$','$',$data);
		$data=str_replace("\'","'",$data);
		$data=str_replace('\{','{',$data);
		$data=str_replace('\}','}',$data);
		$data=str_replace('\[','[',$data);
		$data=str_replace('\]',']',$data);
		$data=str_replace('&quot;','"',$data);
		$data=str_replace('&amp;','&',$data);
		return $data;
	}


    //"normalize" the nickname, that means no spaces and all lowercase
	function normalize($nick)
	{
		$nick=str_replace(" ","",$nick);
		$nick=strtolower($nick);
		return $nick;
	}

	function set_my_info()
	{
		//Sets internal values bvase on the update buddy command
		sEcho("Setting my warning level ...");
		$this->sflap_send(SFLAP_TYPE_DATA,"toc_get_status " . $this->normalize($this->myScreenName),0,0);
		//The rest of this will now be handled by the other functions. It is assumed
		//that we may have other data queued in the socket, do we should just add this
		//message to the queue instead of trying to set it in here
	}

	function signon()
	{
		sEcho("Ready to sign on to the server");
		$this->myConnection=fsockopen($this->myServer,$this->myPort,$errno,$errstr,10) or die("$errorno:$errstr");
		sEcho("Connected to server");
		$this->mySeqNum=(time() % 65536); //Select an arbitrary starting point for
										  //sequence numbers
		if(!$this->myConnection)
			$this->derror("Error connecting to toc.oscar.aol.com");
		sEcho("Connected to AOL");
		//Send the flapon packet
		fputs($this->myConnection,"FLAPON\r\n\n\0"); //send the initial handshake
		sEcho("Sent flapon");
		$this->sflap_read();  //Make sure the server responds with what we expect
		if(!$this->myLastReceived)
			$this->derror("Error sending the initialization string");

		//send the FLAP SIGNON packet back with what it needs
		//There are 2 parts to the signon packet. They are sent in succession, there
		//is no indication if either packet was correctly sent
		$signon_packet=pack("Nnna".strlen($this->myScreenName),1,1,strlen($this->myScreenName),$this->myScreenName);
		$this->sflap_send(SFLAP_TYPE_SIGNON,$signon_packet,1,0);
		sEcho("sent signon packet part one");
		
		$signon_packet_part2='toc2_signon login.oscar.aol.com 29999 ' . $this->myScreenName . ' ' . $this->myRoastedPass . ' english-US "TIC:TOC2:REVISION" 160 ' . $this->myAuthCode;
		sEcho($signon_packet_part2 . "");
		$this->sflap_send(SFLAP_TYPE_DATA,$signon_packet_part2,0,0);
		sEcho("Sent signon packet part 2... Awaiting response...");

		$this->sflap_read();
		sEcho("Received Sign on packet, beginning initilization...");
		$message=$this->getLastReveived();
		sEcho($message . "\n");
		if(strstr($message,"ERROR:"))
		{
			$this->onError($message);
			die("Fatal signon error");
		}
		//The information sent before the config2 command is utterly useless to us
		//So we will just skim through them until we reach it
		
		//UPDATED 4/12/03: Now this will use the receive function and send the
		//received messaged to the assigned handlers. This is where the signon 
		//method has no more use
		
		sEcho("Done with signon proccess");
		//socket_set_blocking($this->myConnection,false);
	}
	
	function parse_buddy_change($message)
	{
		//This will update buddy info when I get around to it
		//TODO: SQL buddy storage
	}

	function send_im($to,$message,$auto=false)
	{
		if($auto) $auto="auto";
		else $auto="";
		$to=$this->normalize($to);
		$message=$this->encode_data($message);
		$command='toc2_send_im "' . $to . '" "' . $message . '" ' .  $auto;
		$this->sflap_send(SFLAP_TYPE_DATA,$command,0,0);
		$cleanedmessage = str_replace("<br>", "   ", $this->decode($message));
		$cleanedmessage = strip_tags($cleanedmessage);
		sEcho("TO - " . $to . " : " . $cleanedmessage);
	}
	
	function get_buddy_list()
	{
		//THis better be the right message
		$message=$this->myLastReceived['decoded'];
		if(strpos($message,"CONFIG2:")===false)
		{
			sEcho("get_buddy_list cannot be called at this time");
			return false;
		}
		$people=explode("\n",trim($message,"\n"));
		//The first 3 elements of the array are who knows what, element 3 should be
		//a letter followed by a person
		for($i=1;$i<sizeof($people);$i++)
		{
   			@list($mode,$name)=explode(":",$people[$i]);
			switch($mode)
			{
				case 'p':
					$this->myPermitList[]=$name;
					break;
				case 'd':
					$this->myBlockedList[]=$name;
					break;
				case 'b':
					$this->myBuddyList[]=$name;
					break;
				case 'done':
	 				break;
				default:
					//
			}
		}
	}
	
	function add_permit($buddy)
	{
		$this->sflap_send(SFLAP_TYPE_DATA,"toc2_add_permit " . $this->normalize($buddy),0,0);
		$this->myPermitList[]=$this->normalize($buddy);
		return 1;
	}
	
	function block_buddy($buddy)
	{
		$this->sflap_send(SFLAP_TYPE_DATA,"toc2_add_deny " . $this->normalize($buddy),0,0);
		$this->myBlockedList[]=$this->normalize($buddy);
		return 1;
	}
	
	function getMessage()
	{
		$in = $this->read_from_aim();
		$cmd = msg_type($in);
		$in = msg_parse($cmd);
		$out = $in;
		$out['type'] = $cmd['type'];
		if($out['type'] == AIM_TYPE_WARN){
			$this->setWarning($out['warnlevel']);
		}
		if($out['type'] == AIM_TYPE_MSG){
			sEcho("" . $out['from'] . ": " . strip_tags($out['message']));
			$out['cleanmessage'] = strip_tags($out['message']);
		}
		return $out;
	}
	
	function getLastReveived()
	{
		if(@$instuff=$this->myLastReceived['decoded']){
			return $this->myLastReceived['decoded'];
		}else{
			return;
		}
	}
	
	function getBuddies()
	{
		return $this->myBuddyList;
	}
	
	function getPermit()
	{
		return $this->myPermitList;
	}
	
	function getBlocked()
	{
		return $this->myBlockedList;
	}
	
	function read_from_aim()
	{
		$this->sflap_read();
		$returnme= $this->getLastReveived();
		return $returnme;
	}
	function setWarning($warnlevel)
	{
		$this->myWarnLevel=$warnlevel;
	}
	
	function warn_user($to,$anon=false)
	{
		if(!$anon)
			$anon='"norm"';

		else
			$anon='"anon"';
		$this->sflap_send(SFLAP_TYPE_DATA,"toc_evil " . $this->normalize($to) . " $anon",0,0);
	}
	
	function update_profile($profiledata, $poweredby=false)
	{
		if($poweredby==false){
			$this->myProfile = $profiledata;
		}else{
			$this->myProfile = $profiledata . "<font size=1 face=tahoma><br><br>Powered by phpTOCLib<br>http://sourceforge.net/projects/phptoclib</font>";
		}
		
		$this->sflap_send(SFLAP_TYPE_DATA,"toc_set_info \"" . $this->encode_data($this->myProfile) . "\"",0,0);
		$this->set_my_info();
		sEcho("Profile has been updated...");
	}
	
	//Added 4/29/04 by Jeremy:
	//Various chat related methods
	
	function join_chat($chatid)
	{
		$this->sflap_send(SFLAP_TYPE_DATA,"toc_chat_accept " . $chatid,0,0);
	}
	
	function leave_chat($chatid)
	{
		$this->sflap_send(SFLAP_TYPE_DATA,"toc_chat_leave " . $chatid,0,0);
	}
	
	function chat_say($chatid,$message)
	{
		$this->sflap_send(SFLAP_TYPE_DATA,"toc_chat_send " . $chatid . " \"" . $this->encode_data($message) . "\"",0,0);
	}
	
	function chat_invite($chatid,$who,$message)
	{
		$this->sflap_send(SFLAP_TYPE_DATA,"toc_chat_invite " . $chatid . " \"" . $this->encode_data($message) . "\" " . $who,0,0);
	}
	
	function join_new_chat($name,$exchange)
	{
		//Creates a new chat
		$this->sflap_send(SFLAP_TYPE_DATA,"toc_chat_join " . $exchange . " \"" . $name . "\"",0,0);
	}
		
	function derror($message)
	{
		sEcho($message);
		sEcho("Error");
		fclose($this->myConnection);
		if((time() - $GLOBALS['errortime']) <  600){
			sEcho("Reconnecting in 60 Seconds");
			sleep(60);
		}
		$this->signon();
		$GLOBALS['errortime'] = time();
	}
	function recieve()
	{
		//This function will be used to get the incoming data
		//and it will be used to call the event handlers
		
		//First step:Get the data sitting in the socket
		$message=$this->read_from_aim();
		if(strlen($message) <= 0)
		{
			return;
		}
		
		//Second step: Get the command from the server
		@list($cmd,$rest)=explode(":",$message);
		
		//Third step, take the command, test the type, and pass it off
		//to the correct internal handler. The internal handler will
		//do what needs to be done on the class internals to allow
		//it to work, then proceed to pass it off to the user created handle
		//if there is one
		sEcho($cmd);
		switch($cmd)
		{
			case 'SIGN_ON':
				$this->onSignOn($message);
				break;
			case 'CONFIG2':
				$this->onConfig($message);
				break;
			case 'ERROR':
				$this->onError($message);
				break;
			case 'NICK':
				$this->onNick($message);
				break;
			case 'IM_IN2':
				echo("Calling onImIn()");
				$this->onImIn($message);
				break;
			case 'UPDATE_BUDDY2':
				$this->onUpdateBuddy($message);
				break;
			case 'EVILED':
				$this->onWarn($message);
				break;
			case 'CHAT_JOIN':
				$this->onChatJoin($message);
				break;
			case 'CHAT_IN':
				$this->onChatJoin($message);
				break;
			case 'CHAT_UPDATE_BUDDY':
				$this->onChatUpdate($message);
				break;
			case 'CHAT_INVITE':
				$this->onChatInvite($message);
				break;
			case 'CHAT_LEFT':
				$this->onChatLeft($message);
				break;
			case 'GOTO_URL':
				$this->onGotoURL($message);
				break;
			case 'DIR_STATUS':
				$this->onDirStatus($message);
				break;
			case 'ADMIN_NICK_STATUS':
				$this->onAdminNick($message);
				break;
			case 'ADMIN_PASSWD_STATUS':
				$this->onAdminPasswd($message);
				break;
			case 'PAUSE':
				$this->onPause($message);
				break;
			case 'RVOUS_PROPOSE':
				$this->onRvous($message);
				break;
			default:
				sEcho("Fell through :(");
				$this->CatchAll($message);
				break;
		}
		//Now get out of this function becuase the handlers should take care
		//of everything
	}
	
	//The next block of code is all the event handlers needed by the class
	//Some are left blank and only call the users handler because the class
	//either does not support the command, or cannot do anything with it
	
	function onSignOn($message)
	{
		$this->signonrcv=true;
		$function=$this->onSignOnf . "(\$message);";
		eval($function);
	}
	
	function onConfig($message)
	{
		if(strpos($message,"CONFIG2:")===false)
		{
			sEcho("get_buddy_list cannot be called at this time");
			return false;
		}
		$people=explode("\n",trim($message,"\n"));
		//The first 3 elements of the array are who knows what, element 3 should be
		//a letter followed by a person
		for($i=1;$i<sizeof($people);$i++)
		{
   			@list($mode,$name)=explode(":",$people[$i]);
			switch($mode)
			{
				case 'p':
					$this->myPermitList[]=$name;
					break;
				case 'd':
					$this->myBlockedList[]=$name;
					break;
				case 'b':
					$this->myBuddyList[]=$name;
					break;
				case 'done':
	 				break;
				default:
			}
		}
		
		//We only get the config message once, so now we should send our pd mode
		
		$this->sflap_send(SFLAP_TYPE_DATA,"toc2_set_pdmode " . $this->myPdMode,0,0);
		//Adds yourself to the permit list
		//This is to fix an odd behavior if you have nobody on your list
		//the server won't send the config command... so this takes care of it
		$this->sflap_send(SFLAP_TYPE_DATA,"toc2_add_permit " . $this->normalize($this->myScreenName),0,0); 
		
		//Now we allow the user to send a list, update anything they want, etc
		$function=$this->onConfigf . "(\$message);";
		eval($function);
		//Now that we have taken care of what the user wants, send the init_done message
		$this->sflap_send(SFLAP_TYPE_DATA,"toc_init_done",0,0);
	}
	

	
	function onError($message)
	{
		global $ERRORS;
		@list($cmd,$errornum,$errargs)=explode(":",$message);
		eval("\$errorstring=\"\$ERRORS[" . $errornum . "]\";");
		$string="\$errorstring=\"\$ERRORS[$errornum]\";";
		//This is important information! We need 
		// a A different outputter for errors
		// b Just to echo it
		//I'm just going to do a straight echo here, becuse we assume that
		//the user will NEED to see this error. An option to supress it will
		//come later I think. Perhaps if we did an error reporting level, similar
		//to PHP's, and we could probably even use PHP's error outputting system
		//I think that may be an idea.... 
		
		echo($errorstring . "\n");
		
		$function=$this->onErrorf . "(\$message);";
		eval($function);
	}
	
	function onNick($message)
	{
		//This is our nick, so set a feild called "mySNick" which will represent
		//the actual name given by the server to us, NOT the normalized screen name
		@list($cmd,$nick)=explode(":",$message);
		$this->mySNick=$nick;
		
		$function=$this->onNickf . "(\$message);";
		eval($function);
	}
	
	function onImIn($message)
	{
		//Perhaps we should add an internal log for debugging purposes??
		//But now, this should probably be handled by the user purely
		
		$function=$this->onImInf . "(\$message);";
		eval($function);
	}
	
	function onUpdateBuddy($message)
	{
		//Again, since our class currently does not deal with other people without
		//outside help, then this is also probably best left to the user. Though
		//we should probably allow this to replace the set_my_info function above
		//by handling the input if and only if it is us
		//Check and see that this is the command expected
		if(strpos($message,"UPDATE_BUDDY2:")==-1)
		{
			sEcho("A different message than expected was received");
			return false;
		}
	
		@list($cmd,$sn,$online,$warning,$starttime,$idletime,$uc)=explode(":",$message);
		if($this->normalize($sn) == $this->normalize($this->myScreenName))
		{
			$warning=rtrim($warning,"%");
			$this->myWarnLevel=$warning;
			sEcho("My warning level is $this->myWarnLevel %");
		}
		
		$function=$this->onUpdateBuddyf . "(\$message);";
		eval($function);
	}
	
	function onWarn($message)
	{
		//SImply update our warning level
		@list($cmd,$newwarn,$user)=explode(":",$message);
		$this->setWarning(trim($newwarn,"%"));
		
		$function=$this->onWarnf . "(\$message);";
		eval($function);
	}
	
	function onChatJoin($message)
	{
		@list($cmd,$rmid,$rmname)=explode(":",$message);
		$this->chatrooms[$rmid]=0;
		$this->numchats++;
		
		$function=$this->onChatJoinf . "(\$message);";
		eval($function);
	}
	
	
	function onChatUpdate($message)
	{
		$stuff=explode(":",$message);
		$people=sizeof($stuff);
		$people-=2;
		
		$function=$this->onChatUpdatef. "(\$message);";
		eval($function);
	}
	
	function onChatInvite($message)
	{
		@list($cmd,$name,$id,$from,$message)=explode(":",$message,6);
		$this->join_chat($id);		
		$function=$this->onChatInvitef . "(\$message);";
		eval($function);
	}
	
	function onChatLeft($message)
	{
		//We are not currently supporting chat
		
		$function=$this->onChatLeftf . "(\$message);";
		eval($function);
	}
	
	function onGotoURL($message)
	{
		//This is of no use to the internal class
		
		$function=$this->onGotoURLf . "(\$message);";
		eval($function);
	}
	
	function onDirStatus($message)
	{
		//This is not currently suported
		
		$function=$this->onDirStatusf . "(\$message);";
		eval($function);
	}
	
	function onAdminNick($message)
	{
		//NOt particularly useful to us		
		$function=$this->onAdminNickf . "(\$message);";
		eval($function);
	}
	
	function onAdminPasswd($message)
	{
		//Also not particlualry useful to the internals
		$function=$this->onAdminPasswdf . "(\$message);";
		eval($function);
	}
	
	function onPause($message)
	{
		//This is pretty useless to us too...
		
		$function=$this->onPausef . "(\$message);";
		eval($function);
	}
	
	function onRvous($message)
	{
		//This may not be of any use to us at all, because currently it does
		//not appear that direct connecting is enabled from the current client
		//to any TOC client
		
		$function=$this->onRvousf . "(\$message);";
		eval($function);
	}
	
	function CatchAll($message)
	{
		//Add to a log of unsupported messages.
		
		$this->unsupported[]=$message;
		//sEcho($message);
		//print_r($message);
		
		$function=$this->CatchAllf . "(\$message);";
		eval($function);
	}
	
	//This next block of code is for the handle registering
	
	function registerHandler($command,$function)
	{
		switch($command)
		{
			case 'SIGN_ON':
				$this->onSignOnf=$function;
				break;
			case 'CONFIG2':
				$this->onConfigf=$function;
				break;
			case 'ERROR':
				$this->onErrorf=$function;
				break;
			case 'NICK':
				$this->onNickf=$function;
				break;
			case 'IM_IN2':
				$this->onImInf=$function;
				break;
			case 'UPDATE_BUDDY2':
				$this->onUpdateBuddyf=$function;
				break;
			case 'EVILED':
				$this->onWarnf=$function;
				break;
			case 'CHAT_JOIN':
				$this->onChatJoinf=$function;
				break;
			case 'CHAT_IN':
				$this->onChatJoinf=$function;
				break;
			case 'CHAT_UPDATE_BUDDY':
				$this->onChatUpdatef=$function;
				break;
			case 'CHAT_INVITE':
				$this->onChatInvitef=$function;
				break;
			case 'CHAT_LEFT':
				$this->onChatLeftf=$function;
				break;
			case 'GOTO_URL':
				$this->onGotoURLf=$function;
				break;
			case 'DIR_STATUS':
				$this->onDirStatusf=$function;
				break;
			case 'ADMIN_NICK_STATUS':
				$this->onAdminNickf=$function;
				break;
			case 'ADMIN_PASSWD_STATUS':
				$this->onAdminPasswdf=$function;
				break;
			case 'PAUSE':
				$this->onPausef=$function;
				break;
			case 'RVOUS_PROPOSE':
				$this->onRvousf=$function;
				break;
			case 'other':
				$this->CatchAllf=$function;
				break;
			default:
				sEcho("This command does not exist");
		}
	}
}

//GLOBAL FUNCTIONS

//6/07/04: pickle- Added funtionality (hopefully) for all messages sent by TOC

function msg_type($message)
{
	$command=array();
	@list($cmd,$rest)=explode(":",$message);
	switch($cmd)
	{
		case 'IM_IN2':
			$type=AIM_TYPE_MSG;
		break;
		
		case 'UPDATE_BUDDY2':
			$type=AIM_TYPE_UPDATEBUDDY;
		break;
		
		case 'EVILED':
			$type=AIM_TYPE_WARN;
		break;
		
		case 'SIGN_ON':
			$type=AIM_TYPE_SIGNON;
		break;
		
		case 'NICK':
			$type=AIM_TYPE_NICK;
		break;
		
		case 'ERROR':
			$type=AIM_TYPE_ERROR;
		break;
		
		case 'CHAT_JOIN':
			$type=AIM_TYPE_CHATJ;
		break;
		
		case 'CHAT_IN':
			$type=AIM_TYPE_CHATI;
		break;
		
		case 'CHAT_UPDATE_BUDDY':
			$type=AIM_TYPE_CHATUPDBUD;
		break;
		
		case 'CHAT_INVITE':
			$type=AIM_TYPE_CHATINV;
		break;
		
		case 'CHAT_LEFT':
			$type=AIM_TYPE_CHATLE;
		break;
		
		case 'GOTO_URL':
			$type=AIM_TYPE_URL;
		break;
		
		case 'ADMIN_NICK_STATUS':
			$type=AIM_TYPE_NICKSTAT;
		break;
		
		case 'ADMIN_PASSWD_STATUS':
			$type=AIM_TYPE_PASSSTAT;
		break;
		
		default:
			$type=AIM_TYPE_NOT_IMPLEMENTED;
		break;
	}
	$command['type']=$type;
	$command['incoming']=$message;
	return $command;
}

function msg_parse($command)
{
	$info=array();
	switch($command['type'])
	{
		case AIM_TYPE_WARN:
			$command['incoming'].=":0";
			$it=explode(":",$command['incoming']);
			$info['warnlevel']=$it[1];
			$info['from']=$it[2];

		break;
		
		case AIM_TYPE_MSG:
			$it=explode(":",$command['incoming'],5);
			$info['auto']=$it[2];
			$info['from']=$it[1];
			$info['message']=$it[4];
		break;
		
		case AIM_TYPE_UPDATEBUDDY:
			@list($cmd,$info['sn'],$info['online'],$info['warnlevel'],$info['signon'],$info['idle'],$info['uc'])=explode(":",$command['incoming']);
		break;
		
		case AIM_TYPE_SIGNON:
			@list($cmd,$info['version'])=explode(":",$command['incoming']);		
		break;
		
		case AIM_TYPE_NICK:
			@list($cmd,$info['nickname'])=explode(":",$command['incoming']);		
		break;
		case AIM_TYPE_ERROR:
			@list($cmd,$info['errorcode'],$info['args'])=explode(":",$command['incoming']);
		break;
		
		case AIM_TYPE_CHATJ:
			@list($cmd,$info['chatid'],$info['chatname'])=explode(":",$command['incoming']);
		break;
		
		case AIM_TYPE_CHATI:
			@list($cmd,$info['chatid'],$info['user'],$info['whisper'],$info['message'])=explode(":",$command['incoming'],5);
		break;
		
		case AIM_TYPE_CHATUPDBUD:
			@list($cmd,$info['chatid'],$info['inside'],$info['userlist'])=explode(":",$command['incoming'],3);	
		break;
		
		case AIM_TYPE_CHATINV:
			@list($cmd,$info['chatname'],$info['chatid'],$info['from'],$info['message'])=explode(":",$command['incoming'],5);
		break;
		
		case AIM_TYPE_CHATLE:
			@list($cmd,$info['chatid'])=explode(":",$command['incoming']);		
		break;
		
		case AIM_TYPE_URL:
			@list($cmd,$info['windowname'],$info['url'])=explode(":",$command['incoming'],3);
		break;
		
		case AIM_TYPE_NICKSTAT:
		case AIM_TYPE_PASSSTAT:
			@list($cmd,$info['returncode'],$info['opt'])=explode(":",$command['incoming'],3);		
		break;
		
		default:
		$info['command']=$command['incoming'];
	}
	return $info;
}

function sEcho($out, $newline=true){
	if($newline){
		echo("\n");
	}
	if(!$GLOBALS["Silent"]){
		print_r($out);
	}
}

function socketcheck($socket){
	$info = stream_get_meta_data($socket);
	return $info['eof'];
	//return(feof($socket));
}

function none($message)
{
	//This function intentionally left blank
	//This is where the handlers will fall to for now. I plan on including a more
	//efficent check to avoid the apparent stack jumps that this code will produce
	//But for now, just fall into here, and be happy
	return;
}

?>
Return current item: PHP TOC Library