Aquarionics

/home/a/aquarion/sites/www.aquarionics.com/epistula/include/class.jabber.php

All my code (That is, anything not in the "Others" list on the right) is BSD licenced.

You can also view this page as text/plain or colour-coded source


<?php

// Epistula data: $id

/***************************************************************************

    Class.Jabber.PHP v0.4
    (c) 2002 Carlo "Gossip" Zottmann
    http://phpjabber.g-blog.net *** gossip@jabber.g-blog.net

    The FULL documentation and examples for this software can be found at
    http://phpjabber.g-blog.net (not many doc comments in here, sorry)

    last modified: 27.04.2003 13:01:53 CET

 ***************************************************************************/

/***************************************************************************
 *

 *
 ***************************************************************************/

/*
    Jabber::Connect()
    Jabber::Disconnect()
    Jabber::SendAuth()
    Jabber::AccountRegistration($reg_email {string}, $reg_name {string})

    Jabber::Listen()
    Jabber::SendPacket($xml {string})

    Jabber::RosterUpdate()
    Jabber::RosterAddUser($jid {string}, $id {string}, $name {string})
    Jabber::RosterRemoveUser($jid {string}, $id {string})
    Jabber::RosterExistsJID($jid {string})

    Jabber::Subscribe($jid {string})
    Jabber::Unsubscribe($jid {string})

    Jabber::CallHandler($message {array})
    Jabber::CruiseControl([$seconds {number}])

    Jabber::SubscriptionApproveRequest($to {string})
    Jabber::SubscriptionDenyRequest($to {string})

    Jabber::GetFirstFromQueue()
    Jabber::GetFromQueueById($packet_type {string}, $id {string})

    Jabber::SendMessage($to {string}, $id {number}, $type {string}, $content {array}[, $payload {array}])
     Jabber::SendIq($to {string}, $type {string}, $id {string}, $xmlns {string}[, $payload {string}])
    Jabber::SendPresence($type {string}[, $to {string}[, $status {string}[, $show {string}[, $priority {number}]]]])

    Jabber::SendError($to {string}, $id {string}, $error_number {number}[, $error_message {string}])

    Jabber::TransportRegistrationDetails($transport {string})
    Jabber::TransportRegistration($transport {string}, $details {array})

    Jabber::GetvCard($jid {string}[, $id {string}])    -- EXPERIMENTAL --

    Jabber::GetInfoFromMessageFrom($packet {array})
    Jabber::GetInfoFromMessageType($packet {array})
    Jabber::GetInfoFromMessageId($packet {array})
    Jabber::GetInfoFromMessageThread($packet {array})
    Jabber::GetInfoFromMessageSubject($packet {array})
    Jabber::GetInfoFromMessageBody($packet {array})
    Jabber::GetInfoFromMessageError($packet {array})

    Jabber::GetInfoFromIqFrom($packet {array})
    Jabber::GetInfoFromIqType($packet {array})
    Jabber::GetInfoFromIqId($packet {array})
    Jabber::GetInfoFromIqKey($packet {array})
     Jabber::GetInfoFromIqError($packet {array})

    Jabber::GetInfoFromPresenceFrom($packet {array})
    Jabber::GetInfoFromPresenceType($packet {array})
    Jabber::GetInfoFromPresenceStatus($packet {array})
    Jabber::GetInfoFromPresenceShow($packet {array})
    Jabber::GetInfoFromPresencePriority($packet {array})

    Jabber::AddToLog($string {string})
    Jabber::PrintLog()

    MakeXML::AddPacketDetails($string {string}[, $value {string/number}])
    MakeXML::BuildPacket([$array {array}])
*/



class Jabber
{
    var $server;
    var $port;
    var $username;
    var $password;
    var $resource;
    var $jid;

    var $connection;
    var $delay_disconnect;

    var $stream_id;
    var $roster;

    var $enable_logging;
    var $log_array;
    var $log_filename;
    var $log_filehandler;

    var $iq_sleep_timer;
    var $last_ping_time;

    var $packet_queue;
    var $subscription_queue;

    var $iq_version_name;
    var $iq_version_os;
    var $iq_version_version;

    var $error_codes;

    var $connected;
    var $keep_alive_id;
    var $returned_keep_alive;
    var $txnid;

    var $CONNECTOR;



    function Jabber()
    {
        $this->server                = "localhost";
        $this->port                    = "5222";

        $this->username                = "larry";
        $this->password                = "curly";
        $this->resource                = NULL;

        $this->enable_logging        = FALSE;
        $this->log_array            = array();
        $this->log_filename            = '';
        $this->log_filehandler        = FALSE;

        $this->packet_queue            = array();
        $this->subscription_queue    = array();

        $this->iq_sleep_timer        = 1;
        $this->delay_disconnect        = 1;

        $this->returned_keep_alive    = TRUE;
        $this->txnid                = 0;

        $this->iq_version_name        = "Class.Jabber.PHP -- http://phpjabber.g-blog.net -- by Carlo 'Gossip' Zottmann, gossip@jabber.g-blog.net";
        $this->iq_version_version    = "0.4";
        $this->iq_version_os        = $_SERVER['SERVER_SOFTWARE'];

        $this->connection_class        = "CJP_StandardConnector";

        $this->error_codes            = array(400 => "Bad Request",
                                            401 => "Unauthorized",
                                            402 => "Payment Required",
                                            403 => "Forbidden",
                                            404 => "Not Found",
                                            405 => "Not Allowed",
                                            406 => "Not Acceptable",
                                            407 => "Registration Required",
                                            408 => "Request Timeout",
                                            409 => "Conflict",
                                            500 => "Internal Server Error",
                                            501 => "Not Implemented",
                                            502 => "Remove Server Error",
                                            503 => "Service Unavailable",
                                            504 => "Remove Server Timeout",
                                            510 => "Disconnected");
    }



    function Connect()
    {
        $this->_create_logfile();

        $this->CONNECTOR = new $this->connection_class;

        if ($this->CONNECTOR->OpenSocket($this->server, $this->port))
        {
            $this->SendPacket("<?xml version='1.0' encoding='UTF-8' ?" . ">\n");
            $this->SendPacket("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>\n");

            sleep(2);

            if ($this->_check_connected())
            {
                $this->connected = TRUE;    // Nathan Fritz
                return TRUE;
            }
            else
            {
                $this->AddToLog("ERROR: Connect() #1");
                return FALSE;
            }
        }
        else
        {
            $this->AddToLog("ERROR: Connect() #2");
            return FALSE;
        }
    }



    function Disconnect()
    {
        if (is_int($this->delay_disconnect))
        {
            sleep($this->delay_disconnect);
        }

        $this->SendPacket("</stream:stream>");
        $this->CONNECTOR->CloseSocket();

        $this->_close_logfile();
        $this->PrintLog();
    }



    function SendAuth()
    {
        $this->auth_id    = "auth_" . md5(time() . $_SERVER['REMOTE_ADDR']);

        $this->resource    = ($this->resource != NULL) ? $this->resource : ("Class.Jabber.PHP " . md5($this->auth_id));
        $this->jid        = "{$this->username}@{$this->server}/{$this->resource}";

        // request available authentication methods
        $payload    = "<username>{$this->username}</username>";
        $packet        = $this->SendIq(NULL, 'get', $this->auth_id, "jabber:iq:auth", $payload);

        // was a result returned?
        if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id)
        {
            // yes, now check for auth method availability in descending order (best to worst)

            if (!function_exists(mhash))
            {
                $this->AddToLog("ATTENTION: SendAuth() - mhash() is not available; screw 0k and digest method, we need to go with plaintext auth");
            }

            // auth_0k
            if (function_exists(mhash) && isset($packet['iq']['#']['query'][0]['#']['sequence'][0]["#"]) && isset($packet['iq']['#']['query'][0]['#']['token'][0]["#"]))
            {
                return $this->_sendauth_0k($packet['iq']['#']['query'][0]['#']['token'][0]["#"], $packet['iq']['#']['query'][0]['#']['sequence'][0]["#"]);
            }
            // digest
            elseif (function_exists(mhash) && isset($packet['iq']['#']['query'][0]['#']['digest']))
            {
                return $this->_sendauth_digest();
            }
            // plain text
            elseif ($packet['iq']['#']['query'][0]['#']['password'])
            {
                return $this->_sendauth_plaintext();
            }
            // dude, you're fucked
            {
                $this->AddToLog("ERROR: SendAuth() #2 - No auth method available!");
                return FALSE;
            }
        }
        else
        {
            // no result returned
            $this->AddToLog("ERROR: SendAuth() #1");
            return FALSE;
        }
    }



    function AccountRegistration($reg_email = NULL, $reg_name = NULL)
    {
        $packet = $this->SendIq($this->server, 'get', 'reg_01', 'jabber:iq:register');

        if ($packet)
        {
            $key = $this->GetInfoFromIqKey($packet);    // just in case a key was passed back from the server
            unset($packet);

            $payload = "<username>{$this->username}</username>
                        <password>{$this->password}</password>
                        <email>$reg_email</email>
                        <name>$reg_name</name>\n";

            $payload .= ($key) ? "<key>$key</key>\n" : '';

            $packet = $this->SendIq($this->server, 'set', "reg_01", "jabber:iq:register", $payload);

            if ($this->GetInfoFromIqType($packet) == 'result')
            {
                if (isset($packet['iq']['#']['query'][0]['#']['registered'][0]['#']))
                {
                    $return_code = 1;
                }
                else
                {
                    $return_code = 2;
                }

                if ($this->resource)
                {
                    $this->jid = "{$this->username}@{$this->server}/{$this->resource}";
                }
                else
                {
                    $this->jid = "{$this->username}@{$this->server}";
                }

            }
            elseif ($this->GetInfoFromIqType($packet) == 'error' && isset($packet['iq']['#']['error'][0]['#']))
            {
                // "conflict" error, i.e. already registered
                if ($packet['iq']['#']['error'][0]['@']['code'] == '409')
                {
                    $return_code = 1;
                }
                else
                {
                    $return_code = "Error " . $packet['iq']['#']['error'][0]['@']['code'] . ": " . $packet['iq']['#']['error'][0]['#'];
                }
            }

            return $return_code;

        }
        else
        {
            return 3;
        }
    }



    function SendPacket($xml)
    {
        $xml = trim($xml);

        if ($this->CONNECTOR->WriteToSocket($xml))
        {
            $this->AddToLog("SEND: $xml");
            return TRUE;
        }
        else
        {
            $this->AddToLog('ERROR: SendPacket() #1');
            return FALSE;
        }
    }



    function Listen()
    {
        unset($incoming);

        while ($line = $this->CONNECTOR->ReadFromSocket(4096))
        {
            $incoming .= $line;
        }

        $incoming = trim($incoming);

        if ($incoming != "")
        {
            $this->AddToLog("RECV: $incoming");
        }

        if ($incoming != "")
        {
            $temp = $this->_split_incoming($incoming);

            for ($a = 0; $a < count($temp); $a++)
            {
                $this->packet_queue[] = $this->xmlize($temp[$a]);
            }
        }

        return TRUE;
    }



    function StripJID($jid = NULL)
    {
        preg_match("/(.*)\/(.*)/Ui", $jid, $temp);
        return ($temp[1] != "") ? $temp[1] : $jid;
    }



    function SendMessage($to, $type = "normal", $id = NULL, $content = NULL, $payload = NULL)
    {
        if ($to && is_array($content))
        {
            if (!$id)
            {
                $id = $type . "_" . time();
            }

            $content = $this->_array_htmlspecialchars($content);

            $xml = "<message to='$to' type='$type' id='$id'>\n";

            if ($content['subject'])
            {
                $xml .= "<subject>" . $content['subject'] . "</subject>\n";
            }

            if ($content['thread'])
            {
                $xml .= "<thread>" . $content['thread'] . "</thread>\n";
            }

            $xml .= "<body>" . $content['body'] . "</body>\n";
            $xml .= $payload;
            $xml .= "</message>\n";


            if ($this->SendPacket($xml))
            {
                return TRUE;
            }
            else
            {
                $this->AddToLog("ERROR: SendMessage() #1");
                return FALSE;
            }
        }
        else
        {
            $this->AddToLog("ERROR: SendMessage() #2");
            return FALSE;
        }
    }



    function SendPresence($type = NULL, $to = NULL, $status = NULL, $show = NULL, $priority = NULL)
    {
        $xml = "<presence";
        $xml .= ($to) ? " to='$to'" : '';
        $xml .= ($type) ? " type='$type'" : '';
        $xml .= ($status || $show || $priority) ? ">\n" : " />\n";

        $xml .= ($status) ? "    <status>$status</status>\n" : '';
        $xml .= ($show) ? "    <show>$show</show>\n" : '';
        $xml .= ($priority) ? "    <priority>$priority</priority>\n" : '';

        $xml .= ($status || $show || $priority) ? "</presence>\n" : '';

        if ($this->SendPacket($xml))
        {
            return TRUE;
        }
        else
        {
            $this->AddToLog("ERROR: SendPresence() #1");
            return FALSE;
        }
    }



    function SendError($to, $id = NULL, $error_number, $error_message = NULL)
    {
        $xml = "<iq type='error' to='$to'";
        $xml .= ($id) ? " id='$id'" : '';
        $xml .= ">\n";
        $xml .= "    <error code='$error_number'>";
        $xml .= ($error_message) ? $error_message : $this->error_codes[$error_number];
        $xml .= "</error>\n";
        $xml .= "</iq>";

        $this->SendPacket($xml);
    }



    function RosterUpdate()
    {
        $roster_request_id = "roster_" . time();

        $incoming_array = $this->SendIq(NULL, 'get', $roster_request_id, "jabber:iq:roster");

        if (is_array($incoming_array))
        {
            if ($incoming_array['iq']['@']['type'] == 'result'
                && $incoming_array['iq']['@']['id'] == $roster_request_id
                && $incoming_array['iq']['#']['query']['0']['@']['xmlns'] == "jabber:iq:roster")
            {
                $number_of_contacts = count($incoming_array['iq']['#']['query'][0]['#']['item']);
                $this->roster = array();

                for ($a = 0; $a < $number_of_contacts; $a++)
                {
                    $this->roster[$a] = array(    "jid"            => strtolower($incoming_array['iq']['#']['query'][0]['#']['item'][$a]['@']['jid']),
                                                "name"            => $incoming_array['iq']['#']['query'][0]['#']['item'][$a]['@']['name'],
                                                "subscription"    => $incoming_array['iq']['#']['query'][0]['#']['item'][$a]['@']['subscription'],
                                                "group"            => $incoming_array['iq']['#']['query'][0]['#']['item'][$a]['#']['group'][0]['#']
                                            );
                }

                return TRUE;
            }
            else
            {
                $this->AddToLog("ERROR: RosterUpdate() #1");
                return FALSE;
            }
        }
        else
        {
            $this->AddToLog("ERROR: RosterUpdate() #2");
            return FALSE;
        }
    }



    function RosterAddUser($jid = NULL, $id = NULL, $name = NULL)
    {
        $id = ($id) ? $id : "adduser_" . time();

        if ($jid)
        {
            $payload = "        <item jid='$jid'";
            $payload .= ($name) ? " name='" . htmlspecialchars($name) . "'" : '';
            $payload .= "/>\n";

            $packet = $this->SendIq(NULL, 'set', $id, "jabber:iq:roster", $payload);

            if ($this->GetInfoFromIqType($packet) == 'result')
            {
                $this->RosterUpdate();
                return TRUE;
            }
            else
            {
                $this->AddToLog("ERROR: RosterAddUser() #2");
                return FALSE;
            }
        }
        else
        {
            $this->AddToLog("ERROR: RosterAddUser() #1");
            return FALSE;
        }
    }



    function RosterRemoveUser($jid = NULL, $id = NULL)
    {
        $id = ($id) ? $id : 'deluser_' . time();

        if ($jid && $id)
        {
            $packet = $this->SendIq(NULL, 'set', $id, "jabber:iq:roster", "<item jid='$jid' subscription='remove'/>");

            if ($this->GetInfoFromIqType($packet) == 'result')
            {
                $this->RosterUpdate();
                return TRUE;
            }
            else
            {
                $this->AddToLog("ERROR: RosterRemoveUser() #2");
                return FALSE;
            }
        }
        else
        {
            $this->AddToLog("ERROR: RosterRemoveUser() #1");
            return FALSE;
        }
    }



    function RosterExistsJID($jid = NULL)
    {
        if ($jid)
        {
            if ($this->roster)
            {
                for ($a = 0; $a < count($this->roster); $a++)
                {
                    if ($this->roster[$a]['jid'] == strtolower($jid))
                    {
                        return $a;
                    }
                }
            }
            else
            {
                $this->AddToLog("ERROR: RosterExistsJID() #2");
                return FALSE;
            }
        }
        else
        {
            $this->AddToLog("ERROR: RosterExistsJID() #1");
            return FALSE;
        }
    }



    function GetFirstFromQueue()
    {
        return array_shift($this->packet_queue);
    }



    function GetFromQueueById($packet_type, $id)
    {
        $found_message = FALSE;

        foreach ($this->packet_queue as $key => $value)
        {
            if ($value[$packet_type]['@']['id'] == $id)
            {
                $found_message = $value;
                unset($this->packet_queue[$key]);

                break;
            }
        }

        return (is_array($found_message)) ? $found_message : FALSE;
    }



    function CallHandler($packet = NULL)
    {
        $packet_type    = $this->_get_packet_type($packet);

        if ($packet_type == "message")
        {
            $type        = $packet['message']['@']['type'];
            $type        = ($type != "") ? $type : "normal";
            $funcmeth    = "Handler_message_$type";
        }
        elseif ($packet_type == "iq")
        {
            $namespace    = $packet['iq']['#']['query'][0]['@']['xmlns'];
            $namespace    = str_replace(":", "_", $namespace);
            $funcmeth    = "Handler_iq_$namespace";
        }
        elseif ($packet_type == "presence")
        {
            $type        = $packet['presence']['@']['type'];
            $type        = ($type != "") ? $type : "available";
            $funcmeth    = "Handler_presence_$type";
        }


        if ($funcmeth != '')
        {
            if (function_exists($funcmeth))
            {
                call_user_func($funcmeth, $packet);
            }
            elseif (method_exists($this, $funcmeth))
            {
                call_user_func(array(&$this, $funcmeth), $packet);
            }
            else
            {
                $this->Handler_NOT_IMPLEMENTED($packet);
                $this->AddToLog("ERROR: CallHandler() #1 - neither method nor function $funcmeth() available");
            }
        }
    }



    function CruiseControl($seconds = -1)
    {
        $count = 0;

        while ($count != $seconds)
        {
            $this->Listen();

            do {
                $packet = $this->GetFirstFromQueue();

                if ($packet) {
                    $this->CallHandler($packet);
                }

            } while (count($this->packet_queue) > 1);

            $count += 0.25;
            usleep(250000);
            
            if ($this->last_ping_time != date('H:i'))
            {
                // Modified by Nathan Fritz
                if ($this->returned_keep_alive == FALSE)
                {
                    $this->connected = FALSE;
                    $this->AddToLog('EVENT: Disconnected');
                }

                $this->returned_keep_alive = FALSE;
                $this->keep_alive_id = 'keep_alive_' . time();
                $this->SendPacket("<iq id='{$this->keep_alive_id}'/>", 'CruiseControl');
                // **

                $this->last_ping_time = date("H:i");
            }
        }

        return TRUE;
    }



    function SubscriptionAcceptRequest($to = NULL)
    {
        return ($to) ? $this->SendPresence("subscribed", $to) : FALSE;
    }



    function SubscriptionDenyRequest($to = NULL)
    {
        return ($to) ? $this->SendPresence("unsubscribed", $to) : FALSE;
    }



    function Subscribe($to = NULL)
    {
        return ($to) ? $this->SendPresence("subscribe", $to) : FALSE;
    }



    function Unsubscribe($to = NULL)
    {
        return ($to) ? $this->SendPresence("unsubscribe", $to) : FALSE;
    }



    function SendIq($to = NULL, $type = 'get', $id = NULL, $xmlns = NULL, $payload = NULL, $from = NULL)
    {
        if (!preg_match("/^(get|set|result|error)$/", $type))
        {
            unset($type);

            $this->AddToLog("ERROR: SendIq() #2 - type must be 'get', 'set', 'result' or 'error'");
            return FALSE;
        }
        elseif ($id && $xmlns)
        {
            $xml = "<iq type='$type' id='$id'";
            $xml .= ($to) ? " to='$to'" : '';
            $xml .= ($from) ? " from='$from'" : '';
            $xml .= ">
                        <query xmlns='$xmlns'>
                            $payload
                        </query>
                    </iq>";

            $this->SendPacket($xml);
            sleep($this->iq_sleep_timer);
            $this->Listen();

            return (preg_match("/^(get|set)$/", $type)) ? $this->GetFromQueueById("iq", $id) : TRUE;
        }
        else
        {
            $this->AddToLog("ERROR: SendIq() #1 - to, id and xmlns are mandatory");
            return FALSE;
        }
    }



    // get the transport registration fields
    // method written by Steve Blinch, http://www.blitzaffe.com 
    function TransportRegistrationDetails($transport)
    {
        $this->txnid++;
        $packet = $this->SendIq($transport, 'get', "reg_{$this->txnid}", "jabber:iq:register", NULL, $this->jid);

        if ($packet)
        {
            $res = array();

            foreach ($packet['iq']['#']['query'][0]['#'] as $element => $data)
            {
                if ($element != 'instructions' && $element != 'key')
                {
                    $res[] = $element;
                }
            }

            return $res;
        }
        else
        {
            return 3;
        }
    }
    


    // register with the transport
    // method written by Steve Blinch, http://www.blitzaffe.com 
    function TransportRegistration($transport, $details)
    {
        $this->txnid++;
        $packet = $this->SendIq($transport, 'get', "reg_{$this->txnid}", "jabber:iq:register", NULL, $this->jid);

        if ($packet)
        {
            $key = $this->GetInfoFromIqKey($packet);    // just in case a key was passed back from the server
            unset($packet);
        
            $payload = ($key) ? "<key>$key</key>\n" : '';
            foreach ($details as $element => $value)
            {
                $payload .= "<$element>$value</$element>\n";
            }
        
            $packet = $this->SendIq($transport, 'set', "reg_{$this->txnid}", "jabber:iq:register", $payload);
        
            if ($this->GetInfoFromIqType($packet) == 'result')
            {
                if (isset($packet['iq']['#']['query'][0]['#']['registered'][0]['#']))
                {
                    $return_code = 1;
                }
                else
                {
                    $return_code = 2;
                }
            }
            elseif ($this->GetInfoFromIqType($packet) == 'error')
            {
                if (isset($packet['iq']['#']['error'][0]['#']))
                {
                    $return_code = "Error " . $packet['iq']['#']['error'][0]['@']['code'] . ": " . $packet['iq']['#']['error'][0]['#'];
                    $this->AddToLog('ERROR: TransportRegistration()');
                }
            }

            return $return_code;
        }
        else
        {
            return 3;
        }
    }



    function GetvCard($jid = NULL, $id = NULL)
    {
        if (!$id)
        {
            $id = "vCard_" . md5(time() . $_SERVER['REMOTE_ADDR']);
        }

        if ($jid)
        {
            $xml = "<iq type='get' to='$jid' id='$id'>
                        <vCard xmlns='vcard-temp'/>
                    </iq>";

            $this->SendPacket($xml);
            sleep($this->iq_sleep_timer);
            $this->Listen();

            return $this->GetFromQueueById("iq", $id);
        }
        else
        {
            $this->AddToLog("ERROR: GetvCard() #1 - to and id are mandatory");
            return FALSE;
        }
    }



    function PrintLog()
    {
        if ($this->enable_logging)
        {
            if ($this->log_filehandler)
            {
                echo "<h2>Logging enabled, logged events have been written to the file {$this->log_filename}.</h2>\n";
            }
            else
            {
                echo "<h2>Logging enabled, logged events below:</h2>\n";
                echo "<pre>\n";
                echo (count($this->log_array) > 0) ? implode("\n\n\n", $this->log_array) : "No logged events.";
                echo "</pre>\n";
            }
        }
    }



    // ======================================================================
    // private methods
    // ======================================================================



    function _sendauth_0k($zerok_token, $zerok_sequence)
    {
        // initial hash of password
        $zerok_hash = mhash(MHASH_SHA1, $this->password);
        $zerok_hash = bin2hex($zerok_hash);

        // sequence 0: hash of hashed-password and token
        $zerok_hash = mhash(MHASH_SHA1, $zerok_hash . $zerok_token);
        $zerok_hash = bin2hex($zerok_hash);

        // repeat as often as needed
        for ($a = 0; $a < $zerok_sequence; $a++)
        {
            $zerok_hash = mhash(MHASH_SHA1, $zerok_hash);
            $zerok_hash = bin2hex($zerok_hash);
        }

        $payload = "<username>{$this->username}</username>
                    <hash>$zerok_hash</hash>
                    <resource>{$this->resource}</resource>";

        $packet = $this->SendIq(NULL, 'set', $this->auth_id, "jabber:iq:auth", $payload);

        // was a result returned?
        if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id)
        {
            return TRUE;
        }
        else
        {
            $this->AddToLog("ERROR: _sendauth_0k() #1");
            return FALSE;
        }
    }



    function _sendauth_digest()
    {
        $payload = "<username>{$this->username}</username>
                    <resource>{$this->resource}</resource>
                    <digest>" . bin2hex(mhash(MHASH_SHA1, $this->stream_id . $this->password)) . "</digest>";

        $packet = $this->SendIq(NULL, 'set', $this->auth_id, "jabber:iq:auth", $payload);

        // was a result returned?
        if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id)
        {
            return TRUE;
        }
        else
        {
            $this->AddToLog("ERROR: _sendauth_digest() #1");
            return FALSE;
        }
    }



    function _sendauth_plaintext()
    {
        $payload = "<username>{$this->username}</username>
                    <password>{$this->password}</password>
                    <resource>{$this->resource}</resource>";

        $packet = $this->SendIq(NULL, 'set', $this->auth_id, "jabber:iq:auth", $payload);

        // was a result returned?
        if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id)
        {
            return TRUE;
        }
        else
        {
            $this->AddToLog("ERROR: _sendauth_plaintext() #1");
            return FALSE;
        }
    }



    function _listen_incoming()
    {
        unset($incoming);

        while ($line = $this->CONNECTOR->ReadFromSocket