PHP YMSG Class

From D3xt3r01.tk
Jump to navigationJump to search

WHY

I remember asking some people ( lamers probably ) about how is a yahoo robot actually made ? And they replied "tcpdump" .. I asked them to explain and help me ... I just wanted to see how the protocol actually works ... none helped like this was a big state secret. Then I remembered pidgin is open source .. so are their libraries .. and finally found someone to help .. so in about 2 days this is the result.

I hope you do know how to read php and use tcpdump. Once you read this code ( pretty verbose ) you should have a general idea of what does what, where and how !

WHAT

This is the main class with a usage example. The class includes some basic functions of a client ( sending/receiving messages ) ..

<?php

/*
*
* @author: Dexter<dexter@d3xt3r01.tk>
* @date: 25.06.2009 3:54 AM
* @Description: Basic class with some functions to connect to yahoo servers. Don't rip the credits.
*
*/

class YMSG{
    // Login stuff
    protected $user = NULL;
    protected $pass = NULL;

    // Details info
    private $verbtype = "Y-m-d H:i:s"; // Output date type for verbosity
    private $verbose = 0; // 0 = no Debug messages ; 1 = Debug messages ; 2 = include curl verbose

    // Protocol info
    protected $version = "\x10"; // In hex ! 16 = 10 => YMSG16 ; 15 - 0f => YMSG15
    protected $key = "\x00\x00\x00\x00"; // initial Key
    protected $delim = "\xC0\x80"; // Packet delimitator

    // Connection info
    protected $status = 0; // 1 = Online ; 0 = Invisible
    protected $newtoken = 0; // 0 = Use old token if available ; 1 = Always get new token
    protected $connected = 0; // 0 - Disconnected ; 1 - Connected

    // Connection Variables
    private $challenge = NULL; // The seed
    private $crumb = NULL; // Crumb
    private $y = NULL; // One of the cookies
    private $t = NULL; // Another cookie
    private $string307 = NULL; // Calculated string for auth
    private $token = NULL; // Connection token

    // Yahoo Variables
    private $buddylist = NULL;
    private $ignorelist = NULL;
    protected $fname = NULL;
    protected $lname = NULL;
    protected $pinginterval = NULL;
    protected $pingnr = NULL;

    // Resources
    protected $ch = NULL; // Curl Resource
    protected $yahoo_server = 'scs.msg.yahoo.com'; // YMSGR server
    protected $yahoo_port = 5050; // YMSGR port
    protected $conn_yahoo = NULL; // Socket Resource

    // Colors
    protected $black = "\033[30m";
    protected $red = "\033[31m";
    protected $green = "\033[32m";
    protected $blue = "\033[34m";
    protected $magenta = "\033[35m";
    protected $cyan = "\033[36m";
    protected $white = "\033[37m";


    protected function verblog($message, $color = "white"){
        switch($color){
            case "black":
                $color = $this->black;
                break;
            case "red":
                $color = $this->red;
                break;
            case "green":
                $color = $this->green;
                break;
            case "blue":
                $color = $this->blue;
                break;
            case "magenta":
                $color = $this->magenta;
                break;
            case "cyan":
                $color = $this->cyan;
                break;
            case "white":
            default:
                $color = $this->white;
                break;
        }
        if($this->verbose > 0){
            echo date($this->verbtype)." ".$color.$message.$this->white."\n";
        }
        return TRUE;
    }

    public function usenewtoken($token){
        if($token == 0 || $token == 1){
            if($token == 0){
                $this->verblog("usenewtoken() Use old token if available.", 'blue');
            }else{
                $this->verblog("usenewtoken() Always get new token.", 'blue');
            }
            $this->newtoken = $token;
        }
        return TRUE;
    }

    public function ConnectedStatus(){
        return $this->connected;
    }

    private function verbtype($type){
        $this->verblog("verbtype() Setting Verbosity date type to ".$type." .", 'blue');
        $this->verbtype = $type;
    }

    public function YahooUser($user){
        $this->user = trim($user);
        $this->verblog("YahooUser() set to ".$this->user, 'blue');
    }

    public function YahooPass($pass){
        $this->pass = trim($pass);
        $this->verblog("YahooPass() set pass to ".$this->pass, 'blue');
    }

    public function Verbosity($verbose){
        switch($verbose){
            case 0:
                if($this->verbose == 0){
                    echo "Verbosity already off.\n";
                }else{
                    echo "Verbosity turned off.\n";
                    $this->verbose = 0;
                }
                break;
            case 1:
                if($this->verbose > 0){
                    echo "Verbosity already on.\n";
                }else{
                    echo "Verbosity turned on (L1).\n";
                    $this->verbose = 1;
                }
                break;
            case 2:
                if($this->verbose > 1){
                    echo "Verbosity already at L2.\n";
                }else{
                    echo "Verbosity set at L2.\n";
                    $this->verbose = 2;
                }
                break;
            default:
                echo "Unknown verbosity value\n";
                return FALSE;
                break;
        }
        return TRUE;
    }
    
    private function MyCurlInit(){
        if(($this->ch = curl_init()) === FALSE){
            $this->verblog("MyCurlInit() Failed to initialize curl session.", 'red');
            return FALSE;
        }
        $this->verblog("MyCurlInit() Created curl session.", 'green');
    }

    private function MyCurlGet($url){
        if(!is_resource($this->ch)){
            $this->verblog("MyCurlGet() CH isn't a valid resource.", 'red');
            if(($this->MyCurlInit()) === FALSE){
                $this->verblog("MyCurlGet()::MyCurlInit() failed creating again.", 'red');
                return FALSE;
            }
        }
            curl_setopt($this->ch, CURLOPT_URL, $url);
            curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
        if($this->verbose > 1){
                curl_setopt($this->ch, CURLOPT_VERBOSE, 1);
        }
            return(curl_exec($this->ch));
    }


    private function MyCurlClose(){
        $this->verblog("MyCurlClose() Closed curl resource.", 'green');
        curl_close($this->ch);
        return TRUE;
    }

    public function ascii2hex($ascii){
        $hex = '';
            for($i=0;$i<strlen($ascii);$i++){
            $byte = dechex(ord($ascii{$i}));
            $byte = str_repeat('0', 2 - strlen($byte)).$byte;
            $hex .= $byte;
        }
            return($hex);
    }

    public function hex2ascii($hex){
        $ascii = '';
        $hex = str_replace(" ", "", $hex);
        for($i=0;$i<strlen($hex);$i=$i+2){
            $ascii .= chr(hexdec(substr($hex, $i, 2)));
        }
        return($ascii);
    }

    private function SockINIT(){
        $this->verblog("YahooConnect() Creating conn_yahooo socket.", 'blue');
        if(($this->conn_yahoo = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === FALSE){
            $this->verblog("SockINIT()::socket_create() failed with reason: ".socket_strerror(socket_last_error($this->conn_yahoo)), 'red');
                return FALSE;
        }
        if((@socket_connect($this->conn_yahoo, $this->yahoo_server, $this->yahoo_port)) === FALSE){
            $this->verblog("SockINIT()::socket_connect() failed with reason: ".socket_strerror(socket_last_error($this->conn_yahoo)), 'red');
                return FALSE;
        }
        socket_set_option($this->conn_yahoo, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 5, "usec" => 0));
        $this->verblog("SockINIT() created connection socket.", 'green');
        return TRUE;
    }

    private function sendsock($packet){
        if(!is_resource($this->conn_yahoo)){
            $this->verblog("sendsock() If conn_yahoo isn't a resource, I can't work with it.", 'red');
            return FALSE;
        }
            $header = substr($packet, 11, 1);
            $this->key = substr($packet, 16, 4);
                $this->verblog("CLIENT > SERVER: Sending Packet Size: ".strlen($packet)." Bytes", 'magenta');
                $this->verblog("CLIENT > SERVER: Sending Header: 0x".strtoupper($this->ascii2hex($header)), 'magenta');
        $this->verblog("CLIENT > SERVER: Session: ".$this->ascii2hex($this->key), 'magenta');
        $this->verblog("CLIENT > SERVER: Sending Packet: ".substr($packet, 20), 'magenta');
        if($this->verbose > 1){
            $this->verblog("CLIENT > SERVER: FULL Sending packet in HEX:\n".$this->ascii2hex($packet), 'magenta');
        }
            socket_write($this->conn_yahoo, $packet, strlen($packet));
            return TRUE;
    }

    private function recvsock(){
        if(!is_resource($this->conn_yahoo)){
            $this->verblog("recvsock() Conn_yahoo isn't a resource. I can't work with it.", 'red');
            return FALSE;
        }
        $return = '';
        do{
            if(!empty($return)){
                $this->verblog("recvsock() Packet didn't finish in C080 Getting next.", 'blue');
            }
                if(($return .= socket_read($this->conn_yahoo, 1441)) === FALSE){
                $this->verblog("recvsock() Error reading.", 'red');
                return FALSE;
            }
            if(substr($return, 11, 1) == "\x4C" || empty($return)){ break; }
            usleep(100);
        }while(substr($return, -2) != "\xC0\x80" && substr($return, -3) != "\xC0\x80\x00");
        if(empty($return)){ return FALSE; }
        $packetcount = substr_count($return, "YMSG\x00\x10\x00");
        if($packetcount > 1){
            $this->verblog("SERVER > CLIENT: Received ".$packetcount." packets from server.", 'cyan');
            $return = explode("YMSG\x00\x10\x00", $return);
            for($i = 1; $i <= $packetcount; $i++){
                $packet[$i] = "YMSG\x00".$this->version."\x00".$return[$i];
                    $header = substr($packet[$i], 11, 1);
                    $this->key = substr($packet[$i], 16, 4);
                        $this->verblog("SERVER > CLIENT: [".$i."] Receiving Packet Size: ".strlen($packet[$i])." Bytes", 'cyan');
                        $this->verblog("SERVER > CLIENT: [".$i."] Receiving Header: 0x".strtoupper($this->ascii2hex($header)), 'cyan');
                $this->verblog("SERVER > CLIENT: [".$i."] Session: ".$this->ascii2hex($this->key), 'cyan');
                $this->verblog("SERVER > CLIENT: [".$i."] Receiving Packet: ".substr($packet[$i], 20), 'cyan');
                if($this->verbose > 1){
                    $this->verblog("SERVER > CLIENT: [".$i."] FULL Receiving packet in HEX:\n".$this->ascii2hex($packet[$i]), 'cyan');
                }
                $packet[$i] = array($header, $packet[$i]);
            }
            return $packet;
        }else if(strlen($return) > 0){
                $header = substr($return, 11, 1);
                $this->key = substr($return, 16, 4);
                    $this->verblog("SERVER > CLIENT: Receiving Packet Size: ".strlen($return)." Bytes", 'cyan');
                    $this->verblog("SERVER > CLIENT: Receiving Header: 0x".strtoupper($this->ascii2hex($header)), 'cyan');
            $this->verblog("SERVER > CLIENT: Session: ".$this->ascii2hex($this->key), 'cyan');
            $this->verblog("SERVER > CLIENT: Receiving Packet: ".substr($return, 20), 'cyan');
            if($this->verbose > 1){
                $this->verblog("SERVER > CLIENT: FULL Receiving packet in HEX:\n".$this->ascii2hex($return), 'cyan');
            }
                return(array($header, $return));
        }else{
            $this->verblog("SERVER->CLIENT: There was a problem here.", 'red');
            return FALSE;
        }
    }

    private function SockClose(){
        if(!is_resource($this->conn_yahoo)){
            $this->verblog("Can't close conn_yahoo if it's not a socket resource.", 'red');
            return FALSE;
        }
        $this->verblog("Closing conn_yahoo socket.", 'green');
        socket_close($this->conn_yahoo);
        $this->connected = 0;
        return TRUE;
    }

    private function Y64E($source){
        $yahoo64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._";
        $inlen = 16;
        $in = 0;
        $dest = "";
        for(; $inlen >=3; $inlen -=3){
            $dest .= $yahoo64[ord($source[$in])>>2];
            $dest .= $yahoo64[((ord($source[$in])<<4)&0x30) | (ord($source[$in+1])>>4)];
            $dest .= $yahoo64[((ord($source[$in+1])<<2)&0x3C) | (ord($source[$in+2])>>6)];
            $dest .= $yahoo64[ord($source[$in+2])&0x3F];
            $in += 3;
        }
        if($inlen > 0){
            $dest .= $yahoo64[ord($source[$in])>>2];
            $fragment = ((ord($source[$in])<<4)&0x30);
            if($inlen > 1){
                $fragment |= (ord($source[$in+1])>>4);
            }
            $dest.=$yahoo64[$fragment];
            if($inlen < 2){
                $dest .= "-";
            }else{
                $dest .= $yahoo64[((ord($source[$in+1])<<2)&0x3c)];
            }
            $dest .= "-";
        }
        return($dest);
    }

    private function pachet($header, $packet = ''){
        if(empty($header)){
            $this->verblog("pachet() Empty header.", 'red');
            return FALSE;
        }
        if(strlen($header) != 1){
            $this->verblog("pachet() Wrong packet length.", 'red');
            return FALSE;
        }
        $value = "YMSG"; // Start # 4 bytes
        $value .= "\x00"; // NULL # 1 byte
            $value .= $this->version; // Version # 1 byte
            $value .= str_repeat("\x00", 2); // 2 NULLs # 2 bytes
            $value .= chr(intval(strlen($packet)/256)).chr(fmod(strlen($packet),256)); // Size # 2 bytes
            $value .= "\x00"; // NULL # 1 byte
            $value .= $header; // Packet type # 1 byte
            if($this->status == 0){
                    $value .= "\x00\x00\x00\x0C"; // 00 00 00 0C ( Invisible ) # 4 bytes
            }else{
                    $value .= str_repeat("\x00", 4); // 4 NULLs ( Available ) # 4 bytes
            }
            $value .= $this->key; // The Session Key # 4 bytes
        if(strlen($value) != 20){
            $this->verblog("pachet() Malformed 20byte packet header: ".$this->ascii2hex($value)." ".strlen($value)." size.", 'red');
            $this->verblog("pachet() Packet content: ".$this->ascii2hex($value.$packet), 'red');
            return FALSE;
        }
            return $value.$packet;
    }

    protected function YahooVRFY(){
        if($this->connected == 1){
            $this->verblog("YahooVRFY() Don't do this if already connected.", 'red');
            return FALSE;
        }
        if(!is_resource($this->conn_yahoo)){
            $this->verblog("YahooVRFY() Can't verify if there is no connection.", 'red');
            return FALSE;
        }
        $this->verblog("YahooConnect() Sending VRFY 0x4C packet.", 'green');
        if(($this->sendsock($this->pachet("\x4C"))) === FALSE){
            $this->verblog("YahooVRFY() Problem sending packet.", 'red');
            return FALSE;
        }
        $return = $this->recvsock();
        if($return[0] != "\x4C"){
            $this->verblog("YahooVRFY() Expected 0x4C but got 0x".$this->ascii2hex($return[0]), 'red');
            return FALSE;
        }else{
            return $return[1];
        }
    }

    protected function processtokenerrors($error){
        switch($error){
            case 1212:
                $this->verblog("processtokenerrors() Invalid ID or password. Please try again.", 'red');
                return FALSE;
                break;
            case 1213:
                $this->verblog("processtokenerrors() As a security precaution please enter your Yahoo! ID and password and type in the code you see in the picture below.", 'red');
                return FALSE;
                break;
            case 1214:
                $this->verblog("processtokenerrors() Invalid ID or password. Please try again and type the text you see in the picture below", 'red');
                return FALSE;
                break;
            case 1235:
                $this->verblog("processtokenerrors() This ID is not yet taken", 'red');
                return FALSE;
                break;
            case 1236:
                $this->verblog("processtokenerrors() Invalid ID or password. Please try again.", 'red');
                return FALSE;
                break;
            case 100:
                $this->verblog("processtokenerrors() Required field missing", 'red');
                return FALSE;
                break;
            default:
                $this->verblog("processtokenerrors() No errors, continue.", 'red');
                return TRUE;
                break;
        }
        return TRUE;
    }

    protected function getyt(){
        if($this->connected == 1){
            $this->verblog("getyt() Don't do this if already connected.", 'red');
            return FALSE;
        }
        if(($this->MyCurlInit()) === FALSE){
            $this->verblog("getyt()::MyCurlInit() Can't create resource.", 'red');
            return FALSE;
        }
        $fh = @file_get_contents("yahoo_tokens");
        $search = "|".$this->user.":([^\n]*)|is";
        if($this->newtoken == 1){
            $this->verblog("getyt() Always getting new token.", 'blue');
            $ourtoken = $this->MyCurlGet('https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=&login='.$this->user.'&passwd='.urlencode($this->pass));
            $this->processtokenerrors($ourtoken);
            preg_match_all("|ymsgr=([^\n]*)\n|", $ourtoken, $token);
            if(empty($token[1][0])){
                $this->verblog("getyt() Got empty token: ".trim($ourtoken), 'red');
                return FALSE;
            }else{
                $this->token = trim($token[1][0]);
                $this->verblog("getyt() Token set to ".$this->token, 'green');
                $fh = fopen("yahoo_tokens", "a+");
                fwrite($fh, $this->user.":".$this->token."\n");
                fclose($fh);
                $this->verblog("getyt() Token saved to file.", 'green');
            }
        }else if(!preg_match($search, $fh, $out)){
            $this->verblog("getyt() No saved token, getting one.", 'blue');
            $ourtoken = $this->MyCurlGet('https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=&login='.$this->user.'&passwd='.urlencode($this->pass));
            $this->processtokenerrors($ourtoken);
            preg_match_all("|ymsgr=([^\n]*)\n|", $ourtoken, $token);
            if(empty($token[1][0])){
                $this->verblog("getyt() Got empty token: ".trim($ourtoken), 'red');
                return FALSE;
            }else{
                $this->token = trim($token[1][0]);
                $this->verblog("getyt() Token set to ".$this->token, 'green');
                $fh = fopen("yahoo_tokens", "a+");
                fwrite($fh, $this->user.":".$this->token."\n");
                fclose($fh);
                $this->verblog("getyt() Token saved to file.", 'green');
            }
        }else{
            $this->token = trim($out[1]);
            $this->verblog("getyt() Using already saved token: ".$out[0], 'green');
            $this->verblog("getyt() Token set to: ".$this->token, 'green');
        }
        $yt307 = $this->MyCurlGet('https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=&token='.$this->token);
        if($this->verbose > 1){
            $this->verblog($yt307);
        }
        if(!preg_match_all("|crumb=([^\n]*)\nY=([^;]*);([^\n]*)\nT=([^;]*);|s", $yt307, $yt)){
            $this->verblog("getyt() Existing token is invalid, getting new one.", 'blue');
            $ourtoken = $this->MyCurlGet('https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=&login='.$this->user.'&passwd='.urlencode($this->pass));
            preg_match_all("|ymsgr=([^\n]*)\n|", $ourtoken, $token);
            if(empty($token[1][0])){
                $this->verblog("getyt() Got empty token: ".trim($ourtoken), 'red');
                return FALSE;
            }else{
                $this->token = trim($token[1][0]);
                $this->verblog("getyt() Token set to ".$this->token, 'green');
                $yahoo_tokens = file_get_contents("yahoo_tokens");
                $yahoo_tokens = preg_replace('|'.$this->user.':(.*)\n|', $this->user.":".$this->token."\n", $yahoo_tokens);
                $fh = fopen("yahoo_tokens", "w+");
                fwrite($fh, $yahoo_tokens);
                fclose($fh);
                $this->verblog("getyt() Old saved token replaced.", 'green');
            }
            $yt307 = $this->MyCurlGet('https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=&token='.$this->token);
            preg_match_all("|crumb=([^\n]*)\nY=([^;]*);([^\n]*)\nT=([^;]*);|s", $yt307, $yt);
        }
        $this->MyCurlClose();
        if(empty($yt[1][0])){
            $this->verblog("getyt() Empty crumb.");
            return FALSE;
        }else{
            $this->crumb = trim($yt[1][0]);
            $this->verblog("getyt() Crumb set to ".$this->crumb);
        }

        if(empty($yt[2][0])){
            $this->verblog("getyt() Empty Y cookie.");
            return FALSE;
        }else{
            $this->y = $yt[2][0];
            $this->verblog("getyt() Y set to ".$this->y);
        }
        if(empty($yt[4][0])){
            $this->verblog("getyt() Empty T cookie.");
            return FALSE;
        }else{
            $this->t = $yt[4][0];
            $this->verblog("getyt() T set to ".$this->t);
        }
        return TRUE;
    }

    protected function gen307(){
        if(!$this->getyt()){
            $this->verblog("gen307()::getyt Getting CRUMB, Y and T");
            return FALSE;
        }
        $this->verblog("YahooConnect() Getting Y, T, Crumb and generating String307.");
        if($this->verbose > 1){
            $this->verblog("gen307() Step1: crumb.challenge : ".$this->crumb.$this->challenge);
            $this->verblog("gen307() Step2: md5(crumb.challenge): ".md5($this->crumb.$this->challenge));
            $this->verblog("gen307() Step3: hex2ascii(md5(crumb.challenge)): ".$this->hex2ascii(md5($this->crumb.$this->challenge)));
            $this->verblog("gen307() Step4: y64e(hex2ascii(md5(crumb.challenge))): ".$this->Y64E($this->hex2ascii(md5($this->crumb.$this->challenge))));
        }
        $this->string307 = $this->Y64E($this->hex2ascii(md5($this->crumb.$this->challenge)));
        $this->verblog("genyt307() String307 set to ".$this->string307." .");
        return TRUE;
    }

    private function YahooAUTH(){
        if($this->connected == 1){
            $this->verblog("YahooAUTH() Can't be used if already connected.", 'red');
            return FALSE;
        }
        if(!is_resource($this->conn_yahoo)){
            $this->verblog("YahooAUTH()::SockINIT() Can't auth without an open socket.", 'red');
            return FALSE;
        }
        $this->verblog("YahooConnect() Sending AUTH 0x57 packet.", 'green');
            $packet = "1".$this->delim.$this->user.$this->delim;
        $this->sendsock($this->pachet("\x57", $packet));
        $return = $this->recvsock();
        if($return[0] != "\x57"){
            $this->verblog("YahooAUTH() Expected 0x57 on return but got 0x".$this->ascii2hex($return[0]), 'red');
            return FALSE;
        }
        if($this->hex2ascii($this->key) == "00000000"){
            $this->verblog("YahooAUTH() Empty KEY.", 'red');
            return FALSE;
        }
        if(!stristr($return[1], "\xC0\x8094\xC0\x80")){
            $this->verblog("YahooAUTH() Expected to have 0xC0 0x80 94 0xC0 0x80.", 'red');
            return FALSE;
        }
        preg_match_all("|\xC0\x8094\xC0\x80(.*)\xC0\x80|", $return[1], $challenge);
        if(empty($challenge[1][0])){
            $this->verblog("YahooAUTH() Challenge is empty.", 'red');
            return FALSE;
        }else{
            $this->challenge = trim($challenge[1][0]);
            $this->verblog("YahooAUTH() Challenge set to ".$this->challenge, 'green');
        }
        return TRUE;
    }

    private function YahooLogin(){
        if($this->connected == 1){
            $this->verblog("YahooLogin() don't do this if you're already connected.", 'red');
            return FALSE;
        }
        if(!is_resource($this->conn_yahoo)){
            $this->verblog("YahooLogin() Can't work if conn_yahoo isn't a resource.", 'red');
            return FALSE;
        }
        $this->verblog("YahooConnect() Sending Login 0x54 packet.");
            $packet = "1".$this->delim.$this->user.$this->delim;
            $packet .= "0".$this->delim.$this->user.$this->delim;
            $packet .= "277".$this->delim.$this->y."; path=/; domain=.yahoo.com".$this->delim;
            $packet .= "278".$this->delim.$this->t."; path=/; domain=.yahoo.com".$this->delim;
            $packet .= "307".$this->delim.$this->string307.$this->delim;
            $packet .= "244".$this->delim."4194239".$this->delim;
            $packet .= "2".$this->delim.$this->user.$this->delim;
            $packet .= "2".$this->delim."1".$this->delim;
            $packet .= "98".$this->delim."us".$this->delim;
            $packet .= "135".$this->delim."9.0.0.2162".$this->delim;
            $this->sendsock($this->pachet("\x54", $packet));
        $return = $this->recvsock();
        if($return[0] != "\x55"){
            $this->verblog("YahooLogin() expects a 0x55 but got 0x".$this->ascii2hex($return[0])." .");
            return FALSE;
        }else{
            preg_match_all('|c080323136c080(.*)c080323534c080(.*)c080323735c080|is', $this->ascii2hex($return[1]), $out);
            $this->fname = $this->hex2ascii($out[1][0]);
            $this->verblog("YahooLogin() First name set to: ".$this->fname);
            $this->lname = $this->hex2ascii($out[2][0]);
            $this->verblog("YahooLogin() Last name set to: ".$this->lname);
            return TRUE;
        }
    }

    private function getusergroup($user){
        foreach($this->buddylist as $buddylist => $name){
            foreach($name as $userul => $info){
                if($userul == $user){
                    return $buddylist;
                }
            }
        }
        return FALSE;
    }

    public function YahooBuddyList($packet = NULL){
        // We may receive multiple packets here.
        if(!is_resource($this->conn_yahoo)){
            $this->verblog("YahooBuddyList() Can't work if conn_yahoo isn't a resource.");
            return FALSE;
        }
        if($this->connected == 1){
            return($this->buddylist);
        }
        switch($packet[0]){
            case "\xF1":
                $this->verblog("YahooBuddyList() (0xF1) Parsing Buddy list.");
                $packet = $this->ascii2hex($packet[1]);
                preg_match_all('|c080333030c080333138c080([a-z0-9]+?)c080333033c080333139c080|', $packet, $outf1);
                if(is_array($outf1[1]) && !empty($outf1[1][0])){
                    foreach($outf1[1] as $list){
                        preg_match('|3635c080(.*)c080333032c080333139c080|', $list, $name);
                        $name = $this->hex2ascii($name[1]);
                        preg_match_all('|c080333030c080333139c08037c080([a-z0-9]+?)c080333031c080333139|', $list, $buddys);
                        foreach($buddys[1] as $buddy){
                            $buddy = $this->hex2ascii($buddy);
                            $status = "offline";
                            if(stristr($buddy, "\xC0\x80223\xC0\x801")){
                                $buddy = str_replace("\xC0\x80223\xC0\x801", '', $buddy);
                                $status = "Didn't accept your add request yet.";
                            }
                            $buddylist[$name][$buddy] = NULL;
                            $this->buddylist[$name][$buddy]['status'] = $status;
                            $status = NULL;
                        }
                        $name = NULL;
                    }
                }
                preg_match_all('|c080333030c080333230c08037c080([a-z0-9]+?)c080333031c080333230|', $packet, $ignored);
                if(is_array($ignored[1]) && !empty($ignored[1][0])){
                    foreach($ignored[1] as $person){
                        $this->ignorelist[] = $this->hex2ascii($person);
                    }
                }
                $outf1 = NULL;
                break;
            case "\xF0":
                $this->verblog("YahooBuddyList() (0xF0) Parsing Buddy statuses.");
                $packet = $this->ascii2hex($packet[1]);
                preg_match_all('|c080333030c080333135c08037c080([a-z0-9]+?)c0803130c080([a-f0-9]+?)c080([a-f0-9]+)c080333031c080333135|', $packet, $outf0);
                if(is_array($outf0[1]) && !empty($outf0[1][0])){
                    foreach($outf0[1] as $key => $user){
                        $user = $this->hex2ascii($user);
                        $buddylist = $this->getusergroup($user);
                        $this->buddylist[$buddylist][$user]['status'] = "online";
                        switch($outf0[2][$key]){
                            case "31":
                                $msg = "(AWAY) Be Right Back";
                                break;
                            case "32":
                                $msg = "(AWAY) Busy";
                                break;
                            case "33":
                                $msg = "(AWAY) Not At Home";
                                break;
                            case "34":
                                $msg = "(AWAY) Not At Desk";
                                break;
                            case "35":
                                $msg = "(AWAY) Not in Office";
                                break;
                            case "36":
                                $msg = "(AWAY) On the Phone";
                                break;
                            case "37":
                                $msg = "(AWAY) On Vacation";
                                break;
                            case "38":
                                $msg = "(AWAY) Out to lunch";
                                break;
                            case "39":
                                $msg = "(AWAY) Stepped out";
                                break;
                            case "3939":
                                preg_match('|c0803139c080([a-f0-9]+?)c0803937c08031c080|is', $outf0[3][0], $sts);
                                $msg = "(AVAILABLE) ".$this->hex2ascii($sts[1]);
                                break;
                            default:
                                $msg = "";
                                break;
                        }
                        $this->buddylist[$buddylist][$user]['message'] = $msg;
                    }
                }
                break;
            default:
                return FALSE;
                break;
        }
        return TRUE;
    }

    public function YahooKeepAlive(){
        // This has to be send every 60 seconds.
        if($this->connected == 0){
            $this->verblog("YahooKeepAlive() Can't do this if not connected.");
            return FALSE;
        }
        $this->verblog("YahooKeepAlive() Sending Keep Alive packet (0x8A) .");
        $packet = "0".$this->delim.$this->user.$this->delim;
        return $this->sendsock($this->pachet("\x8A", $packet));
    }

    public function YahooAddAbuddy($dest, $msg = '', $list = 'Buddies'){
        if($this->connected == 0){
            $this->verblog("YahooAddABuddy() Can't do this if not connected.", 'red');
            return FALSE;
        }
        if(empty($dest)){
            $this->verblog("YahooAddABuddy() No user given.", 'red');
            return FALSE;
        }
        $slist = $this->getusergroup($dest);
        if(!empty($slist)){
            $this->verblog("YahooAddABuddy() Can't add ".$dest." since he/she already is in '".$slist."'", 'red');
            return FALSE;
        }
        if(!empty($msg)){
            $this->verblog("YahooAddABuddy() Adding ".$dest." in ".$list." with message: ".$msg, 'green');
        }else{
            $this->verblog("YahooAddABuddy() Adding ".$dest." in ".$list, 'green');
        }
            $packet = "1".$this->delim.$this->user.$this->delim;
            $packet .= "14".$this->delim.$msg.$this->delim;
            $packet .= "65".$this->delim.$list.$this->delim;
            $packet .= "97".$this->delim."1".$this->delim;
        if(!empty($this->fname)){
            $packet .= "216".$this->delim.$this->fname.$this->delim;
        }
        if(!empty($this->lname)){
            $packet .= "254".$this->delim.$this->lname.$this->delim;
        }
            $packet .= "302".$this->delim."319".$this->delim;
            $packet .= "300".$this->delim."319".$this->delim;
            $packet .= "7".$this->delim.$dest.$this->delim;
            $packet .= "301".$this->delim."319".$this->delim;
            $packet .= "303".$this->delim."319".$this->delim;
            return $this->sendsock($this->pachet("\x83", $packet));
    }

    public function YahooDenyABuddy($dest, $msg = ''){
        // The great fun here is that even after you have accepted the add request, you can still deny it and remove yourself from his list.
        if($this->connected == 0){
            $this->verblog("YahooDenyABuddy() Can't do this if not connected.");
            return FALSE;
        }
        if(empty($dest)){
            $this->verblog("YahooDenyABuddy() No user given.");
            return FALSE;
        }
        if(empty($msg)){
            $this->verblog("YahooDenyABuddy() Denying buddy ".$dest);
        }else{
            $this->verblog("YahooDenyABuddy() Denying buddy ".$dest." with message: ".$msg);
        }
            $packet = "1".$this->delim.$this->user.$this->delim;
            $packet .= "5".$this->delim.$dest.$this->delim;
            $packet .= "13".$this->delim."2".$this->delim; // Reject Authorization
        if(!empty($msg)){
                $packet .= "14".$this->delim.$msg.$this->delim;
        }
            return $this->sendsock($this->pachet("\xD6", $packet));
    }

    private function YahooAddABuddyRequest($packet){
        if(empty($packet[1])){
            $this->verblog("YahooAddABuddyRequest() No packet given.");
            return FALSE;
        }
        if($packet[0] != "\xD6"){
            $this->verblog("YahooAddABuddyRequest() You've given me a wrong packet type to parse, I need 0xD6, got 0x".$this->ascii2hex($packet[0]));
            return FALSE;
        }
        $packet = $this->ascii2hex($packet[1]);
        preg_match('|34c080([a-f0-9]+?)c08035c080([a-f0-9]+?)c080|is', $packet, $request);
        if(stristr($packet, 'c0803133c08032c080')){
            if(preg_match('|c0803134c080([a-f0-9]+?)c080|is', $packet, $message)){
                $this->verblog("YahooAddABuddyRequest() ".$this->hex2ascii($request[1])." denied our add buddy request: ".$this->hex2ascii($message[1]), 'red');
            }else{
                $this->verblog("YahooAddABuddyRequest() ".$this->hex2ascii($request[1])." denied our request.", 'red');
            }
            unset($this->buddylist[$this->getusergroup($this->hex2ascii($request[1]))][$this->hex2ascii($request[1])]);
            return TRUE;
        }
        if(isset($request[1]) && isset($request[2]) && $this->hex2ascii($request[2]) == $this->user){
            if(stristr($packet, 'c080323136c080')){
                preg_match('|c080323136c080([a-f0-9]+?)c080|is', $packet, $fname);
                $fname = $this->hex2ascii($fname[1]);
            }
            if(stristr($packet, 'c080323534c080')){
                preg_match('|c080323534c080([a-f0-9]+?)c080|is', $packet, $lname);
                $lname = $this->hex2ascii($lname[1]);
            }
            if(stristr($packet, 'c0803134c080')){
                preg_match('|c0803134c080([a-f0-9]+?)c080|is', $packet, $message);
                $message = $this->hex2ascii($message[1]);
            }
            $reply = "YahooAddABuddyRequest() ".$this->hex2ascii($request[1]);
            if((isset($fname) && !empty($fname)) || (isset($lname) && !empty($lname))){
                $reply .= " (";
                            if((isset($fname) && !empty($fname)) && (isset($lname) && !empty($lname))){
                    $reply .= $fname." ".$lname;
                }else{
                    if(isset($fname) && !empty($fname)){
                        $reply .= $fname;
                    }else{
                        $reply .= $lname;
                    }
                }
                $reply .= ")";
            }

            if(isset($message[1]) && !empty($message[1])){
                $reply .= " wants to add you to his/hers buddy list: ".$message;
            }else{
                $reply .= " wants to add you to his/hers buddy list.";
            }
            $this->verblog($reply);
        }else{
            $this->verblog("YahooAddABuddyRequest() Error getting buddy request.");
            return FALSE;
        }
        return TRUE;
    }

    public function YahooRemoveABuddy($user){
        if($this->connected == 0){
            $this->verblog("YahooRemoveABuddy() Unable to process this if not connected.");
            return FALSE;
        }
        if(!$this->getusergroup($user)){
            $this->verblog("YahooRemoveABuddy() ".$user." isn't in your buddy list.");
            return FALSE;
        }
        $group = $this->getusergroup($user);
        $packet = "1".$this->delim.$this->user.$this->delim;
        $packet .= "7".$this->delim.$user.$this->delim;
        $packet .= "65".$this->delim.$group.$this->delim;
        $packet .= "66".$this->delim."0".$this->delim;
        $this->verblog("YahooRemoveABuddy() Removing ".$user." from your '".$group."' list.");
        unset($this->buddylist[$group][$user]);
        return $this->sendsock($this->pachet("\x84", $packet));
    }

    public function YahooAvatarLink($dest){
        if($this->connected == 0){
            $this->verblog("YahooAvatarLink() Can't do this if not connected.");
            return FALSE;
        }
        if(empty($dest)){
            $this->verblog("YahooAvatarLink() No user given.");
            return FALSE;
        }
        $this->verblog("YahooAvatarLink() Getting ".$dest."'s avatar link.");
        // C0 $packeti="1".$delim.$user.$delim."5".$delim.$vict.$delim."198".$delim."0".$delim.'197'.$delim.$delim; // not working anymore
        // C1 $packeti="1".$delim.$user.$delim."5".$delim.$vict.$delim."206".$delim."2".$delim; // not working anymore
        // BE $packeti="1".$delim.$user.$delim."5".$delim.$vict.$delim."13".$delim."1".$delim; // Only works for people using yahoo messenger
        $packet = "1".$this->delim.$this->user.$this->delim;
        $packet .= "5".$this->delim.$dest.$this->delim;
        $packet .= "13".$this->delim."1".$this->delim;
        return $this->sendsock($this->pachet("\xBE", $packet));
    }

    public function YahooPrivateMessage($dest, $msg){
        /*
             63 - imvironment  string;11
             64 - imvironment enabled/allowed
                        0 - enabled imwironment ;0 - no imvironment
                        2 - disabled                '' - empty cause we don;t do these
        */
        if($this->connected == 0){
            $this->verblog("YahooPrivateMessage() Can't do this if not connected.");
            return FALSE;
        }
        if(empty($dest)){
            $this->verblog("YahooPrivateMessage() No user given.");
            return FALSE;
        }
        if(empty($msg)){
            $this->verblog("YahooPrivateMessage() No message given.");
            return FALSE;
        }
        $this->verblog("YahooPrivateMessage() Sending to ".$dest." message: ".$msg);
            $packet = "1".$this->delim.$this->user.$this->delim;
            $packet .= "5".$this->delim.$dest.$this->delim;
            $packet .= '97'.$this->delim.'1'.$this->delim;
            $packet .= "14".$this->delim.$msg.$this->delim;
            $packet .= '63'.$this->delim.';0'.$this->delim;
            $packet .= '64'.$this->delim.'0'.$this->delim;
            $packet .= '1002'.$this->delim.'1'.$this->delim;
            $packet .= '206'.$this->delim.'0'.$this->delim;
            return $this->sendsock($this->pachet("\x06", $packet));
    }

    private function YahooIncommingMessage($packet){
        if(empty($packet[1])){
            $this->verblog("YahooIncommingMessage() No packet given.");
            return FALSE;
        }
        if($packet[0] != "\x06"){
            $this->verblog("YahooIncommingMessage() You've given me a wrong packet type to parse, I need 0x06, got 0x".$this->ascii2hex($packet[0]));
            return FALSE;
        }
        $this->verblog("YahooIncommingMessage() (0x06) parsing incomming message.");
        $packet = $this->ascii2hex($packet[1]);
        if(stristr($packet, "c0803633c080") && stristr($packet, "c0803634c080")){
            preg_match_all('|34c080([a-f0-9]+?)c08035c080'.$this->ascii2hex($this->user).'c0803134c080([a-f0-9]+?)c080|is', $packet, $messages);
            foreach($messages[1] as $key => $source){
                $this->verblog("YahooIncommingMessage() Message at ".date("Y-m-d H:i:s")." from ".$this->hex2ascii($source)." : ".$this->hex2ascii($messages[2][$key]));
            }
        }else{
            preg_match_all('|3331c08036c0803332c08036c08034c080([a-f0-9]+?)c08035c080'.$this->ascii2hex($this->user).'c0803134c080([a-f0-9]+?)c0803135c080([a-f0-9]+?)c0803937c08031c080|is', $packet, $messages);
            foreach($messages[1] as $key => $source){
                $this->verblog("YahooIncommingMessage() Offline message at ".date("Y-m-d H:i:s", $this->hex2ascii($messages[3][$key]))." from ".$this->hex2ascii($source)." : ".$this->hex2ascii($messages[2][$key]));
            }
        }
        return TRUE;
    }

    private function YahooNewMail($packet){
        if(empty($packet[1])){
            $this->verblog("YahooNewMail() No packet given.");
            return FALSE;
        }
        if($packet[0] != "\x0B"){
            $this->verblog("YahooNewMail() You've given me a wrong packet type to parse, I need 0x0B, got 0x".$this->ascii2hex($packet[0]));
            return FALSE;
        }
        $this->verblog("YahooNewMail() (0x0B) parsing mail number.");
        $packet = $this->ascii2hex($packet[1]);
        if(stristr($packet, "c0803138c080")){
            preg_match('|39c08031c0803138c080([a-f0-9]+?)c0803432c080([a-f0-9]+?)c0803433c080([a-f0-9]+?)c080|is', $packet, $mails);
            $this->verblog("YahooNewMail() You've got a mail from ".$this->hex2ascii($mails[3])." (".$this->hex2ascii($mails[2]).") : ".$this->hex2ascii($mails[1]));
        }else{
            preg_match('|39c080([a-f0-9]+?)c080|is', $packet, $mails);
            if(isset($mails[1]) && is_numeric($mails[1])){
                if($mails[1] != '30'){
                    if($mails[1] > 31){
                        $this->verblog("YahooNewMail() You've got ".$this->hex2ascii($mails[1])." new mails.");
                    }else{
                        $this->verblog("YahooNewMail() You've got ".$this->hex2ascii($mails[1])." new mail.");
                    }
                }else{
                    $this->verblog("YahooNewMail() You've got no new mail.");
                }
            }else{
                $this->verblog("YahooNewMail() Error getting mail number.");
                return FALSE;
            }
        }
        return TRUE;
    }

    private function YahooSkinname(){
        $packet = "211".$this->delim."Skin:Name=Purple\nSettings:StartLaunchcast=0\tShowInsider=0\tAutologin=1\tArchiving=2\tHiddenLogin=1\nEnv:OS=7\nPlugins:ContainerWindowState=0\n";
        return $this->sendsock($this->pachet("\x15", $packet));
    }

    private function YahooPing($packet){
        if(empty($packet[1])){
            $this->verblog("YahooPing() No packet given.", 'red');
            return FALSE;
        }
        if($packet[0] != "\x12"){
            $this->verblog("YahooPing() You've given me a wrong packet type to parse, I need 0x12, got 0x".$this->ascii2hex($packet[0]), 'red');
            return FALSE;
        }        
        $this->verblog("YahooPing() (0x12) parsing incomming ping request.", 'green');
        $packet = $this->ascii2hex($packet[1]);
        preg_match('|313433c080([a-f0-9]+?)c080313434c080([a-f0-9]+?)c080|is', $packet, $pings);
        if(isset($pings[1]) && isset($pings[2]) && is_numeric($this->hex2ascii($pings[1])) && is_numeric($this->hex2ascii($pings[2]))){
            $this->pinginterval = $this->hex2ascii($pings[1]);
            $this->pingnr = $this->hex2ascii($pings[2]);
            $this->verblog("YahooPing() Yahoo wants ".$this->pingnr." ping every ".$this->pinginterval." seconds.");
        }else{
            $this->verblog("YahooPing() Error getting ping numbers.");
            return FALSE;
        }
        return TRUE;
    }

    private function YahooPersonLogOff($packet){
        if(empty($packet[1])){
            $this->verblog("YahooPersonLogOff() No packet given.", 'red');
            return FALSE;
        }
        if($packet[0] != "\x02"){
            $this->verblog("YahooPersonLogOff() You've given me a wrong packet type to parse, I need 0x02, got 0x".$this->ascii2hex($packet[0]), 'red');
            return FALSE;
        }        
        $this->verblog("YahooPersonLogOff() (0x02) parsing incomming log off persson.", 'green');
        $packet = $this->ascii2hex($packet[1]);
        if(preg_match('|37c080([a-f0-9]+?)c080|', $packet, $out)){
            $this->verblog('YahooPersonLogOff() '.$this->hex2ascii($out[1]).' logged off.', 'green');
        }else{
            $this->verblog("YahooPersonLogOff() Regex failed, here's the packet: ".$packet, 'red');
            return FALSE;
        }
        return TRUE;
    }

    public function YahooAddABuddyProcess($packet){
        if($this->connected == 0){
            $this->verblog("YahooAddABuddyProcess() Can't do this if not connected.", 'red');
            return FALSE;
        }
        if($packet[0] != "\x83"){
            $this->verblog("YahooAddABuddyProcess() You've given me a wrong packet type to parse, I need 0x83, got 0x".$this->ascii2hex($packet[0]), 'red');
            return FALSE;
        }
        $packet = $this->ascii2hex($packet[1]);
        if(preg_match('|31c080'.$this->ascii2hex($this->user).'c08037c080([a-f0-9]+?)c0803635c080([a-f0-9]+?)c0803636c080([a-f0-9]+?)c080|', $packet, $out)){
            switch($out[3]){
                case "30":
                    $this->buddylist[$this->hex2ascii($out[2])][$this->hex2ascii($out[1])]['status'] = "Didn't accept your add request yet.";
                    $this->verblog("YahooAddABuddyProcess() Everything's ok, awayting buddy deny/accept.", 'green');
                    return TRUE;
                    break;
                case "32":
                    $this->verblog("YahooAddABuddyProcess() ".$this->hex2ascii($out[1])." is already in the buddy list.", 'red');
                    return FALSE;
                    break;
                case "33":
                    $this->verblog("YahooAddABuddyProcess() ".$this->hex2ascii($out[1])." doesn't exist.", 'red');
                    return FALSE;
                    break;                    
            }
        }else{
            $this->verblog("YahooAddABuddyProcess() Regex failed, here's the packet: ".$packet, 'red');
            return FALSE;
        }
        return TRUE;
    }

    private function YahooDisconnect(){
        $this->verblog("YahooDisconnect() Got disconnection packet.");
        $this->SockClose();
        $this->connected = 0;
    }
    private function ParseAvatarLink($packet){
        if($packet[0] != "\xBE"){
            $this->verblog("ParseAvatarLink() You've given me the wrong packet type to parse, I need 0xBE, got 0x".$this->ascii2hex($packet[0]), 'red');
            return FALSE;
        }
        $avatarlink = explode("c080", $this->ascii2hex($packet[1]));
        $yahooid = $this->hex2ascii($avatarlink[1]);
        $avatarlink = $this->hex2ascii($avatarlink[7]);
        $this->verblog("ParseAvatarLink() ".$yahooid."'s avatar link is: ".$avatarlink, 'green');
        return($avatarlink);
    }

    private function parseaccess($packet){
        switch($packet[0]){
            case "\x02":
                // Person logs off (or goes invisible)
                $this->YahooPersonLogOff($packet);
                break;
            case "\x06":
                // Incomming messages
                $this->YahooIncommingMessage($packet);
                break;
            case "\x0B":
                // Mail notifications
                $this->YahooNewMail($packet);
                break;
            case "\x12":
                // Ping
                $this->YahooPing($packet);
                break;
            case "\x4B":
                // Typing notification ( or other kind )
                break;
            case "\x83":
                // Buddy request response
                $this->YahooAddABuddyProcess($packet);
                break;
            case "\xBD":
                // Avatar checksum
                break;
            case "\xC6":
                // Person status update
                break;
            case "\xD1":
                // Disconnect 
                $this->YahooDisconnect($packet);
                break;
            case "\xD6":
                // Add request
                $this->YahooAddABuddyRequest($packet);
                break;
            case "\xF0":
                // Status updates
            case "\xF1":
                // Buddy List 
                $this->YahooBuddyList($packet);
                break;
            case "\xBE":
                // Avatar link
                $this->ParseAvatarLink($packet);
                break;
            default:
                // Discard the rest
                $this->verblog("parseaccess() Don't know what to do with 0x".$this->ascii2hex($packet[0])." packet.");
                break;
        }
    }

    public function parsepackets(){
        $return = $this->recvsock();
        if(is_array($return[1])){
            foreach($return as $packet){
                $this->parseaccess($packet);
            }
        }else if(!empty($return)){
            $this->parseaccess($return);
        }
        return TRUE;
    }

    public function YahooConnect(){
        if($this->connected == 1){
            $this->verblog("YahooConnect() Can't reconned since I'm already connected.");
            return FALSE;
        }
        if(!$this->SockINIT()){
            $this->verblog("YahooConnect()::SockINIT() Can't create socket.");
            return FALSE;
        }
        usleep(100);
        if(!$this->YahooVRFY()){
            $this->verblog("YahooConnect()::YahooVRFY() failed.");
            $this->YahooDisconnect();
            return FALSE;
        }
        usleep(100);
        if(!$this->YahooAUTH()){
            $this->verblog("YahooConnect()::YahooAUTH() failed.");
            $this->YahooDisconnect();
            return FALSE;
        }
        usleep(100);
        if(!$this->gen307()){
            $this->verblog("YahooConnect()::genyt307() failed.");
            $this->YahooDisconnect();
            return FALSE;
        }
        usleep(100);
        if(!$this->YahooLogin()){
            $this->verblog("YahooConnect()::YahooLogin() failed.");
            $this->YahooDisconnect();
            return FALSE;
        }
        usleep(100);
        if(!$this->YahooSkinname()){
            $this->verblog("YahooConnect()::YahooSkinname() failed.");
            $this->YahooDisconnect();
            return FALSE;
        }
        $this->parsepackets();
        $this->verblog("YahooConnect() Finished login procedure, feel free to do your thing now.");
        $this->connected = 1;
        $this->YahooKeepAlive();
    }
}

$ymsg = new YMSG();
$ymsg->Verbosity(2);
$ymsg->YahooUser("your username here");
$ymsg->YahooPass("the password goes here");
$ymsg->YahooConnect();
if($ymsg->ConnectedStatus() == 0){
    exit;
}
while(TRUE){
    // $ymsg->YahooDenyABuddy($argv[1]);
    // $ymsg->YahooAvatarLink($argv[1]);
    $ymsg->parsepackets();
    sleep(2);
}
?>