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\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 = "
";
$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 "Logging enabled, logged events have been written to the file {$this->log_filename}.
\n";
}
else
{
echo "Logging enabled, logged events below:
\n";
echo "\n";
echo (count($this->log_array) > 0) ? implode("\n\n\n", $this->log_array) : "No logged events.";
echo "
\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 = "{$this->username}
$zerok_hash
{$this->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 = "{$this->username}
{$this->resource}
" . bin2hex(mhash(MHASH_SHA1, $this->stream_id . $this->password)) . "";
$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 = "{$this->username}
{$this->password}
{$this->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(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");
}
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;
}
// ======================================================================
// 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 GetInfoFromMessageError($packet = NULL)
{
$error = preg_replace("/^\/$/", "", ($packet['message']['#']['error'][0]['@']['code'] . "/" . $packet['message']['#']['error'][0]['#']));
return (is_array($packet)) ? $error : FALSE;
}
// ======================================================================
// 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;
}
// ======================================================================
// 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;
}
// ======================================================================
// 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");
}
// ======================================================================
// 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)
{
$type = $this->GetInfoFromIqType($packet);
$from = $this->GetInfoFromIqFrom($packet);
$id = $this->GetInfoFromIqId($packet);
$id = ($id != "") ? $id : "time_" . time();
if ($type == 'get')
{
$payload = "" . gmdate("Ydm\TH:i:s") . "
" . date("T") . "
" . date("Y/d/m h:i:s A") . "";
$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 = "{$this->iq_version_name}
{$this->iq_version_os}
{$this->iq_version_version}";
$this->SendIq($from, 'result', $id, "jabber:iq:version", $payload);
}
$this->AddToLog("EVENT: jabber:iq:version (type $type) from $from");
}
// keepalive method, added by Nathan Fritz
function Handler_iq_($packet)
{
if ($this->keep_alive_id == $this->GetInfoFromIqId($packet))
{
$this->returned_keep_alive = TRUE;
$this->AddToLog('EVENT: Keep-Alive returned, connection alive.');
}
}
// ======================================================================
// 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[] = "Presence: (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();
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 ($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 = sizeof($children[$tagname]);
$children[$tagname][$size]['#'] = trim($vals[$i]['value']);
if ($vals[$i]['attributes'])
{
$children[$tagname][$size]['@'] = $vals[$i]['attributes'];
}
break;
case 'open':
$tagname = $vals[$i]['tag'];
$size = sizeof($children[$tagname]);
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 "";
}
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 "
";
}
}
}
class MakeXML extends Jabber
{
var $nodes;
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) . "\";
";
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
{
var $active_socket;
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;
}
}
?>