PHP YMSG Class

From D3xt3r01.tk
Jump to navigationJump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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);
}
?>