PageRenderTime 74ms CodeModel.GetById 12ms app.highlight 45ms RepoModel.GetById 1ms app.codeStats 1ms

/main/class/notify/notify_jabber.php

http://github.com/FSB/Fire-Soft-Board-2
PHP | 2009 lines | 1341 code | 501 blank | 167 comment | 181 complexity | b0f60c82ce8627812bb813b48d6138d0 MD5 | raw file
   1<?php
   2
   3/***************************************************************************
   4
   5	Class.Jabber.PHP v0.4.2
   6	(c) 2004 Nathan "Fritzy" Fritz
   7	http://cjphp.netflint.net *** fritzy@netflint.net
   8
   9	This is a bugfix version, specifically for those who can't get 
  10	0.4 to work on Jabberd2 servers. 
  11
  12	last modified: 24.03.2004 13:01:53 
  13
  14 ***************************************************************************/
  15
  16/***************************************************************************
  17 *
  18
  19 *
  20 ***************************************************************************/
  21
  22/*
  23	Jabber::Connect()
  24	Jabber::Disconnect()
  25	Jabber::SendAuth()
  26	Jabber::AccountRegistration($reg_email {string}, $reg_name {string})
  27
  28	Jabber::Listen()
  29	Jabber::SendPacket($xml {string})
  30
  31	Jabber::RosterUpdate()
  32	Jabber::RosterAddUser($jid {string}, $id {string}, $name {string})
  33	Jabber::RosterRemoveUser($jid {string}, $id {string})
  34	Jabber::RosterExistsJID($jid {string})
  35
  36	Jabber::Subscribe($jid {string})
  37	Jabber::Unsubscribe($jid {string})
  38
  39	Jabber::CallHandler($message {array})
  40	Jabber::CruiseControl([$seconds {number}])
  41
  42	Jabber::SubscriptionApproveRequest($to {string})
  43	Jabber::SubscriptionDenyRequest($to {string})
  44
  45	Jabber::GetFirstFromQueue()
  46	Jabber::GetFromQueueById($packet_type {string}, $id {string})
  47
  48	Jabber::SendMessage($to {string}, $id {number}, $type {string}, $content {array}[, $payload {array}])
  49 	Jabber::SendIq($to {string}, $type {string}, $id {string}, $xmlns {string}[, $payload {string}])
  50	Jabber::SendPresence($type {string}[, $to {string}[, $status {string}[, $show {string}[, $priority {number}]]]])
  51
  52	Jabber::SendError($to {string}, $id {string}, $error_number {number}[, $error_message {string}])
  53
  54	Jabber::TransportRegistrationDetails($transport {string})
  55	Jabber::TransportRegistration($transport {string}, $details {array})
  56
  57	Jabber::GetvCard($jid {string}[, $id {string}])	-- EXPERIMENTAL --
  58
  59	Jabber::GetInfoFromMessageFrom($packet {array})
  60	Jabber::GetInfoFromMessageType($packet {array})
  61	Jabber::GetInfoFromMessageId($packet {array})
  62	Jabber::GetInfoFromMessageThread($packet {array})
  63	Jabber::GetInfoFromMessageSubject($packet {array})
  64	Jabber::GetInfoFromMessageBody($packet {array})
  65	Jabber::GetInfoFromMessageError($packet {array})
  66
  67	Jabber::GetInfoFromIqFrom($packet {array})
  68	Jabber::GetInfoFromIqType($packet {array})
  69	Jabber::GetInfoFromIqId($packet {array})
  70	Jabber::GetInfoFromIqKey($packet {array})
  71 	Jabber::GetInfoFromIqError($packet {array})
  72
  73	Jabber::GetInfoFromPresenceFrom($packet {array})
  74	Jabber::GetInfoFromPresenceType($packet {array})
  75	Jabber::GetInfoFromPresenceStatus($packet {array})
  76	Jabber::GetInfoFromPresenceShow($packet {array})
  77	Jabber::GetInfoFromPresencePriority($packet {array})
  78
  79	Jabber::AddToLog($string {string})
  80	Jabber::PrintLog()
  81
  82	MakeXML::AddPacketDetails($string {string}[, $value {string/number}])
  83	MakeXML::BuildPacket([$array {array}])
  84*/
  85
  86
  87
  88class Notify_jabber
  89{
  90	public $server;
  91	public $port;
  92	public $username;
  93	public $password;
  94	public $resource;
  95	public $jid;
  96
  97	public $connection;
  98	public $delay_disconnect;
  99
 100	public $stream_id;
 101	public $roster;
 102
 103	public $enable_logging;
 104	public $log_array;
 105	public $log_filename;
 106	public $log_filehandler;
 107
 108	public $iq_sleep_timer;
 109	public $last_ping_time;
 110
 111	public $packet_queue;
 112	public $subscription_queue;
 113
 114	public $iq_version_name;
 115	public $iq_version_os;
 116	public $iq_version_version;
 117
 118	public $error_codes;
 119
 120	public $connected;
 121	public $keep_alive_id;
 122	public $returned_keep_alive;
 123	public $txnid;
 124
 125	public $CONNECTOR;
 126
 127
 128
 129	public function __construct()
 130	{
 131		$this->server				= "localhost";
 132		$this->port					= "5222";
 133
 134		$this->username				= "larry";
 135		$this->password				= "curly";
 136		$this->resource				= null;
 137
 138		$this->enable_logging		= false;
 139		$this->log_array			= array();
 140		$this->log_filename			= '';
 141		$this->log_filehandler		= false;
 142
 143		$this->packet_queue			= array();
 144		$this->subscription_queue	= array();
 145
 146		$this->iq_sleep_timer		= 1;
 147		$this->delay_disconnect		= 1;
 148
 149		$this->returned_keep_alive	= true;
 150		$this->txnid				= 0;
 151
 152		$this->iq_version_name		= "Class.Jabber.PHP -- http://cjphp.netflint.net -- by Nathan 'Fritzy' Fritz, fritz@netflint.net";
 153		$this->iq_version_version	= "0.4";
 154		$this->iq_version_os		= $_SERVER['SERVER_SOFTWARE'];
 155
 156		$this->connection_class		= "CJP_StandardConnector";
 157
 158		$this->error_codes			= array(400 => "Bad Request",
 159											401 => "Unauthorized",
 160											402 => "Payment Required",
 161											403 => "Forbidden",
 162											404 => "Not Found",
 163											405 => "Not Allowed",
 164											406 => "Not Acceptable",
 165											407 => "Registration Required",
 166											408 => "Request Timeout",
 167											409 => "Conflict",
 168											500 => "Internal Server Error",
 169											501 => "Not Implemented",
 170											502 => "Remove Server Error",
 171											503 => "Service Unavailable",
 172											504 => "Remove Server Timeout",
 173											510 => "Disconnected");
 174	}
 175
 176
 177
 178	public function Connect()
 179	{
 180		$this->_create_logfile();
 181
 182		$this->CONNECTOR = new $this->connection_class;
 183
 184		if ($this->CONNECTOR->OpenSocket($this->server, $this->port))
 185		{
 186			$this->SendPacket("<?xml version='1.0' encoding='UTF-8' ?" . ">\n");
 187			$this->SendPacket("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n");
 188
 189			sleep(2);
 190
 191			if ($this->_check_connected())
 192			{
 193				$this->connected = true;	// Nathan Fritz
 194				return true;
 195			}
 196			else
 197			{
 198				$this->AddToLog("ERROR: Connect() #1");
 199				return false;
 200			}
 201		}
 202		else
 203		{
 204			$this->AddToLog("ERROR: Connect() #2");
 205			return false;
 206		}
 207	}
 208
 209
 210
 211	public function Disconnect()
 212	{
 213		if (is_int($this->delay_disconnect))
 214		{
 215			sleep($this->delay_disconnect);
 216		}
 217
 218		$this->SendPacket("</stream:stream>");
 219		$this->CONNECTOR->CloseSocket();
 220
 221		$this->_close_logfile();
 222		$this->PrintLog();
 223	}
 224
 225
 226
 227	public function SendAuth()
 228	{
 229		$this->auth_id	= "auth_" . md5(time() . $_SERVER['REMOTE_ADDR']);
 230
 231		$this->resource	= ($this->resource != null) ? $this->resource : ("Class.Jabber.PHP " . md5($this->auth_id));
 232		$this->jid		= "{$this->username}@{$this->server}/{$this->resource}";
 233
 234		// request available authentication methods
 235		$payload	= "<username>{$this->username}</username>";
 236		$packet		= $this->SendIq(null, 'get', $this->auth_id, "jabber:iq:auth", $payload);
 237
 238		// was a result returned?
 239		if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id)
 240		{
 241			// yes, now check for auth method availability in descending order (best to worst)
 242
 243			if (!function_exists("mhash"))
 244			{
 245				$this->AddToLog("ATTENTION: SendAuth() - mhash() is not available; screw 0k and digest method, we need to go with plaintext auth");
 246			}
 247
 248			// auth_0k
 249			if (function_exists("mhash") && isset($packet['iq']['#']['query'][0]['#']['sequence'][0]["#"]) && isset($packet['iq']['#']['query'][0]['#']['token'][0]["#"]))
 250			{
 251				return $this->_sendauth_0k($packet['iq']['#']['query'][0]['#']['token'][0]["#"], $packet['iq']['#']['query'][0]['#']['sequence'][0]["#"]);
 252			}
 253			// digest
 254			elseif (function_exists("mhash") && isset($packet['iq']['#']['query'][0]['#']['digest']))
 255			{
 256				return $this->_sendauth_digest();
 257			}
 258			// plain text
 259			elseif ($packet['iq']['#']['query'][0]['#']['password'])
 260			{
 261				return $this->_sendauth_plaintext();
 262			}
 263			// dude, you're fucked
 264			{
 265				$this->AddToLog("ERROR: SendAuth() #2 - No auth method available!");
 266				return false;
 267			}
 268		}
 269		else
 270		{
 271			// no result returned
 272			$this->AddToLog("ERROR: SendAuth() #1");
 273			return false;
 274		}
 275	}
 276
 277
 278
 279	public function AccountRegistration($reg_email = null, $reg_name = null)
 280	{
 281		$packet = $this->SendIq($this->server, 'get', 'reg_01', 'jabber:iq:register');
 282
 283		if ($packet)
 284		{
 285			$key = $this->GetInfoFromIqKey($packet);	// just in case a key was passed back from the server
 286			unset($packet);
 287
 288			$payload = "<username>{$this->username}</username>
 289						<password>{$this->password}</password>
 290						<email>$reg_email</email>
 291						<name>$reg_name</name>\n";
 292
 293			$payload .= ($key) ? "<key>$key</key>\n" : '';
 294
 295			$packet = $this->SendIq($this->server, 'set', "reg_01", "jabber:iq:register", $payload);
 296
 297			if ($this->GetInfoFromIqType($packet) == 'result')
 298			{
 299				if (isset($packet['iq']['#']['query'][0]['#']['registered'][0]['#']))
 300				{
 301					$return_code = 1;
 302				}
 303				else
 304				{
 305					$return_code = 2;
 306				}
 307
 308				if ($this->resource)
 309				{
 310					$this->jid = "{$this->username}@{$this->server}/{$this->resource}";
 311				}
 312				else
 313				{
 314					$this->jid = "{$this->username}@{$this->server}";
 315				}
 316
 317			}
 318			elseif ($this->GetInfoFromIqType($packet) == 'error' && isset($packet['iq']['#']['error'][0]['#']))
 319			{
 320				// "conflict" error, i.e. already registered
 321				if ($packet['iq']['#']['error'][0]['@']['code'] == '409')
 322				{
 323					$return_code = 1;
 324				}
 325				else
 326				{
 327					$return_code = "Error " . $packet['iq']['#']['error'][0]['@']['code'] . ": " . $packet['iq']['#']['error'][0]['#'];
 328				}
 329			}
 330
 331			return $return_code;
 332
 333		}
 334		else
 335		{
 336			return 3;
 337		}
 338	}
 339
 340
 341
 342	public function SendPacket($xml)
 343	{
 344		$xml = trim($xml);
 345
 346		if ($this->CONNECTOR->WriteToSocket($xml))
 347		{
 348			$this->AddToLog("SEND: $xml");
 349			return true;
 350		}
 351		else
 352		{
 353			$this->AddToLog('ERROR: SendPacket() #1');
 354			return false;
 355		}
 356	}
 357
 358
 359
 360	public function Listen()
 361	{
 362		unset($incoming);
 363
 364		$incoming = '';
 365		while ($line = $this->CONNECTOR->ReadFromSocket(4096))
 366		{
 367			$incoming .= $line;
 368		}
 369
 370		$incoming = trim($incoming);
 371
 372		if ($incoming != "")
 373		{
 374			$this->AddToLog("RECV: $incoming");
 375		}
 376
 377		if ($incoming != "")
 378		{
 379			$temp = $this->_split_incoming($incoming);
 380
 381			for ($a = 0; $a < count($temp); $a++)
 382			{
 383				$this->packet_queue[] = $this->xmlize($temp[$a]);
 384			}
 385		}
 386
 387		return true;
 388	}
 389
 390
 391
 392	public function StripJID($jid = null)
 393	{
 394		preg_match("/(.*)\/(.*)/Ui", $jid, $temp);
 395		return ($temp[1] != "") ? $temp[1] : $jid;
 396	}
 397
 398
 399
 400	public function SendMessage($to, $type = "normal", $id = null, $content = null, $payload = null)
 401	{
 402		if ($to && is_array($content))
 403		{
 404			if (!$id)
 405			{
 406				$id = $type . "_" . time();
 407			}
 408
 409			$content = $this->_array_htmlspecialchars($content);
 410
 411			$xml = "<message to='$to' type='$type' id='$id'>\n";
 412
 413			if (isset($content['subject']))
 414			{
 415				$xml .= "<subject>" . $content['subject'] . "</subject>\n";
 416			}
 417
 418			if (isset($content['thread']))
 419			{
 420				$xml .= "<thread>" . $content['thread'] . "</thread>\n";
 421			}
 422
 423			$xml .= "<body>" . $content['body'] . "</body>\n";
 424			$xml .= $payload;
 425			$xml .= "</message>\n";
 426
 427
 428			if ($this->SendPacket($xml))
 429			{
 430				return true;
 431			}
 432			else
 433			{
 434				$this->AddToLog("ERROR: SendMessage() #1");
 435				return false;
 436			}
 437		}
 438		else
 439		{
 440			$this->AddToLog("ERROR: SendMessage() #2");
 441			return false;
 442		}
 443	}
 444
 445
 446
 447	public function SendPresence($type = null, $to = null, $status = null, $show = null, $priority = null)
 448	{
 449		$xml = "<presence";
 450		$xml .= ($to) ? " to='$to'" : '';
 451		$xml .= ($type) ? " type='$type'" : '';
 452		$xml .= ($status || $show || $priority) ? ">\n" : " />\n";
 453
 454		$xml .= ($status) ? "	<status>$status</status>\n" : '';
 455		$xml .= ($show) ? "	<show>$show</show>\n" : '';
 456		$xml .= ($priority) ? "	<priority>$priority</priority>\n" : '';
 457
 458		$xml .= ($status || $show || $priority) ? "</presence>\n" : '';
 459
 460		if ($this->SendPacket($xml))
 461		{
 462			return true;
 463		}
 464		else
 465		{
 466			$this->AddToLog("ERROR: SendPresence() #1");
 467			return false;
 468		}
 469	}
 470
 471
 472
 473	public function SendError($to, $id = null, $error_number, $error_message = null)
 474	{
 475		$xml = "<iq type='error' to='$to'";
 476		$xml .= ($id) ? " id='$id'" : '';
 477		$xml .= ">\n";
 478		$xml .= "	<error code='$error_number'>";
 479		$xml .= ($error_message) ? $error_message : $this->error_codes[$error_number];
 480		$xml .= "</error>\n";
 481		$xml .= "</iq>";
 482
 483		$this->SendPacket($xml);
 484	}
 485
 486
 487
 488	public function RosterUpdate()
 489	{
 490		$roster_request_id = "roster_" . time();
 491
 492		$incoming_array = $this->SendIq(null, 'get', $roster_request_id, "jabber:iq:roster");
 493
 494		if (is_array($incoming_array))
 495		{
 496			if ($incoming_array['iq']['@']['type'] == 'result'
 497				&& $incoming_array['iq']['@']['id'] == $roster_request_id
 498				&& $incoming_array['iq']['#']['query']['0']['@']['xmlns'] == "jabber:iq:roster")
 499			{
 500				$number_of_contacts = count($incoming_array['iq']['#']['query'][0]['#']['item']);
 501				$this->roster = array();
 502
 503				for ($a = 0; $a < $number_of_contacts; $a++)
 504				{
 505					$this->roster[$a] = array(	"jid"			=> strtolower($incoming_array['iq']['#']['query'][0]['#']['item'][$a]['@']['jid']),
 506												"name"			=> $incoming_array['iq']['#']['query'][0]['#']['item'][$a]['@']['name'],
 507												"subscription"	=> $incoming_array['iq']['#']['query'][0]['#']['item'][$a]['@']['subscription'],
 508												"group"			=> $incoming_array['iq']['#']['query'][0]['#']['item'][$a]['#']['group'][0]['#']
 509											);
 510				}
 511
 512				return true;
 513			}
 514			else
 515			{
 516				$this->AddToLog("ERROR: RosterUpdate() #1");
 517				return false;
 518			}
 519		}
 520		else
 521		{
 522			$this->AddToLog("ERROR: RosterUpdate() #2");
 523			return false;
 524		}
 525	}
 526
 527
 528
 529	public function RosterAddUser($jid = null, $id = null, $name = null)
 530	{
 531		$id = ($id) ? $id : "adduser_" . time();
 532
 533		if ($jid)
 534		{
 535			$payload = "		<item jid='$jid'";
 536			$payload .= ($name) ? " name='" . htmlspecialchars($name) . "'" : '';
 537			$payload .= "/>\n";
 538
 539			$packet = $this->SendIq(null, 'set', $id, "jabber:iq:roster", $payload);
 540
 541			if ($this->GetInfoFromIqType($packet) == 'result')
 542			{
 543				$this->RosterUpdate();
 544				return true;
 545			}
 546			else
 547			{
 548				$this->AddToLog("ERROR: RosterAddUser() #2");
 549				return false;
 550			}
 551		}
 552		else
 553		{
 554			$this->AddToLog("ERROR: RosterAddUser() #1");
 555			return false;
 556		}
 557	}
 558
 559
 560
 561	public function RosterRemoveUser($jid = null, $id = null)
 562	{
 563		$id = ($id) ? $id : 'deluser_' . time();
 564
 565		if ($jid && $id)
 566		{
 567			$packet = $this->SendIq(null, 'set', $id, "jabber:iq:roster", "<item jid='$jid' subscription='remove'/>");
 568
 569			if ($this->GetInfoFromIqType($packet) == 'result')
 570			{
 571				$this->RosterUpdate();
 572				return true;
 573			}
 574			else
 575			{
 576				$this->AddToLog("ERROR: RosterRemoveUser() #2");
 577				return false;
 578			}
 579		}
 580		else
 581		{
 582			$this->AddToLog("ERROR: RosterRemoveUser() #1");
 583			return false;
 584		}
 585	}
 586
 587
 588
 589	public function RosterExistsJID($jid = null)
 590	{
 591		if ($jid)
 592		{
 593			if ($this->roster)
 594			{
 595				for ($a = 0; $a < count($this->roster); $a++)
 596				{
 597					if ($this->roster[$a]['jid'] == strtolower($jid))
 598					{
 599						return $a;
 600					}
 601				}
 602			}
 603			else
 604			{
 605				$this->AddToLog("ERROR: RosterExistsJID() #2");
 606				return false;
 607			}
 608		}
 609		else
 610		{
 611			$this->AddToLog("ERROR: RosterExistsJID() #1");
 612			return false;
 613		}
 614	}
 615
 616
 617
 618	public function GetFirstFromQueue()
 619	{
 620		return array_shift($this->packet_queue);
 621	}
 622
 623
 624
 625	public function GetFromQueueById($packet_type, $id)
 626	{
 627		$found_message = false;
 628
 629		foreach ($this->packet_queue as $key => $value)
 630		{
 631			if ($value[$packet_type]['@']['id'] == $id)
 632			{
 633				$found_message = $value;
 634				unset($this->packet_queue[$key]);
 635
 636				break;
 637			}
 638		}
 639
 640		return (is_array($found_message)) ? $found_message : false;
 641	}
 642
 643
 644
 645	public function CallHandler($packet = null)
 646	{
 647		$packet_type	= $this->_get_packet_type($packet);
 648
 649		if ($packet_type == "message")
 650		{
 651			$type		= $packet['message']['@']['type'];
 652			$type		= ($type != "") ? $type : "normal";
 653			$funcmeth	= "Handler_message_$type";
 654		}
 655		elseif ($packet_type == "iq")
 656		{
 657			$namespace	= $packet['iq']['#']['query'][0]['@']['xmlns'];
 658			$namespace	= str_replace(":", "_", $namespace);
 659			$funcmeth	= "Handler_iq_$namespace";
 660		}
 661		elseif ($packet_type == "presence")
 662		{
 663			$type		= $packet['presence']['@']['type'];
 664			$type		= ($type != "") ? $type : "available";
 665			$funcmeth	= "Handler_presence_$type";
 666		}
 667
 668
 669		if ($funcmeth != '')
 670		{
 671			if (function_exists($funcmeth))
 672			{
 673				call_user_func($funcmeth, $packet);
 674			}
 675			elseif (method_exists($this, $funcmeth))
 676			{
 677				call_user_func(array(&$this, $funcmeth), $packet);
 678			}
 679			else
 680			{
 681				$this->Handler_NOT_IMPLEMENTED($packet);
 682				$this->AddToLog("ERROR: CallHandler() #1 - neither method nor function $funcmeth() available");
 683			}
 684		}
 685	}
 686
 687
 688
 689	public function CruiseControl($seconds = -1)
 690	{
 691		$count = 0;
 692
 693		while ($count != $seconds)
 694		{
 695			$this->Listen();
 696
 697			do {
 698				$packet = $this->GetFirstFromQueue();
 699
 700				if ($packet) {
 701					$this->CallHandler($packet);
 702				}
 703
 704			} while (count($this->packet_queue) > 1);
 705
 706			$count += 1;
 707			sleep(1);
 708			
 709			if ($this->last_ping_time + 180 < time())
 710			{
 711				// Modified by Nathan Fritz
 712				if ($this->returned_keep_alive == false)
 713				{
 714					$this->connected = false;
 715					$this->AddToLog('EVENT: Disconnected');
 716				}
 717				if ($this->returned_keep_alive == true)
 718				{
 719					$this->connected = true;
 720				}
 721
 722				$this->returned_keep_alive = false;
 723				$this->keep_alive_id = 'keep_alive_' . time();
 724				//$this->SendPacket("<iq id='{$this->keep_alive_id}'/>", 'CruiseControl');
 725				$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>");
 726				// **
 727
 728				$this->last_ping_time = time();
 729			}
 730		}
 731
 732		return true;
 733	}
 734
 735
 736
 737	public function SubscriptionAcceptRequest($to = null)
 738	{
 739		return ($to) ? $this->SendPresence("subscribed", $to) : false;
 740	}
 741
 742
 743
 744	public function SubscriptionDenyRequest($to = null)
 745	{
 746		return ($to) ? $this->SendPresence("unsubscribed", $to) : false;
 747	}
 748
 749
 750
 751	public function Subscribe($to = null)
 752	{
 753		return ($to) ? $this->SendPresence("subscribe", $to) : false;
 754	}
 755
 756
 757
 758	public function Unsubscribe($to = null)
 759	{
 760		return ($to) ? $this->SendPresence("unsubscribe", $to) : false;
 761	}
 762
 763
 764
 765	public function SendIq($to = null, $type = 'get', $id = null, $xmlns = null, $payload = null, $from = null)
 766	{
 767		if (!preg_match("/^(get|set|result|error)$/", $type))
 768		{
 769			unset($type);
 770
 771			$this->AddToLog("ERROR: SendIq() #2 - type must be 'get', 'set', 'result' or 'error'");
 772			return false;
 773		}
 774		elseif ($id && $xmlns)
 775		{
 776			$xml = "<iq type='$type' id='$id'";
 777			$xml .= ($to) ? " to='" . htmlspecialchars($to) . "'" : '';
 778			$xml .= ($from) ? " from='$from'" : '';
 779			$xml .= ">
 780						<query xmlns='$xmlns'>
 781							$payload
 782						</query>
 783					</iq>";
 784
 785			$this->SendPacket($xml);
 786			sleep($this->iq_sleep_timer);
 787			$this->Listen();
 788
 789			return (preg_match("/^(get|set)$/", $type)) ? $this->GetFromQueueById("iq", $id) : true;
 790		}
 791		else
 792		{
 793			$this->AddToLog("ERROR: SendIq() #1 - to, id and xmlns are mandatory");
 794			return false;
 795		}
 796	}
 797
 798
 799
 800	// get the transport registration fields
 801	// method written by Steve Blinch, http://www.blitzaffe.com 
 802	public function TransportRegistrationDetails($transport)
 803	{
 804		$this->txnid++;
 805		$packet = $this->SendIq($transport, 'get', "reg_{$this->txnid}", "jabber:iq:register", null, $this->jid);
 806
 807		if ($packet)
 808		{
 809			$res = array();
 810
 811			foreach ($packet['iq']['#']['query'][0]['#'] as $element => $data)
 812			{
 813				if ($element != 'instructions' && $element != 'key')
 814				{
 815					$res[] = $element;
 816				}
 817			}
 818
 819			return $res;
 820		}
 821		else
 822		{
 823			return 3;
 824		}
 825	}
 826	
 827
 828
 829	// register with the transport
 830	// method written by Steve Blinch, http://www.blitzaffe.com 
 831	public function TransportRegistration($transport, $details)
 832	{
 833		$this->txnid++;
 834		$packet = $this->SendIq($transport, 'get', "reg_{$this->txnid}", "jabber:iq:register", null, $this->jid);
 835
 836		if ($packet)
 837		{
 838			$key = $this->GetInfoFromIqKey($packet);	// just in case a key was passed back from the server
 839			unset($packet);
 840		
 841			$payload = ($key) ? "<key>$key</key>\n" : '';
 842			foreach ($details as $element => $value)
 843			{
 844				$payload .= "<$element>$value</$element>\n";
 845			}
 846		
 847			$packet = $this->SendIq($transport, 'set', "reg_{$this->txnid}", "jabber:iq:register", $payload);
 848		
 849			if ($this->GetInfoFromIqType($packet) == 'result')
 850			{
 851				if (isset($packet['iq']['#']['query'][0]['#']['registered'][0]['#']))
 852				{
 853					$return_code = 1;
 854				}
 855				else
 856				{
 857					$return_code = 2;
 858				}
 859			}
 860			elseif ($this->GetInfoFromIqType($packet) == 'error')
 861			{
 862				if (isset($packet['iq']['#']['error'][0]['#']))
 863				{
 864					$return_code = "Error " . $packet['iq']['#']['error'][0]['@']['code'] . ": " . $packet['iq']['#']['error'][0]['#'];
 865					$this->AddToLog('ERROR: TransportRegistration()');
 866				}
 867			}
 868
 869			return $return_code;
 870		}
 871		else
 872		{
 873			return 3;
 874		}
 875	}
 876
 877
 878
 879	public function GetvCard($jid = null, $id = null)
 880	{
 881		if (!$id)
 882		{
 883			$id = "vCard_" . md5(time() . $_SERVER['REMOTE_ADDR']);
 884		}
 885
 886		if ($jid)
 887		{
 888			$xml = "<iq type='get' to='$jid' id='$id'>
 889						<vCard xmlns='vcard-temp'/>
 890					</iq>";
 891
 892			$this->SendPacket($xml);
 893			sleep($this->iq_sleep_timer);
 894			$this->Listen();
 895
 896			return $this->GetFromQueueById("iq", $id);
 897		}
 898		else
 899		{
 900			$this->AddToLog("ERROR: GetvCard() #1 - to and id are mandatory");
 901			return false;
 902		}
 903	}
 904
 905
 906
 907	public function PrintLog()
 908	{
 909		if ($this->enable_logging)
 910		{
 911			if ($this->log_filehandler)
 912			{
 913				echo "<h2>Logging enabled, logged events have been written to the file {$this->log_filename}.</h2>\n";
 914			}
 915			else
 916			{
 917				echo "<h2>Logging enabled, logged events below:</h2>\n";
 918				echo "<pre>\n";
 919				echo (count($this->log_array) > 0) ? implode("\n\n\n", $this->log_array) : "No logged events.";
 920				echo "</pre>\n";
 921			}
 922		}
 923	}
 924
 925
 926
 927	// ======================================================================
 928	// private methods
 929	// ======================================================================
 930
 931
 932
 933	public function _sendauth_0k($zerok_token, $zerok_sequence)
 934	{
 935		// initial hash of password
 936		$zerok_hash = mhash(MHASH_SHA1, $this->password);
 937		$zerok_hash = bin2hex($zerok_hash);
 938
 939		// sequence 0: hash of hashed-password and token
 940		$zerok_hash = mhash(MHASH_SHA1, $zerok_hash . $zerok_token);
 941		$zerok_hash = bin2hex($zerok_hash);
 942
 943		// repeat as often as needed
 944		for ($a = 0; $a < $zerok_sequence; $a++)
 945		{
 946			$zerok_hash = mhash(MHASH_SHA1, $zerok_hash);
 947			$zerok_hash = bin2hex($zerok_hash);
 948		}
 949
 950		$payload = "<username>{$this->username}</username>
 951					<hash>$zerok_hash</hash>
 952					<resource>{$this->resource}</resource>";
 953
 954		$packet = $this->SendIq(null, 'set', $this->auth_id, "jabber:iq:auth", $payload);
 955
 956		// was a result returned?
 957		if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id)
 958		{
 959			return true;
 960		}
 961		else
 962		{
 963			$this->AddToLog("ERROR: _sendauth_0k() #1");
 964			return false;
 965		}
 966	}
 967
 968
 969
 970	public function _sendauth_digest()
 971	{
 972		$payload = "<username>{$this->username}</username>
 973					<resource>{$this->resource}</resource>
 974					<digest>" . bin2hex(mhash(MHASH_SHA1, $this->stream_id . $this->password)) . "</digest>";
 975
 976		$packet = $this->SendIq(null, 'set', $this->auth_id, "jabber:iq:auth", $payload);
 977
 978		// was a result returned?
 979		if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id)
 980		{
 981			return true;
 982		}
 983		else
 984		{
 985			$this->AddToLog("ERROR: _sendauth_digest() #1");
 986			return false;
 987		}
 988	}
 989
 990
 991
 992	public function _sendauth_plaintext()
 993	{
 994		$payload = "<username>{$this->username}</username>
 995					<password>{$this->password}</password>
 996					<resource>{$this->resource}</resource>";
 997
 998		$packet = $this->SendIq(null, 'set', $this->auth_id, "jabber:iq:auth", $payload);
 999
1000		// was a result returned?
1001		if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id)
1002		{
1003			return true;
1004		}
1005		else
1006		{
1007			$this->AddToLog("ERROR: _sendauth_plaintext() #1");
1008			return false;
1009		}
1010	}
1011
1012
1013
1014	public function _listen_incoming()
1015	{
1016		unset($incoming);
1017
1018		$incoming = '';
1019		while ($line = $this->CONNECTOR->ReadFromSocket(4096))
1020		{
1021			$incoming .= $line;
1022		}
1023
1024		$incoming = trim($incoming);
1025
1026		if ($incoming != "")
1027		{
1028			$this->AddToLog("RECV: $incoming");
1029		}
1030
1031		return $this->xmlize($incoming);
1032	}
1033
1034
1035
1036	public function _check_connected()
1037	{
1038		$incoming_array = $this->_listen_incoming();
1039
1040		if (is_array($incoming_array))
1041		{
1042			if ($incoming_array["stream:stream"]['@']['from'] == $this->server
1043				&& $incoming_array["stream:stream"]['@']['xmlns'] == "jabber:client"
1044				&& $incoming_array["stream:stream"]['@']["xmlns:stream"] == "http://etherx.jabber.org/streams")
1045			{
1046				$this->stream_id = $incoming_array["stream:stream"]['@']['id'];
1047
1048				if ($incoming_array["stream:stream"]["#"]["stream:features"][0]["#"]["starttls"][0]["@"]["xmlns"] == "urn:ietf:params:xml:ns:xmpp-tls")
1049				{
1050					return $this->_starttls();
1051				}
1052				else
1053				{
1054					return true;
1055				}
1056			}
1057			else
1058			{
1059				$this->AddToLog("ERROR: _check_connected() #1");
1060				return false;
1061			}
1062		}
1063		else
1064		{
1065			$this->AddToLog("ERROR: _check_connected() #2");
1066			return false;
1067		}
1068	}
1069
1070
1071
1072	public function _starttls()
1073	{
1074		if (!function_exists("stream_socket_enable_crypto"))
1075		{
1076			$this->AddToLog("WARNING: TLS is not available");
1077			return true;
1078		}
1079
1080		$this->SendPacket("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>\n");
1081		sleep(2);
1082		$incoming_array = $this->_listen_incoming();
1083
1084		if (!is_array($incoming_array))
1085		{
1086			$this->AddToLog("ERROR: _starttls() #1");
1087			return false;
1088		}
1089
1090		if ($incoming_array["proceed"]["@"]["xmlns"] != "urn:ietf:params:xml:ns:xmpp-tls")
1091		{
1092			$this->AddToLog("ERROR: _starttls() #2");
1093			return false;
1094		}
1095
1096		$meta = stream_get_meta_data($this->CONNECTOR->active_socket);
1097		socket_set_blocking($this->CONNECTOR->active_socket, 1);
1098		if (!@stream_socket_enable_crypto($this->CONNECTOR->active_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT))
1099		{
1100			socket_set_blocking($this->CONNECTOR->active_socket, $meta["blocked"]);
1101			$this->AddToLog("ERROR: _starttls() #3");
1102			return false;
1103		}
1104		socket_set_blocking($this->CONNECTOR->active_socket, $meta["blocked"]);
1105
1106		$this->SendPacket("<?xml version='1.0' encoding='UTF-8' ?" . ">\n");
1107		$this->SendPacket("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n");
1108		sleep(2);
1109
1110		if (!$this->_check_connected())
1111		{
1112			$this->AddToLog("ERROR: _starttls() #4");
1113			return false;
1114		}
1115
1116		return true;
1117	}
1118
1119
1120
1121	public function _get_packet_type($packet = null)
1122	{
1123		if (is_array($packet))
1124		{
1125			reset($packet);
1126			$packet_type = key($packet);
1127		}
1128
1129		return ($packet_type) ? $packet_type : false;
1130	}
1131
1132
1133
1134	public function _split_incoming($incoming)
1135	{
1136		$temp = preg_split("/<(message|iq|presence|stream)/", $incoming, -1, PREG_SPLIT_DELIM_CAPTURE);
1137		$array = array();
1138
1139		for ($a = 1; $a < count($temp); $a = $a + 2)
1140		{
1141			$array[] = "<" . $temp[$a] . $temp[($a + 1)];
1142		}
1143
1144		return $array;
1145	}
1146
1147
1148
1149	public function _create_logfile()
1150	{
1151		if ($this->log_filename != '' && $this->enable_logging)
1152		{
1153			$this->log_filehandler = fopen($this->log_filename, 'w');
1154		}
1155	}
1156
1157
1158
1159	public function AddToLog($string)
1160	{
1161		if ($this->enable_logging)
1162		{
1163			if ($this->log_filehandler)
1164			{
1165				#fwrite($this->log_filehandler, $string . "\n\n");
1166				print "$string \n\n";
1167			}
1168			else
1169			{
1170				$this->log_array[] = htmlspecialchars($string);
1171			}
1172		}
1173	}
1174
1175
1176
1177	public function _close_logfile()
1178	{
1179		if ($this->log_filehandler)
1180		{
1181			fclose($this->log_filehandler);
1182		}
1183	}
1184
1185
1186
1187	// _array_htmlspecialchars()
1188	// applies htmlspecialchars() to all values in an array
1189
1190	public function _array_htmlspecialchars($array)
1191	{
1192		if (is_array($array))
1193		{
1194			foreach ($array as $k => $v)
1195			{
1196				if (is_array($v))
1197				{
1198					$v = $this->_array_htmlspecialchars($v);
1199				}
1200				else
1201				{
1202					$v = htmlspecialchars($v);
1203				}
1204			}
1205		}
1206
1207		return $array;
1208	}
1209
1210
1211
1212	// ======================================================================
1213	// <message/> parsers
1214	// ======================================================================
1215
1216
1217
1218	public function GetInfoFromMessageFrom($packet = null)
1219	{
1220		return (is_array($packet)) ? $packet['message']['@']['from'] : false;
1221	}
1222
1223
1224
1225	public function GetInfoFromMessageType($packet = null)
1226	{
1227		return (is_array($packet)) ? $packet['message']['@']['type'] : false;
1228	}
1229
1230
1231
1232	public function GetInfoFromMessageId($packet = null)
1233	{
1234		return (is_array($packet)) ? $packet['message']['@']['id'] : false;
1235	}
1236
1237
1238
1239	public function GetInfoFromMessageThread($packet = null)
1240	{
1241		return (is_array($packet)) ? $packet['message']['#']['thread'][0]['#'] : false;
1242	}
1243
1244
1245
1246	public function GetInfoFromMessageSubject($packet = null)
1247	{
1248		return (is_array($packet)) ? $packet['message']['#']['subject'][0]['#'] : false;
1249	}
1250
1251
1252
1253	public function GetInfoFromMessageBody($packet = null)
1254	{
1255		return (is_array($packet)) ? $packet['message']['#']['body'][0]['#'] : false;
1256	}
1257
1258	public function GetInfoFromMessageXMLNS($packet = null)
1259	{
1260		return (is_array($packet)) ? $packet['message']['#']['x'] : false;
1261	}
1262
1263
1264
1265	public function GetInfoFromMessageError($packet = null)
1266	{
1267		$error = preg_replace("/^\/$/", "", ($packet['message']['#']['error'][0]['@']['code'] . "/" . $packet['message']['#']['error'][0]['#']));
1268		return (is_array($packet)) ? $error : false;
1269	}
1270
1271
1272
1273	// ======================================================================
1274	// <iq/> parsers
1275	// ======================================================================
1276
1277
1278
1279	public function GetInfoFromIqFrom($packet = null)
1280	{
1281		return (is_array($packet)) ? $packet['iq']['@']['from'] : false;
1282	}
1283
1284
1285
1286	public function GetInfoFromIqType($packet = null)
1287	{
1288		return (is_array($packet)) ? $packet['iq']['@']['type'] : false;
1289	}
1290
1291
1292
1293	public function GetInfoFromIqId($packet = null)
1294	{
1295		return (is_array($packet)) ? $packet['iq']['@']['id'] : false;
1296	}
1297
1298
1299
1300	public function GetInfoFromIqKey($packet = null)
1301	{
1302		return (is_array($packet)) ? $packet['iq']['#']['query'][0]['#']['key'][0]['#'] : false;
1303	}
1304
1305
1306
1307	public function GetInfoFromIqError($packet = null)
1308	{
1309		$error = preg_replace("/^\/$/", "", ($packet['iq']['#']['error'][0]['@']['code'] . "/" . $packet['iq']['#']['error'][0]['#']));
1310		return (is_array($packet)) ? $error : false;
1311	}
1312
1313
1314
1315	// ======================================================================
1316	// <presence/> parsers
1317	// ======================================================================
1318
1319
1320
1321	public function GetInfoFromPresenceFrom($packet = null)
1322	{
1323		return (is_array($packet)) ? $packet['presence']['@']['from'] : false;
1324	}
1325
1326
1327
1328	public function GetInfoFromPresenceType($packet = null)
1329	{
1330		return (is_array($packet)) ? $packet['presence']['@']['type'] : false;
1331	}
1332
1333
1334
1335	public function GetInfoFromPresenceStatus($packet = null)
1336	{
1337		return (is_array($packet)) ? $packet['presence']['#']['status'][0]['#'] : false;
1338	}
1339
1340
1341
1342	public function GetInfoFromPresenceShow($packet = null)
1343	{
1344		return (is_array($packet)) ? $packet['presence']['#']['show'][0]['#'] : false;
1345	}
1346
1347
1348
1349	public function GetInfoFromPresencePriority($packet = null)
1350	{
1351		return (is_array($packet)) ? $packet['presence']['#']['priority'][0]['#'] : false;
1352	}
1353
1354
1355
1356	// ======================================================================
1357	// <message/> handlers
1358	// ======================================================================
1359
1360
1361
1362	public function Handler_message_normal($packet)
1363	{
1364		$from = $packet['message']['@']['from'];
1365		$this->AddToLog("EVENT: Message (type normal) from $from");
1366	}
1367
1368
1369
1370	public function Handler_message_chat($packet)
1371	{
1372		$from = $packet['message']['@']['from'];
1373		$this->AddToLog("EVENT: Message (type chat) from $from");
1374	}
1375
1376
1377
1378	public function Handler_message_groupchat($packet)
1379	{
1380		$from = $packet['message']['@']['from'];
1381		$this->AddToLog("EVENT: Message (type groupchat) from $from");
1382	}
1383
1384
1385
1386	public function Handler_message_headline($packet)
1387	{
1388		$from = $packet['message']['@']['from'];
1389		$this->AddToLog("EVENT: Message (type headline) from $from");
1390	}
1391
1392
1393
1394	public function Handler_message_error($packet)
1395	{
1396		$from = $packet['message']['@']['from'];
1397		$this->AddToLog("EVENT: Message (type error) from $from");
1398	}
1399
1400
1401
1402	// ======================================================================
1403	// <iq/> handlers
1404	// ======================================================================
1405
1406
1407
1408	// application version updates
1409	public function Handler_iq_jabber_iq_autoupdate($packet)
1410	{
1411		$from	= $this->GetInfoFromIqFrom($packet);
1412		$id		= $this->GetInfoFromIqId($packet);
1413
1414		$this->SendError($from, $id, 501);
1415		$this->AddToLog("EVENT: jabber:iq:autoupdate from $from");
1416	}
1417
1418
1419
1420	// interactive server component properties
1421	public function Handler_iq_jabber_iq_agent($packet)
1422	{
1423		$from	= $this->GetInfoFromIqFrom($packet);
1424		$id		= $this->GetInfoFromIqId($packet);
1425
1426		$this->SendError($from, $id, 501);
1427		$this->AddToLog("EVENT: jabber:iq:agent from $from");
1428	}
1429
1430
1431
1432	// method to query interactive server components
1433	public function Handler_iq_jabber_iq_agents($packet)
1434	{
1435		$from	= $this->GetInfoFromIqFrom($packet);
1436		$id		= $this->GetInfoFromIqId($packet);
1437
1438		$this->SendError($from, $id, 501);
1439		$this->AddToLog("EVENT: jabber:iq:agents from $from");
1440	}
1441
1442
1443
1444	// simple client authentication
1445	public function Handler_iq_jabber_iq_auth($packet)
1446	{
1447		$from	= $this->GetInfoFromIqFrom($packet);
1448		$id		= $this->GetInfoFromIqId($packet);
1449
1450		$this->SendError($from, $id, 501);
1451		$this->AddToLog("EVENT: jabber:iq:auth from $from");
1452	}
1453
1454
1455
1456	// out of band data
1457	public function Handler_iq_jabber_iq_oob($packet)
1458	{
1459		$from	= $this->GetInfoFromIqFrom($packet);
1460		$id		= $this->GetInfoFromIqId($packet);
1461
1462		$this->SendError($from, $id, 501);
1463		$this->AddToLog("EVENT: jabber:iq:oob from $from");
1464	}
1465
1466
1467
1468	// method to store private data on the server
1469	public function Handler_iq_jabber_iq_private($packet)
1470	{
1471		$from	= $this->GetInfoFromIqFrom($packet);
1472		$id		= $this->GetInfoFromIqId($packet);
1473
1474		$this->SendError($from, $id, 501);
1475		$this->AddToLog("EVENT: jabber:iq:private from $from");
1476	}
1477
1478
1479
1480	// method for interactive registration
1481	public function Handler_iq_jabber_iq_register($packet)
1482	{
1483		$from	= $this->GetInfoFromIqFrom($packet);
1484		$id		= $this->GetInfoFromIqId($packet);
1485
1486		$this->SendError($from, $id, 501);
1487		$this->AddToLog("EVENT: jabber:iq:register from $from");
1488	}
1489
1490
1491
1492	// client roster management
1493	public function Handler_iq_jabber_iq_roster($packet)
1494	{
1495		$from	= $this->GetInfoFromIqFrom($packet);
1496		$id		= $this->GetInfoFromIqId($packet);
1497
1498		$this->SendError($from, $id, 501);
1499		$this->AddToLog("EVENT: jabber:iq:roster from $from");
1500	}
1501
1502
1503
1504	// method for searching a user database
1505	public function Handler_iq_jabber_iq_search($packet)
1506	{
1507		$from	= $this->GetInfoFromIqFrom($packet);
1508		$id		= $this->GetInfoFromIqId($packet);
1509
1510		$this->SendError($from, $id, 501);
1511		$this->AddToLog("EVENT: jabber:iq:search from $from");
1512	}
1513
1514
1515
1516	// method for requesting the current time
1517	public function Handler_iq_jabber_iq_time($packet)
1518	{
1519		if ($this->keep_alive_id == $this->GetInfoFromIqId($packet))
1520		{
1521			$this->returned_keep_alive = true;
1522			$this->connected = true;
1523			$this->AddToLog('EVENT: Keep-Alive returned, connection alive.');
1524		}
1525		$type	= $this->GetInfoFromIqType($packet);
1526		$from	= $this->GetInfoFromIqFrom($packet);
1527		$id		= $this->GetInfoFromIqId($packet);
1528		$id		= ($id != "") ? $id : "time_" . time();
1529
1530		if ($type == 'get')
1531		{
1532			$payload = "<utc>" . gmdate("Ydm\TH:i:s") . "</utc>
1533						<tz>" . date("T") . "</tz>
1534						<display>" . date("Y/d/m h:i:s A") . "</display>";
1535
1536			$this->SendIq($from, 'result', $id, "jabber:iq:time", $payload);
1537		}
1538
1539		$this->AddToLog("EVENT: jabber:iq:time (type $type) from $from");
1540	}
1541
1542	public function Handler_iq_error($packet)
1543	{
1544		// We'll do something with these later.  This is a placeholder so that errors don't bounce back and forth.
1545	}
1546
1547
1548
1549	// method for requesting version
1550	public function Handler_iq_jabber_iq_version($packet)
1551	{
1552		$type	= $this->GetInfoFromIqType($packet);
1553		$from	= $this->GetInfoFromIqFrom($packet);
1554		$id		= $this->GetInfoFromIqId($packet);
1555		$id		= ($id != "") ? $id : "version_" . time();
1556
1557		if ($type == 'get')
1558		{
1559			$payload = "<name>{$this->iq_version_name}</name>
1560						<os>{$this->iq_version_os}</os>
1561						<version>{$this->iq_version_version}</version>";
1562
1563			#$this->SendIq($from, 'result', $id, "jabber:iq:version", $payload);
1564		}
1565
1566		$this->AddToLog("EVENT: jabber:iq:version (type $type) from $from -- DISABLED");
1567	}
1568
1569
1570
1571	// keepalive method, added by Nathan Fritz
1572	/*
1573	public function Handler_jabber_iq_time($packet)
1574	{
1575		if ($this->keep_alive_id == $this->GetInfoFromIqId($packet))
1576		{
1577			$this->returned_keep_alive = true;
1578			$this->connected = true;
1579			$this->AddToLog('EVENT: Keep-Alive returned, connection alive.');
1580		}
1581	}
1582	*/
1583	
1584	
1585	// ======================================================================
1586	// <presence/> handlers
1587	// ======================================================================
1588
1589
1590
1591	public function Handler_presence_available($packet)
1592	{
1593		$from = $this->GetInfoFromPresenceFrom($packet);
1594
1595		$show_status = $this->GetInfoFromPresenceStatus($packet) . " / " . $this->GetInfoFromPresenceShow($packet);
1596		$show_status = ($show_status != " / ") ? " ($addendum)" : '';
1597
1598		$this->AddToLog("EVENT: Presence (type: available) - $from is available $show_status");
1599	}
1600
1601
1602
1603	public function Handler_presence_unavailable($packet)
1604	{
1605		$from = $this->GetInfoFromPresenceFrom($packet);
1606
1607		$show_status = $this->GetInfoFromPresenceStatus($packet) . " / " . $this->GetInfoFromPresenceShow($packet);
1608		$show_status = ($show_status != " / ") ? " ($addendum)" : '';
1609
1610		$this->AddToLog("EVENT: Presence (type: unavailable) - $from is unavailable $show_status");
1611	}
1612
1613
1614
1615	public function Handler_presence_subscribe($packet)
1616	{
1617		$from = $this->GetInfoFromPresenceFrom($packet);
1618		$this->SubscriptionAcceptRequest($from);
1619		$this->RosterUpdate();
1620
1621		$this->log_array[] = "<b>Presence:</b> (type: subscribe) - Subscription request from $from, was added to \$this->subscription_queue, roster updated";
1622	}
1623
1624
1625
1626	public function Handler_presence_subscribed($packet)
1627	{
1628		$from = $this->GetInfoFromPresenceFrom($packet);
1629		$this->RosterUpdate();
1630
1631		$this->AddToLog("EVENT: Presence (type: subscribed) - Subscription allowed by $from, roster updated");
1632	}
1633
1634
1635
1636	public function Handler_presence_unsubscribe($packet)
1637	{
1638		$from = $this->GetInfoFromPresenceFrom($packet);
1639		$this->SendPresence("unsubscribed", $from);
1640		$this->RosterUpdate();
1641
1642		$this->AddToLog("EVENT: Presence (type: unsubscribe) - Request to unsubscribe from $from, was automatically approved, roster updated");
1643	}
1644
1645
1646
1647	public function Handler_presence_unsubscribed($packet)
1648	{
1649		$from = $this->GetInfoFromPresenceFrom($packet);
1650		$this->RosterUpdate();
1651
1652		$this->AddToLog("EVENT: Presence (type: unsubscribed) - Unsubscribed from $from's presence");
1653	}
1654
1655
1656
1657	// Added By Nathan Fritz
1658	public function Handler_presence_error($packet)
1659	{
1660		$from = $this->GetInfoFromPresenceFrom($packet);
1661		$this->AddToLog("EVENT: Presence (type: error) - Error in $from's presence");
1662	}
1663	
1664	
1665	
1666	// ======================================================================
1667	// Generic handlers
1668	// ======================================================================
1669
1670
1671
1672	// Generic handler for unsupported requests
1673	public function Handler_NOT_IMPLEMENTED($packet)
1674	{
1675		$packet_type	= $this->_get_packet_type($packet);
1676		$from			= call_user_func(array(&$this, "GetInfoFrom" . ucfirst($packet_type) . "From"), $packet);
1677		$id				= call_user_func(array(&$this, "GetInfoFrom" . ucfirst($packet_type) . "Id"), $packet);
1678
1679		$this->SendError($from, $id, 501);
1680		$this->AddToLog("EVENT: Unrecognized <$packet_type/> from $from");
1681	}
1682
1683
1684
1685	// ======================================================================
1686	// Third party code
1687	// m@d pr0ps to the coders ;)
1688	// ======================================================================
1689
1690
1691
1692	// xmlize()
1693	// (c) Hans Anderson / http://www.hansanderson.com/php/xml/
1694
1695	public function xmlize($data, $WHITE=1, $encoding='UTF-8') {
1696
1697		$data = trim($data);
1698		$vals = $index = $array = array();
1699		$parser = xml_parser_create($encoding);
1700		xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
1701		xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, $WHITE);
1702		xml_parse_into_struct($parser, $data, $vals, $index);
1703		xml_parser_free($parser);
1704
1705		$i = 0;
1706
1707		$tagname = $vals[$i]['tag'];
1708		if ( isset ($vals[$i]['attributes'] ) )
1709		{
1710			$array[$tagname]['@'] = $vals[$i]['attributes'];
1711		} else {
1712			$array[$tagname]['@'] = array();
1713		}
1714
1715		$array[$tagname]["#"] = $this->_xml_depth($vals, $i);
1716
1717
1718		return $array;
1719	}
1720
1721
1722
1723	// _xml_depth()
1724	// (c) Hans Anderson / http://www.hansanderson.com/php/xml/
1725
1726	public function _xml_depth($vals, &$i) {
1727		$children = array();
1728
1729		if ( isset($vals[$i]['value']) )
1730		{
1731			array_push($children, $vals[$i]['value']);
1732		}
1733
1734		while (++$i < count($vals)) {
1735
1736			switch ($vals[$i]['type']) {
1737
1738				case 'open':
1739
1740					if ( isset ( $vals[$i]['tag'] ) )
1741					{
1742						$tagname = $vals[$i]['tag'];
1743					} else {
1744						$tagname = '';
1745					}
1746
1747					if ( isset ( $children[$tagname] ) )
1748					{
1749						$size = sizeof($children[$tagname]);
1750					} else {
1751						$size = 0;
1752					}
1753
1754					if ( isset ( $vals[$i]['attributes'] ) ) {
1755						$children[$tagname][$size]['@'] = $vals[$i]["attributes"];
1756
1757					}
1758
1759					$children[$tagname][$size]['#'] = $this->_xml_depth($vals, $i);
1760
1761					break;
1762
1763
1764				case 'cdata':
1765					array_push($children, $vals[$i]['value']);
1766					break;
1767
1768				case 'complete':
1769					$tagname = $vals[$i]['tag'];
1770
1771					if( isset ($children[$tagname]) )
1772					{
1773						$size = sizeof($children[$tagname]);
1774					} else {
1775						$size = 0;
1776					}
1777
1778					if( isset ( $vals[$i]['value'] ) )
1779					{
1780						$children[$tagname][$size]["#"] = $vals[$i]['value'];
1781					} else {
1782						$children[$tagname][$size]["#"] = array();
1783					}
1784
1785					if ( isset ($vals[$i]['attributes']) ) {
1786						$children[$tagname][$size]['@']
1787						= $vals[$i]['attributes'];
1788					}
1789
1790					break;
1791
1792				case 'close':
1793					return $children;
1794					break;
1795			}
1796
1797		}
1798
1799		return $children;
1800
1801
1802	}
1803
1804
1805
1806	// TraverseXMLize()
1807	// (c) acebone@f2s.com, a HUGE help!
1808
1809	public function TraverseXMLize($array, $arrName = "array", $level = 0) {
1810
1811		if ($level == 0)
1812		{
1813			echo "<pre>";
1814		}
1815
1816		foreach($array as $key=>$val)
1817		{
1818			if ( is_array($val) )
1819			{
1820				$this->TraverseXMLize($val, $arrName . "[" . $key . "]", $level + 1);
1821			} else {
1822				$GLOBALS['traverse_array'][] = '$' . $arrName . '[' . $key . '] = "' . $val . "\"\n";
1823			}
1824		}
1825
1826		if ($level == 0)
1827		{
1828			echo "</pre>";
1829		}
1830
1831		return 1;
1832
1833	}
1834}
1835
1836
1837
1838class MakeXML extends Jabber
1839{
1840	public $nodes;
1841
1842
1843	public function MakeXML()
1844	{
1845		$nodes = array();
1846	}
1847
1848
1849
1850	public function AddPacketDetails($string, $value = null)
1851	{
1852		if (preg_match("/\(([0-9]*)\)$/i", $string))
1853		{
1854			$string .= "/[\"#\"]";
1855		}
1856
1857		$temp = @explode("/", $string);
1858
1859		for ($a = 0; $a < count($temp); $a++)
1860		{
1861			$temp[$a] = preg_replace("/^[@]{1}([a-z0-9_]*)$/i", "[\"@\"][\"\\1\"]", $temp[$a]);
1862			$temp[$a] = preg_replace("/^([a-z0-9_]*)\(([0-9]*)\)$/i", "[\"\\1\"][\\2]", $temp[$a]);
1863			$temp[$a] = preg_replace("/^([a-z0-9_]*)$/i", "[\"\\1\"]", $temp[$a]);
1864		}
1865
1866		$node = implode("", $temp);
1867
1868		// Yeahyeahyeah, I know it's ugly... get over it. ;)
1869		echo "\$this->nodes$node = \"" . htmlspecialchars($value) . "\";<br/>";
1870		eval("\$this->nodes$node = \"" . htmlspecialchars($value) . "\";");
1871	}
1872
1873
1874
1875	public function BuildPacket($array = null)
1876	{
1877
1878		if (!$array)
1879		{
1880			$array = $this->nodes;
1881		}
1882
1883		if (is_array($array))
1884		{
1885			array_multisort($array, SORT_ASC, SORT_STRING);
1886
1887			foreach ($array as $key => $value)
1888			{
1889				if (is_array($value) && $key == "@")
1890				{
1891					foreach ($value as $subkey => $subvalue)
1892					{
1893						$subvalue = htmlspecialchars($subvalue);
1894						$text .= " $subkey='$subvalue'";
1895					}
1896
1897					$text .= ">\n";
1898
1899				}
1900				elseif ($key == "#")
1901				{
1902					$text .= htmlspecialchars($value);
1903				}
1904				elseif (is_array($value))
1905				{
1906					for ($a = 0; $a < count($value); $a++)
1907					{
1908						$text .= "<$key";
1909
1910						if (!$this->_preg_grep_keys("/^@/", $value[$a]))
1911						{
1912							$text .= ">";
1913						}
1914
1915						$text .= $this->BuildPacket($value[$a]);
1916
1917						$text .= "</$key>\n";
1918					}
1919				}
1920				else
1921				{
1922					$value = htmlspecialchars($value);
1923					$text .= "<$key>$value</$key>\n";
1924				}
1925			}
1926
1927			return $text;
1928		}
1929	}
1930
1931
1932
1933	public function _preg_grep_keys($pattern, $array)
1934	{
1935		while (list($key, $val) = each($array))
1936		{
1937			if (preg_match($pattern, $key))
1938			{
1939				$newarray[$key] = $val;
1940			}
1941		}
1942		return (is_array($newarray)) ? $newarray : false;
1943	}
1944}
1945
1946
1947
1948class CJP_StandardConnector
1949{
1950	public $active_socket;
1951
1952	public function OpenSocket($server, $port)
1953	{
1954		if (function_exists("dns_get_record"))
1955		{
1956			$record = dns_get_record("_xmpp-client._tcp.$server", DNS_SRV);
1957			if (!empty($record))
1958			{
1959				$server = $record[0]["target"];
1960				$port = $record[0]["port"];
1961			}
1962		}
1963
1964		if ($this->active_socket = fsockopen($server, $port))
1965		{
1966			socket_set_blocking($this->active_socket, 0);
1967			socket_set_timeout($this->active_socket, 31536000);
1968
1969			return true;
1970		}
1971		else
1972		{
1973			return false;
1974		}
1975	}
1976
1977
1978
1979	public function CloseSocket()
1980	{
1981		return fclose($this->active_socket);
1982	}
1983
1984
1985
1986	public function WriteToSocket($data)
1987	{
1988		if (false)
1989		{
1990			echo '>>> <pre>' . htmlspecialchars($data) . '</pre>';
1991		}
1992		return fwrite($this->active_socket, $data);
1993	}
1994
1995
1996
1997	public function ReadFromSocket($chunksize)
1998	{
1999		set_magic_quotes_runtime(0);
2000		$buffer = fread($this->active_socket, $chunksize);
2001		set_magic_quotes_runtime(get_magic_quotes_gpc());
2002
2003		return $buffer;
2004	}
2005}
2006
2007
2008
2009/* EOF */