diff options
author | cookie <cookie@29ba0400-6e00-0410-a75a-ca02368028f8> | 2006-08-19 22:14:59 +0000 |
---|---|---|
committer | cookie <cookie@29ba0400-6e00-0410-a75a-ca02368028f8> | 2006-08-19 22:14:59 +0000 |
commit | 68f6a0d92c17647f5afe16f38b6836fb3f542a9e (patch) | |
tree | e837464cb2206425fa6c280420378f8e11ef6b77 /www-ssl/inc/funktion_jabber.php | |
parent | c37baec3bc274d978410f3c59f251e993cb9c0e5 (diff) |
jabba und mail error benachrichtigung (Entnommen aus pentabarf)
git-svn-id: svn://svn.cccv.de/engel-system@130 29ba0400-6e00-0410-a75a-ca02368028f8
Diffstat (limited to 'www-ssl/inc/funktion_jabber.php')
-rwxr-xr-x | www-ssl/inc/funktion_jabber.php | 1853 |
1 files changed, 1853 insertions, 0 deletions
diff --git a/www-ssl/inc/funktion_jabber.php b/www-ssl/inc/funktion_jabber.php new file mode 100755 index 00000000..9c699d70 --- /dev/null +++ b/www-ssl/inc/funktion_jabber.php @@ -0,0 +1,1853 @@ +<?php + +/*************************************************************************** + + Class.Jabber.PHP v0.4.2 + (c) 2004 Nathan "Fritzy" Fritz + http://cjphp.netflint.net *** fritzy@netflint.net + + This is a bugfix version, specifically for those who can't get + 0.4 to work on Jabberd2 servers. + + last modified: 24.03.2004 13:01:53 + + ***************************************************************************/ + +/*************************************************************************** + * + + * + ***************************************************************************/ + +/* + 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 +{ + function Jabber($server, $port, $username, $password, $resource) + { + + $this->server = $server; + $this->port = $port; + + $this->username = $username; + $this->password = $password; + $this->resource = $resource; + + $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://cjphp.netflint.net -- by Nathan 'Fritzy' Fritz, fritz@netflint.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() + { + $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 (isset($content['subject'])) + { + $xml .= "<subject>" . $content['subject'] . "</subject>\n"; + } + + if (isset($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 + 180 < time()) + { + // Modified by Nathan Fritz + if ($this->returned_keep_alive == FALSE) + { + $this->connected = FALSE; + $this->AddToLog('EVENT: Disconnected'); + } + if ($this->returned_keep_alive == TRUE) + { + $this->connected = TRUE; + } + + $this->returned_keep_alive = FALSE; + $this->keep_alive_id = 'keep_alive_' . time(); + //$this->SendPacket("<iq id='{$this->keep_alive_id}'/>", 'CruiseControl'); + $this->SendPacket("<iq type='get' from='" . $this->username . "@" . $this->server . "/" . $this->resource . "' to='" . $this->server . "' id='" . $this->keep_alive_id . "'><query xmlns='jabber:iq:time' /></iq>"); + // ** + + $this->last_ping_time = time(); + } + } + + 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='" . htmlspecialchars($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() + { + $incoming = ""; + + while ($line = $this->CONNECTOR->ReadFromSocket(4096)) + { + $incoming .= $line; + } + + $incoming = trim($incoming); + + if ($incoming != "") + { + $this->AddToLog("RECV: $incoming"); + } + + return $this->xmlize($incoming); + } + + + + function _check_connected() + { + $incoming_array = $this->_listen_incoming(); + + if (is_array($incoming_array)) + { + if ($incoming_array["stream:stream"]['@']['from'] == $this->server + && $incoming_array["stream:stream"]['@']['xmlns'] == "jabber:client" + && $incoming_array["stream:stream"]['@']["xmlns:stream"] == "http://etherx.jabber.org/streams") + { + $this->stream_id = $incoming_array["stream:stream"]['@']['id']; + + return TRUE; + } + else + { + $this->AddToLog("ERROR: _check_connected() #1"); + return FALSE; + } + } + else + { + $this->AddToLog("ERROR: _check_connected() #2"); + return FALSE; + } + } + + + + function _get_packet_type($packet = NULL) + { + if (is_array($packet)) + { + reset($packet); + $packet_type = key($packet); + } + + return ($packet_type) ? $packet_type : FALSE; + } + + + + function _split_incoming($incoming) + { + $temp = preg_split("/<(message|iq|presence|stream)/", $incoming, -1, PREG_SPLIT_DELIM_CAPTURE); + $array = array(); + + for ($a = 1; $a < count($temp); $a = $a + 2) + { + $array[] = "<" . $temp[$a] . $temp[($a + 1)]; + } + + return $array; + } + + + + function _create_logfile() + { + if ($this->log_filename != '' && $this->enable_logging) + { + $this->log_filehandler = fopen($this->log_filename, 'w'); + } + } + + + + function AddToLog($string) + { + if ($this->enable_logging) + { + if ($this->log_filehandler) + { + #fwrite($this->log_filehandler, $string . "\n\n"); + print "$string \n\n"; + } + else + { + $this->log_array[] = htmlspecialchars($string); + } + } + } + + + + function _close_logfile() + { + if ($this->log_filehandler) + { + fclose($this->log_filehandler); + } + } + + + + // _array_htmlspecialchars() + // applies htmlspecialchars() to all values in an array + + function _array_htmlspecialchars($array) + { + if (is_array($array)) + { + foreach ($array as $k => $v) + { + if (is_array($v)) + { + $v = $this->_array_htmlspecialchars($v); + } + else + { + $v = htmlspecialchars($v); + } + } + } + + return $array; + } + + + + // ====================================================================== + // <message/> parsers + // ====================================================================== + + + + function GetInfoFromMessageFrom($packet = NULL) + { + return (is_array($packet)) ? $packet['message']['@']['from'] : FALSE; + } + + + + function GetInfoFromMessageType($packet = NULL) + { + return (is_array($packet)) ? $packet['message']['@']['type'] : FALSE; + } + + + + function GetInfoFromMessageId($packet = NULL) + { + return (is_array($packet)) ? $packet['message']['@']['id'] : FALSE; + } + + + + function GetInfoFromMessageThread($packet = NULL) + { + return (is_array($packet)) ? $packet['message']['#']['thread'][0]['#'] : FALSE; + } + + + + function GetInfoFromMessageSubject($packet = NULL) + { + return (is_array($packet)) ? $packet['message']['#']['subject'][0]['#'] : FALSE; + } + + + + function GetInfoFromMessageBody($packet = NULL) + { + return (is_array($packet)) ? $packet['message']['#']['body'][0]['#'] : FALSE; + } + + function GetInfoFromMessageXMLNS($packet = NULL) + { + return (is_array($packet)) ? $packet['message']['#']['x'] : FALSE; + } + + + + function GetInfoFromMessageError($packet = NULL) + { + $error = preg_replace("/^\/$/", "", ($packet['message']['#']['error'][0]['@']['code'] . "/" . $packet['message']['#']['error'][0]['#'])); + return (is_array($packet)) ? $error : FALSE; + } + + + + // ====================================================================== + // <iq/> parsers + // ====================================================================== + + + + function GetInfoFromIqFrom($packet = NULL) + { + return (is_array($packet)) ? $packet['iq']['@']['from'] : FALSE; + } + + + + function GetInfoFromIqType($packet = NULL) + { + return (is_array($packet)) ? $packet['iq']['@']['type'] : FALSE; + } + + + + function GetInfoFromIqId($packet = NULL) + { + return (is_array($packet)) ? $packet['iq']['@']['id'] : FALSE; + } + + + + function GetInfoFromIqKey($packet = NULL) + { + return (is_array($packet)) ? $packet['iq']['#']['query'][0]['#']['key'][0]['#'] : FALSE; + } + + + + function GetInfoFromIqError($packet = NULL) + { + $error = preg_replace("/^\/$/", "", ($packet['iq']['#']['error'][0]['@']['code'] . "/" . $packet['iq']['#']['error'][0]['#'])); + return (is_array($packet)) ? $error : FALSE; + } + + + + // ====================================================================== + // <presence/> parsers + // ====================================================================== + + + + function GetInfoFromPresenceFrom($packet = NULL) + { + return (is_array($packet)) ? $packet['presence']['@']['from'] : FALSE; + } + + + + function GetInfoFromPresenceType($packet = NULL) + { + return (is_array($packet)) ? $packet['presence']['@']['type'] : FALSE; + } + + + + function GetInfoFromPresenceStatus($packet = NULL) + { + return (is_array($packet)) ? $packet['presence']['#']['status'][0]['#'] : FALSE; + } + + + + function GetInfoFromPresenceShow($packet = NULL) + { + return (is_array($packet)) ? $packet['presence']['#']['show'][0]['#'] : FALSE; + } + + + + function GetInfoFromPresencePriority($packet = NULL) + { + return (is_array($packet)) ? $packet['presence']['#']['priority'][0]['#'] : FALSE; + } + + + + // ====================================================================== + // <message/> handlers + // ====================================================================== + + + + function Handler_message_normal($packet) + { + $from = $packet['message']['@']['from']; + $this->AddToLog("EVENT: Message (type normal) from $from"); + } + + + + function Handler_message_chat($packet) + { + $from = $packet['message']['@']['from']; + $this->AddToLog("EVENT: Message (type chat) from $from"); + } + + + + function Handler_message_groupchat($packet) + { + $from = $packet['message']['@']['from']; + $this->AddToLog("EVENT: Message (type groupchat) from $from"); + } + + + + function Handler_message_headline($packet) + { + $from = $packet['message']['@']['from']; + $this->AddToLog("EVENT: Message (type headline) from $from"); + } + + + + function Handler_message_error($packet) + { + $from = $packet['message']['@']['from']; + $this->AddToLog("EVENT: Message (type error) from $from"); + } + + + + // ====================================================================== + // <iq/> handlers + // ====================================================================== + + + + // application version updates + function Handler_iq_jabber_iq_autoupdate($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:autoupdate from $from"); + } + + + + // interactive server component properties + function Handler_iq_jabber_iq_agent($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:agent from $from"); + } + + + + // method to query interactive server components + function Handler_iq_jabber_iq_agents($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:agents from $from"); + } + + + + // simple client authentication + function Handler_iq_jabber_iq_auth($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:auth from $from"); + } + + + + // out of band data + function Handler_iq_jabber_iq_oob($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:oob from $from"); + } + + + + // method to store private data on the server + function Handler_iq_jabber_iq_private($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:private from $from"); + } + + + + // method for interactive registration + function Handler_iq_jabber_iq_register($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:register from $from"); + } + + + + // client roster management + function Handler_iq_jabber_iq_roster($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:roster from $from"); + } + + + + // method for searching a user database + function Handler_iq_jabber_iq_search($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:search from $from"); + } + + + + // method for requesting the current time + function Handler_iq_jabber_iq_time($packet) + { + if ($this->keep_alive_id == $this->GetInfoFromIqId($packet)) + { + $this->returned_keep_alive = TRUE; + $this->connected = TRUE; + $this->AddToLog('EVENT: Keep-Alive returned, connection alive.'); + } + $type = $this->GetInfoFromIqType($packet); + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + $id = ($id != "") ? $id : "time_" . time(); + + if ($type == 'get') + { + $payload = "<utc>" . gmdate("Ydm\TH:i:s") . "</utc> + <tz>" . date("T") . "</tz> + <display>" . date("Y/d/m h:i:s A") . "</display>"; + + $this->SendIq($from, 'result', $id, "jabber:iq:time", $payload); + } + + $this->AddToLog("EVENT: jabber:iq:time (type $type) from $from"); + } + + + + // method for requesting version + function Handler_iq_jabber_iq_version($packet) + { + $type = $this->GetInfoFromIqType($packet); + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + $id = ($id != "") ? $id : "version_" . time(); + + if ($type == 'get') + { + $payload = "<name>{$this->iq_version_name}</name> + <os>{$this->iq_version_os}</os> + <version>{$this->iq_version_version}</version>"; + + #$this->SendIq($from, 'result', $id, "jabber:iq:version", $payload); + } + + $this->AddToLog("EVENT: jabber:iq:version (type $type) from $from -- DISABLED"); + } + + + + // keepalive method, added by Nathan Fritz + /* + function Handler_jabber_iq_time($packet) + { + if ($this->keep_alive_id == $this->GetInfoFromIqId($packet)) + { + $this->returned_keep_alive = TRUE; + $this->connected = TRUE; + $this->AddToLog('EVENT: Keep-Alive returned, connection alive.'); + } + } + */ + + + // ====================================================================== + // <presence/> handlers + // ====================================================================== + + + + function Handler_presence_available($packet) + { + $from = $this->GetInfoFromPresenceFrom($packet); + + $show_status = $this->GetInfoFromPresenceStatus($packet) . " / " . $this->GetInfoFromPresenceShow($packet); + $show_status = ($show_status != " / ") ? " ($addendum)" : ''; + + $this->AddToLog("EVENT: Presence (type: available) - $from is available $show_status"); + } + + + + function Handler_presence_unavailable($packet) + { + $from = $this->GetInfoFromPresenceFrom($packet); + + $show_status = $this->GetInfoFromPresenceStatus($packet) . " / " . $this->GetInfoFromPresenceShow($packet); + $show_status = ($show_status != " / ") ? " ($addendum)" : ''; + + $this->AddToLog("EVENT: Presence (type: unavailable) - $from is unavailable $show_status"); + } + + + + function Handler_presence_subscribe($packet) + { + $from = $this->GetInfoFromPresenceFrom($packet); + $this->SubscriptionAcceptRequest($from); + $this->RosterUpdate(); + + $this->log_array[] = "<b>Presence:</b> (type: subscribe) - Subscription request from $from, was added to \$this->subscription_queue, roster updated"; + } + + + + function Handler_presence_subscribed($packet) + { + $from = $this->GetInfoFromPresenceFrom($packet); + $this->RosterUpdate(); + + $this->AddToLog("EVENT: Presence (type: subscribed) - Subscription allowed by $from, roster updated"); + } + + + + function Handler_presence_unsubscribe($packet) + { + $from = $this->GetInfoFromPresenceFrom($packet); + $this->SendPresence("unsubscribed", $from); + $this->RosterUpdate(); + + $this->AddToLog("EVENT: Presence (type: unsubscribe) - Request to unsubscribe from $from, was automatically approved, roster updated"); + } + + + + function Handler_presence_unsubscribed($packet) + { + $from = $this->GetInfoFromPresenceFrom($packet); + $this->RosterUpdate(); + + $this->AddToLog("EVENT: Presence (type: unsubscribed) - Unsubscribed from $from's presence"); + } + + + + // Added By Nathan Fritz + function Handler_presence_error($packet) + { + $from = $this->GetInfoFromPresenceFrom($packet); + $this->AddToLog("EVENT: Presence (type: error) - Error in $from's presence"); + } + + + + // ====================================================================== + // Generic handlers + // ====================================================================== + + + + // Generic handler for unsupported requests + function Handler_NOT_IMPLEMENTED($packet) + { + $packet_type = $this->_get_packet_type($packet); + $from = call_user_func(array(&$this, "GetInfoFrom" . ucfirst($packet_type) . "From"), $packet); + $id = call_user_func(array(&$this, "GetInfoFrom" . ucfirst($packet_type) . "Id"), $packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: Unrecognized <$packet_type/> from $from"); + } + + + + // ====================================================================== + // Third party code + // m@d pr0ps to the coders ;) + // ====================================================================== + + + + // xmlize() + // (c) Hans Anderson / http://www.hansanderson.com/php/xml/ + + function xmlize($data) + { + $vals = $index = $array = array(); + $parser = xml_parser_create('utf-8'); + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); + xml_parse_into_struct($parser, $data, $vals, $index); + xml_parser_free($parser); + + $i = 0; + + $tagname = $vals[$i]['tag']; + $array[$tagname]['@'] = $vals[$i]['attributes']; + $array[$tagname]['#'] = $this->_xml_depth($vals, $i); + + return $array; + } + + + + // _xml_depth() + // (c) Hans Anderson / http://www.hansanderson.com/php/xml/ + + function _xml_depth($vals, &$i) + { + $children = array(); + + if (isset($vals[$i]['value'])) + { + array_push($children, trim($vals[$i]['value'])); + } + + while (++$i < count($vals)) + { + switch ($vals[$i]['type']) + { + case 'cdata': + array_push($children, trim($vals[$i]['value'])); + break; + + case 'complete': + $tagname = $vals[$i]['tag']; + $size = isset($children[$tagname]) ? sizeof($children[$tagname]) : 0; + $children[$tagname][$size]['#'] = isset($vals[$i]['value']) ? trim($vals[$i]['value']) : ""; + if (isset($vals[$i]['attributes'])) + { + $children[$tagname][$size]['@'] = $vals[$i]['attributes']; + } + break; + + case 'open': + $tagname = $vals[$i]['tag']; + $size = isset($children[$tagname]) ? sizeof($children[$tagname]) : 0; + if ($vals[$i]['attributes']) + { + $children[$tagname][$size]['@'] = $vals[$i]['attributes']; + $children[$tagname][$size]['#'] = $this->_xml_depth($vals, $i); + } + else + { + $children[$tagname][$size]['#'] = $this->_xml_depth($vals, $i); + } + break; + + case 'close': + return $children; + break; + } + } + + return $children; + } + + + + // TraverseXMLize() + // (c) acebone@f2s.com, a HUGE help! + + function TraverseXMLize($array, $arrName = "array", $level = 0) + { + if ($level == 0) + { + echo "<pre>"; + } + + while (list($key, $val) = @each($array)) + { + if (is_array($val)) + { + $this->TraverseXMLize($val, $arrName . "[" . $key . "]", $level + 1); + } + else + { + echo '$' . $arrName . '[' . $key . '] = "' . $val . "\"\n"; + } + } + + if ($level == 0) + { + echo "</pre>"; + } + } +} + + + +class MakeXML extends Jabber +{ + + function MakeXML() + { + $nodes = array(); + } + + + + function AddPacketDetails($string, $value = NULL) + { + if (preg_match("/\(([0-9]*)\)$/i", $string)) + { + $string .= "/[\"#\"]"; + } + + $temp = @explode("/", $string); + + for ($a = 0; $a < count($temp); $a++) + { + $temp[$a] = preg_replace("/^[@]{1}([a-z0-9_]*)$/i", "[\"@\"][\"\\1\"]", $temp[$a]); + $temp[$a] = preg_replace("/^([a-z0-9_]*)\(([0-9]*)\)$/i", "[\"\\1\"][\\2]", $temp[$a]); + $temp[$a] = preg_replace("/^([a-z0-9_]*)$/i", "[\"\\1\"]", $temp[$a]); + } + + $node = implode("", $temp); + + // Yeahyeahyeah, I know it's ugly... get over it. ;) + echo "\$this->nodes$node = \"" . htmlspecialchars($value) . "\";<br/>"; + eval("\$this->nodes$node = \"" . htmlspecialchars($value) . "\";"); + } + + + + function BuildPacket($array = NULL) + { + + if (!$array) + { + $array = $this->nodes; + } + + if (is_array($array)) + { + array_multisort($array, SORT_ASC, SORT_STRING); + + foreach ($array as $key => $value) + { + if (is_array($value) && $key == "@") + { + foreach ($value as $subkey => $subvalue) + { + $subvalue = htmlspecialchars($subvalue); + $text .= " $subkey='$subvalue'"; + } + + $text .= ">\n"; + + } + elseif ($key == "#") + { + $text .= htmlspecialchars($value); + } + elseif (is_array($value)) + { + for ($a = 0; $a < count($value); $a++) + { + $text .= "<$key"; + + if (!$this->_preg_grep_keys("/^@/", $value[$a])) + { + $text .= ">"; + } + + $text .= $this->BuildPacket($value[$a]); + + $text .= "</$key>\n"; + } + } + else + { + $value = htmlspecialchars($value); + $text .= "<$key>$value</$key>\n"; + } + } + + return $text; + } + } + + + + function _preg_grep_keys($pattern, $array) + { + while (list($key, $val) = each($array)) + { + if (preg_match($pattern, $key)) + { + $newarray[$key] = $val; + } + } + return (is_array($newarray)) ? $newarray : FALSE; + } +} + + + +class CJP_StandardConnector +{ + function OpenSocket($server, $port) + { + if ($this->active_socket = fsockopen($server, $port)) + { + socket_set_blocking($this->active_socket, 0); + socket_set_timeout($this->active_socket, 31536000); + + return TRUE; + } + else + { + return FALSE; + } + } + + + + function CloseSocket() + { + return fclose($this->active_socket); + } + + + + function WriteToSocket($data) + { + return fwrite($this->active_socket, $data); + } + + + + function ReadFromSocket($chunksize) + { + set_magic_quotes_runtime(0); + $buffer = fread($this->active_socket, $chunksize); + set_magic_quotes_runtime(get_magic_quotes_gpc()); + + return $buffer; + } +} + + + +?> |