683 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			683 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * XMPP Prebind for PHP
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @copyright 2011 Amiado Group AG
							 | 
						||
| 
								 | 
							
								 * @author Michael Weibel <michael.weibel@amiadogroup.com>
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * FirePHP for debugging
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								include 'FirePHP/fb.php';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * PEAR Auth_SASL
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								require 'Auth/SASL.php';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * XMPP Library for connecting to jabber server & receiving sid and rid
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								class XmppPrebind {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const XMLNS_BODY    = 'http://jabber.org/protocol/httpbind';
							 | 
						||
| 
								 | 
							
									const XMLNS_BOSH    = 'urn:xmpp:xbosh';
							 | 
						||
| 
								 | 
							
									const XMLNS_CLIENT  = 'jabber:client';
							 | 
						||
| 
								 | 
							
									const XMLNS_SESSION = 'urn:ietf:params:xml:ns:xmpp-session';
							 | 
						||
| 
								 | 
							
									const XMLNS_BIND    = 'urn:ietf:params:xml:ns:xmpp-bind';
							 | 
						||
| 
								 | 
							
									const XMLNS_SASL    = 'urn:ietf:params:xml:ns:xmpp-sasl';
							 | 
						||
| 
								 | 
							
									const XMLNS_VCARD   = 'vcard-temp';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const XML_LANG      = 'en';
							 | 
						||
| 
								 | 
							
									const CONTENT_TYPE  = 'text/xml charset=utf-8';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const ENCRYPTION_PLAIN      = 'PLAIN';
							 | 
						||
| 
								 | 
							
									const ENCRYPTION_DIGEST_MD5 = 'DIGEST-MD5';
							 | 
						||
| 
								 | 
							
									const ENCRYPTION_CRAM_MD5 = 'CRAM-MD5';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const SERVICE_NAME = 'xmpp';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									protected $jabberHost = '';
							 | 
						||
| 
								 | 
							
									protected $boshUri    = '';
							 | 
						||
| 
								 | 
							
									protected $resource   = '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									protected $debug = false;
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * FirePHP Instance
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @var FirePHP
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected $firePhp = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									protected $useGzip = false;
							 | 
						||
| 
								 | 
							
									protected $useSsl = false;
							 | 
						||
| 
								 | 
							
									protected $encryption = self::ENCRYPTION_PLAIN;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									protected $jid = '';
							 | 
						||
| 
								 | 
							
									protected $password = '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									protected $rid = '';
							 | 
						||
| 
								 | 
							
									protected $sid = '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									protected $doSession = false;
							 | 
						||
| 
								 | 
							
									protected $doBind    = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									protected $mechanisms = array();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// the Bosh attributes for use in a client using this prebound session
							 | 
						||
| 
								 | 
							
									protected $wait;
							 | 
						||
| 
								 | 
							
									protected $requests;
							 | 
						||
| 
								 | 
							
									protected $ver;
							 | 
						||
| 
								 | 
							
									protected $polling;
							 | 
						||
| 
								 | 
							
									protected $inactivity;
							 | 
						||
| 
								 | 
							
									protected $hold;
							 | 
						||
| 
								 | 
							
									protected $to;
							 | 
						||
| 
								 | 
							
									protected $ack;
							 | 
						||
| 
								 | 
							
									protected $accept;
							 | 
						||
| 
								 | 
							
									protected $maxpause;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Session creation response
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @var DOMDocument
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public $response;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Create a new XmppPrebind Object with the required params
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param string $jabberHost Jabber Server Host
							 | 
						||
| 
								 | 
							
									 * @param string $boshUri    Full URI to the http-bind
							 | 
						||
| 
								 | 
							
									 * @param string $resource   Resource identifier
							 | 
						||
| 
								 | 
							
									 * @param bool   $useSsl     Use SSL (not working yet, TODO)
							 | 
						||
| 
								 | 
							
									 * @param bool   $debug      Enable debug
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public function __construct($jabberHost, $boshUri, $resource, $useSsl = false, $debug = false) {
							 | 
						||
| 
								 | 
							
										$this->jabberHost = $jabberHost;
							 | 
						||
| 
								 | 
							
										$this->boshUri    = $boshUri;
							 | 
						||
| 
								 | 
							
										$this->resource   = $resource;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$this->useSsl = $useSsl;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$this->debug = $debug;
							 | 
						||
| 
								 | 
							
										if ($this->debug === true) {
							 | 
						||
| 
								 | 
							
											$this->firePhp = FirePHP::getInstance(true);
							 | 
						||
| 
								 | 
							
											$this->firePhp->setEnabled(true);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* TODO: Not working
							 | 
						||
| 
								 | 
							
										 if (function_exists('gzinflate')) {
							 | 
						||
| 
								 | 
							
											$this->useGzip = true;
							 | 
						||
| 
								 | 
							
										}*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/*
							 | 
						||
| 
								 | 
							
										 * The client MUST generate a large, random, positive integer for the initial 'rid' (see Security Considerations)
							 | 
						||
| 
								 | 
							
										 * and then increment that value by one for each subsequent request. The client MUST take care to choose an
							 | 
						||
| 
								 | 
							
										 * initial 'rid' that will never be incremented above 9007199254740991 [21] within the session.
							 | 
						||
| 
								 | 
							
										 * In practice, a session would have to be extraordinarily long (or involve the exchange of an extraordinary
							 | 
						||
| 
								 | 
							
										 * number of packets) to exceed the defined limit.
							 | 
						||
| 
								 | 
							
										 *
							 | 
						||
| 
								 | 
							
										 * @link http://xmpp.org/extensions/xep-0124.html#rids
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										if (function_exists('mt_rand')) {
							 | 
						||
| 
								 | 
							
											$this->rid = mt_rand(1000000000, 10000000000);
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											$this->rid = rand(1000000000, 10000000000);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * connect to the jabber server with the supplied username & password
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param string $username Username without jabber host
							 | 
						||
| 
								 | 
							
									 * @param string $password Password
							 | 
						||
| 
								 | 
							
									 * @param string $route Route
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public function connect($username, $password, $route = false) {
							 | 
						||
| 
								 | 
							
										$this->jid      = $username . '@' . $this->jabberHost;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if($this->resource) {
							 | 
						||
| 
								 | 
							
											$this->jid .= '/' . $this->resource;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$this->password = $password;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$response = $this->sendInitialConnection($route);
							 | 
						||
| 
								 | 
							
								        if(empty($response)) {
							 | 
						||
| 
								 | 
							
											throw new XmppPrebindConnectionException("No response from server.");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$body = self::getBodyFromXml($response);
							 | 
						||
| 
								 | 
							
								        if ( empty( $body ) )
							 | 
						||
| 
								 | 
							
											throw new XmppPrebindConnectionException("No body could be found in response from server.");
							 | 
						||
| 
								 | 
							
										$this->sid = $body->getAttribute('sid');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// set the Bosh Attributes
							 | 
						||
| 
								 | 
							
										$this->wait = $body->getAttribute('wait');
							 | 
						||
| 
								 | 
							
										$this->requests = $body->getAttribute('requests');
							 | 
						||
| 
								 | 
							
										$this->ver = $body->getAttribute('ver');
							 | 
						||
| 
								 | 
							
										$this->polling = $body->getAttribute('polling');
							 | 
						||
| 
								 | 
							
										$this->inactivity = $body->getAttribute('inactivity');
							 | 
						||
| 
								 | 
							
										$this->hold = $body->getAttribute('hold');
							 | 
						||
| 
								 | 
							
										$this->to = $body->getAttribute('to');
							 | 
						||
| 
								 | 
							
										$this->accept = $body->getAttribute('accept');
							 | 
						||
| 
								 | 
							
										$this->maxpause = $body->getAttribute('maxpause');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$this->debug($this->sid, 'sid');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if(empty($body->firstChild) || empty($body->firstChild->firstChild)) {
							 | 
						||
| 
								 | 
							
											throw new XmppPrebindConnectionException("Child not found in response from server.");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
										$mechanisms = $body->getElementsByTagName('mechanism');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										foreach ($mechanisms as $value) {
							 | 
						||
| 
								 | 
							
											$this->mechanisms[] = $value->nodeValue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (in_array(self::ENCRYPTION_DIGEST_MD5, $this->mechanisms)) {
							 | 
						||
| 
								 | 
							
											$this->encryption = self::ENCRYPTION_DIGEST_MD5;
							 | 
						||
| 
								 | 
							
										} elseif (in_array(self::ENCRYPTION_CRAM_MD5, $this->mechanisms)) {
							 | 
						||
| 
								 | 
							
											$this->encryption = self::ENCRYPTION_CRAM_MD5;
							 | 
						||
| 
								 | 
							
										} elseif (in_array(self::ENCRYPTION_PLAIN, $this->mechanisms)) {
							 | 
						||
| 
								 | 
							
											$this->encryption = self::ENCRYPTION_PLAIN;
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											throw new XmppPrebindConnectionException("No encryption supported by the server is supported by this library.");
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$this->debug($this->encryption, 'encryption used');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Assign session creation response
							 | 
						||
| 
								 | 
							
										$this->response = $body;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Try to authenticate
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @throws XmppPrebindException if invalid login
							 | 
						||
| 
								 | 
							
									 * @return bool
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public function auth() {
							 | 
						||
| 
								 | 
							
										$auth = Auth_SASL::factory($this->encryption);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										switch ($this->encryption) {
							 | 
						||
| 
								 | 
							
											case self::ENCRYPTION_PLAIN:
							 | 
						||
| 
								 | 
							
												$authXml = $this->buildPlainAuth($auth);
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
											case self::ENCRYPTION_DIGEST_MD5:
							 | 
						||
| 
								 | 
							
												$authXml = $this->sendChallengeAndBuildDigestMd5Auth($auth);
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
											case self::ENCRYPTION_CRAM_MD5:
							 | 
						||
| 
								 | 
							
												$authXml = $this->sendChallengeAndBuildCramMd5Auth($auth);
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										$response = $this->send($authXml);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$body = self::getBodyFromXml($response);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (!$body->hasChildNodes() || $body->firstChild->nodeName !== 'success') {
							 | 
						||
| 
								 | 
							
											throw new XmppPrebindException("Invalid login");
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$this->sendRestart();
							 | 
						||
| 
								 | 
							
										$this->sendBindIfRequired();
							 | 
						||
| 
								 | 
							
										$this->sendSessionIfRequired();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Get BOSH parameters to properly setup the BOSH client
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @return array
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public function getBoshInfo()
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return array(
							 | 
						||
| 
								 | 
							
											'wait' => $this->wait,
							 | 
						||
| 
								 | 
							
											'requests' => $this->requests,
							 | 
						||
| 
								 | 
							
											'ver' => $this->ver,
							 | 
						||
| 
								 | 
							
											'polling' => $this->polling,
							 | 
						||
| 
								 | 
							
											'inactivity' => $this->inactivity,
							 | 
						||
| 
								 | 
							
											'hold' => $this->hold,
							 | 
						||
| 
								 | 
							
											'to' => $this->to,
							 | 
						||
| 
								 | 
							
											'ack' => $this->ack,
							 | 
						||
| 
								 | 
							
											'accept' => $this->accept,
							 | 
						||
| 
								 | 
							
											'maxpause' => $this->maxpause,
							 | 
						||
| 
								 | 
							
										);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Get jid, sid and rid for attaching
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @return array
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public function getSessionInfo() {
							 | 
						||
| 
								 | 
							
										return array('jid' => $this->jid, 'sid' => $this->sid, 'rid' => $this->rid);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Debug if debug enabled
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param string $msg
							 | 
						||
| 
								 | 
							
									 * @param string $label
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function debug($msg, $label = null) {
							 | 
						||
| 
								 | 
							
										if ($this->firePhp) {
							 | 
						||
| 
								 | 
							
											$this->firePhp->log($msg, $label);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Send xmpp restart message after successful auth
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @return string Response
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function sendRestart() {
							 | 
						||
| 
								 | 
							
										$domDocument = $this->buildBody();
							 | 
						||
| 
								 | 
							
										$body = self::getBodyFromDomDocument($domDocument);
							 | 
						||
| 
								 | 
							
										$body->appendChild(self::getNewTextAttribute($domDocument, 'to', $this->jabberHost));
							 | 
						||
| 
								 | 
							
										$body->appendChild(self::getNewTextAttribute($domDocument, 'xmlns:xmpp', self::XMLNS_BOSH));
							 | 
						||
| 
								 | 
							
										$body->appendChild(self::getNewTextAttribute($domDocument, 'xmpp:restart', 'true'));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$restartResponse = $this->send($domDocument->saveXML());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$restartBody = self::getBodyFromXml($restartResponse);
							 | 
						||
| 
								 | 
							
										foreach ($restartBody->childNodes as $bodyChildNodes) {
							 | 
						||
| 
								 | 
							
											if ($bodyChildNodes->nodeName === 'stream:features') {
							 | 
						||
| 
								 | 
							
												foreach ($bodyChildNodes->childNodes as $streamFeatures) {
							 | 
						||
| 
								 | 
							
													if ($streamFeatures->nodeName === 'bind') {
							 | 
						||
| 
								 | 
							
														$this->doBind = true;
							 | 
						||
| 
								 | 
							
													} elseif ($streamFeatures->nodeName === 'session') {
							 | 
						||
| 
								 | 
							
														$this->doSession = true;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $restartResponse;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Send xmpp bind message after restart
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @return string Response
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function sendBindIfRequired() {
							 | 
						||
| 
								 | 
							
										if ($this->doBind) {
							 | 
						||
| 
								 | 
							
											$domDocument = $this->buildBody();
							 | 
						||
| 
								 | 
							
											$body = self::getBodyFromDomDocument($domDocument);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											$iq = $domDocument->createElement('iq');
							 | 
						||
| 
								 | 
							
											$iq->appendChild(self::getNewTextAttribute($domDocument, 'xmlns', self::XMLNS_CLIENT));
							 | 
						||
| 
								 | 
							
											$iq->appendChild(self::getNewTextAttribute($domDocument, 'type', 'set'));
							 | 
						||
| 
								 | 
							
											$iq->appendChild(self::getNewTextAttribute($domDocument, 'id', 'bind_' . rand()));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											$bind = $domDocument->createElement('bind');
							 | 
						||
| 
								 | 
							
											$bind->appendChild(self::getNewTextAttribute($domDocument, 'xmlns', self::XMLNS_BIND));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											$resource = $domDocument->createElement('resource');
							 | 
						||
| 
								 | 
							
											$resource->appendChild($domDocument->createTextNode($this->resource));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											$bind->appendChild($resource);
							 | 
						||
| 
								 | 
							
											$iq->appendChild($bind);
							 | 
						||
| 
								 | 
							
											$body->appendChild($iq);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return $this->send($domDocument->saveXML());
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Send session if there's a session node in the restart response (within stream:features)
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function sendSessionIfRequired() {
							 | 
						||
| 
								 | 
							
										if ($this->doSession) {
							 | 
						||
| 
								 | 
							
											$domDocument = $this->buildBody();
							 | 
						||
| 
								 | 
							
											$body = self::getBodyFromDomDocument($domDocument);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											$iq = $domDocument->createElement('iq');
							 | 
						||
| 
								 | 
							
											$iq->appendChild(self::getNewTextAttribute($domDocument, 'xmlns', self::XMLNS_CLIENT));
							 | 
						||
| 
								 | 
							
											$iq->appendChild(self::getNewTextAttribute($domDocument, 'type', 'set'));
							 | 
						||
| 
								 | 
							
											$iq->appendChild(self::getNewTextAttribute($domDocument, 'id', 'session_auth_' . rand()));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											$session = $domDocument->createElement('session');
							 | 
						||
| 
								 | 
							
											$session->appendChild(self::getNewTextAttribute($domDocument, 'xmlns', self::XMLNS_SESSION));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											$iq->appendChild($session);
							 | 
						||
| 
								 | 
							
											$body->appendChild($iq);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return $this->send($domDocument->saveXML());
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Send initial connection string
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param string $route
							 | 
						||
| 
								 | 
							
									 * @return string Response
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function sendInitialConnection($route = false) {
							 | 
						||
| 
								 | 
							
										$domDocument = $this->buildBody();
							 | 
						||
| 
								 | 
							
										$body = self::getBodyFromDomDocument($domDocument);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$waitTime = 60;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$body->appendChild(self::getNewTextAttribute($domDocument, 'hold', '1'));
							 | 
						||
| 
								 | 
							
										$body->appendChild(self::getNewTextAttribute($domDocument, 'to', $this->jabberHost));
							 | 
						||
| 
								 | 
							
										$body->appendChild(self::getNewTextAttribute($domDocument, 'xmlns:xmpp', self::XMLNS_BOSH));
							 | 
						||
| 
								 | 
							
										$body->appendChild(self::getNewTextAttribute($domDocument, 'xmpp:version', '1.0'));
							 | 
						||
| 
								 | 
							
										$body->appendChild(self::getNewTextAttribute($domDocument, 'wait', $waitTime));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ($route)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$body->appendChild(self::getNewTextAttribute($domDocument, 'route', $route));
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $this->send($domDocument->saveXML());
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Send challenge request
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @return string Challenge
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function sendChallenge() {
							 | 
						||
| 
								 | 
							
										$domDocument = $this->buildBody();
							 | 
						||
| 
								 | 
							
										$body = self::getBodyFromDomDocument($domDocument);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$auth = $domDocument->createElement('auth');
							 | 
						||
| 
								 | 
							
										$auth->appendChild(self::getNewTextAttribute($domDocument, 'xmlns', self::XMLNS_SASL));
							 | 
						||
| 
								 | 
							
										$auth->appendChild(self::getNewTextAttribute($domDocument, 'mechanism', $this->encryption));
							 | 
						||
| 
								 | 
							
										$body->appendChild($auth);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$response = $this->send($domDocument->saveXML());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$body = $this->getBodyFromXml($response);
							 | 
						||
| 
								 | 
							
										$challenge = base64_decode($body->firstChild->nodeValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $challenge;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Build PLAIN auth string
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param Auth_SASL_Common $auth
							 | 
						||
| 
								 | 
							
									 * @return string Auth XML to send
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function buildPlainAuth(Auth_SASL_Common $auth) {
							 | 
						||
| 
								 | 
							
										$authString = $auth->getResponse(self::getNodeFromJid($this->jid), $this->password, self::getBareJidFromJid($this->jid));
							 | 
						||
| 
								 | 
							
										$authString = base64_encode($authString);
							 | 
						||
| 
								 | 
							
										$this->debug($authString, 'PLAIN Auth String');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$domDocument = $this->buildBody();
							 | 
						||
| 
								 | 
							
										$body = self::getBodyFromDomDocument($domDocument);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$auth = $domDocument->createElement('auth');
							 | 
						||
| 
								 | 
							
										$auth->appendChild(self::getNewTextAttribute($domDocument, 'xmlns', self::XMLNS_SASL));
							 | 
						||
| 
								 | 
							
										$auth->appendChild(self::getNewTextAttribute($domDocument, 'mechanism', $this->encryption));
							 | 
						||
| 
								 | 
							
										$auth->appendChild($domDocument->createTextNode($authString));
							 | 
						||
| 
								 | 
							
										$body->appendChild($auth);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $domDocument->saveXML();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Send challenge request and build DIGEST-MD5 auth string
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param Auth_SASL_Common $auth
							 | 
						||
| 
								 | 
							
									 * @return string Auth XML to send
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function sendChallengeAndBuildDigestMd5Auth(Auth_SASL_Common $auth) {
							 | 
						||
| 
								 | 
							
										$challenge = $this->sendChallenge();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$authString = $auth->getResponse(self::getNodeFromJid($this->jid), $this->password, $challenge, $this->jabberHost, self::SERVICE_NAME);
							 | 
						||
| 
								 | 
							
										$this->debug($authString, 'DIGEST-MD5 Auth String');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$authString = base64_encode($authString);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$domDocument = $this->buildBody();
							 | 
						||
| 
								 | 
							
										$body = self::getBodyFromDomDocument($domDocument);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$response = $domDocument->createElement('response');
							 | 
						||
| 
								 | 
							
										$response->appendChild(self::getNewTextAttribute($domDocument, 'xmlns', self::XMLNS_SASL));
							 | 
						||
| 
								 | 
							
										$response->appendChild($domDocument->createTextNode($authString));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$body->appendChild($response);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$challengeResponse = $this->send($domDocument->saveXML());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $this->replyToChallengeResponse($challengeResponse);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Send challenge request and build CRAM-MD5 auth string
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param Auth_SASL_Common $auth
							 | 
						||
| 
								 | 
							
									 * @return string Auth XML to send
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function sendChallengeAndBuildCramMd5Auth(Auth_SASL_Common $auth) {
							 | 
						||
| 
								 | 
							
										$challenge = $this->sendChallenge();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$authString = $auth->getResponse(self::getNodeFromJid($this->jid), $this->password, $challenge);
							 | 
						||
| 
								 | 
							
										$this->debug($authString, 'CRAM-MD5 Auth String');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$authString = base64_encode($authString);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$domDocument = $this->buildBody();
							 | 
						||
| 
								 | 
							
										$body = self::getBodyFromDomDocument($domDocument);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$response = $domDocument->createElement('response');
							 | 
						||
| 
								 | 
							
										$response->appendChild(self::getNewTextAttribute($domDocument, 'xmlns', self::XMLNS_SASL));
							 | 
						||
| 
								 | 
							
										$response->appendChild($domDocument->createTextNode($authString));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$body->appendChild($response);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$challengeResponse = $this->send($domDocument->saveXML());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $this->replyToChallengeResponse($challengeResponse);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * CRAM-MD5 and DIGEST-MD5 reply with an additional challenge response which must be replied to.
							 | 
						||
| 
								 | 
							
									 * After this additional reply, the server should reply with "success".
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function replyToChallengeResponse($challengeResponse) {
							 | 
						||
| 
								 | 
							
										$body = self::getBodyFromXml($challengeResponse);
							 | 
						||
| 
								 | 
							
										$challenge = base64_decode((string)$body->firstChild->nodeValue);
							 | 
						||
| 
								 | 
							
										if (strpos($challenge, 'rspauth') === false) {
							 | 
						||
| 
								 | 
							
											throw new XmppPrebindConnectionException('Invalid challenge response received');
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$domDocument = $this->buildBody();
							 | 
						||
| 
								 | 
							
										$body = self::getBodyFromDomDocument($domDocument);
							 | 
						||
| 
								 | 
							
										$response = $domDocument->createElement('response');
							 | 
						||
| 
								 | 
							
										$response->appendChild(self::getNewTextAttribute($domDocument, 'xmlns', self::XMLNS_SASL));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$body->appendChild($response);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $domDocument->saveXML();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Send XML via CURL
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param string $xml
							 | 
						||
| 
								 | 
							
									 * @return string Response
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function send($xml) {
							 | 
						||
| 
								 | 
							
										$ch = curl_init($this->boshUri);
							 | 
						||
| 
								 | 
							
										curl_setopt($ch, CURLOPT_HEADER, 0);
							 | 
						||
| 
								 | 
							
										curl_setopt($ch, CURLOPT_POST, 1);
							 | 
						||
| 
								 | 
							
										curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
							 | 
						||
| 
								 | 
							
										curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$header = array('Content-Type: ' . self::CONTENT_TYPE);
							 | 
						||
| 
								 | 
							
										if ($this->useGzip) {
							 | 
						||
| 
								 | 
							
											$header[] = 'Accept-Encoding: gzip, deflate';
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										curl_setopt($ch, CURLOPT_VERBOSE, 0);
							 | 
						||
| 
								 | 
							
										curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$response = curl_exec($ch);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Check if curl failed to get response
							 | 
						||
| 
								 | 
							
										if ($response === false) {
							 | 
						||
| 
								 | 
							
											throw new XmppPrebindConnectionException("Cannot connect to service");
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										curl_close($ch);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ($this->useGzip) {
							 | 
						||
| 
								 | 
							
											$response = self::compatibleGzInflate($response);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$this->debug($xml, 'SENT');
							 | 
						||
| 
								 | 
							
										$this->debug($response, 'RECV:');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $response;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Fix gzdecompress/gzinflate data error warning.
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @link http://www.mydigitallife.info/2010/01/17/workaround-to-fix-php-warning-gzuncompress-or-gzinflate-data-error-in-wordpress-http-php/
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param string $gzData
							 | 
						||
| 
								 | 
							
									 * @return string|bool
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public static function compatibleGzInflate($gzData) {
							 | 
						||
| 
								 | 
							
										if ( substr($gzData, 0, 3) == "\x1f\x8b\x08" ) {
							 | 
						||
| 
								 | 
							
											$i = 10;
							 | 
						||
| 
								 | 
							
											$flg = ord( substr($gzData, 3, 1) );
							 | 
						||
| 
								 | 
							
											if ( $flg > 0 ) {
							 | 
						||
| 
								 | 
							
												if ( $flg & 4 ) {
							 | 
						||
| 
								 | 
							
													list($xlen) = unpack('v', substr($gzData, $i, 2) );
							 | 
						||
| 
								 | 
							
													$i = $i + 2 + $xlen;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												if ( $flg & 8 )
							 | 
						||
| 
								 | 
							
													$i = strpos($gzData, "\0", $i) + 1;
							 | 
						||
| 
								 | 
							
												if ( $flg & 16 )
							 | 
						||
| 
								 | 
							
													$i = strpos($gzData, "\0", $i) + 1;
							 | 
						||
| 
								 | 
							
												if ( $flg & 2 )
							 | 
						||
| 
								 | 
							
													$i = $i + 2;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											return gzinflate( substr($gzData, $i, -8) );
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Build DOMDocument with standard xmpp body child node.
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @return DOMDocument
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function buildBody() {
							 | 
						||
| 
								 | 
							
										$xml = new DOMDocument('1.0', 'UTF-8');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$body = $xml->createElement('body');
							 | 
						||
| 
								 | 
							
										$xml->appendChild($body);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$body->appendChild(self::getNewTextAttribute($xml, 'xmlns', self::XMLNS_BODY));
							 | 
						||
| 
								 | 
							
										$body->appendChild(self::getNewTextAttribute($xml, 'content', self::CONTENT_TYPE));
							 | 
						||
| 
								 | 
							
										$body->appendChild(self::getNewTextAttribute($xml, 'rid', $this->getAndIncrementRid()));
							 | 
						||
| 
								 | 
							
										$body->appendChild(self::getNewTextAttribute($xml, 'xml:lang', self::XML_LANG));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ($this->sid != '') {
							 | 
						||
| 
								 | 
							
											$body->appendChild(self::getNewTextAttribute($xml, 'sid', $this->sid));
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $xml;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Get jid in form of username@jabberHost
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param string $jid Jid in form username@jabberHost/Resource
							 | 
						||
| 
								 | 
							
									 * @return string JID
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public static function getBareJidFromJid($jid) {
							 | 
						||
| 
								 | 
							
										if ($jid == '') {
							 | 
						||
| 
								 | 
							
											return '';
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										$splittedJid = explode('/', $jid, 1);
							 | 
						||
| 
								 | 
							
										return $splittedJid[0];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Get node (username) from jid
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param string $jid
							 | 
						||
| 
								 | 
							
									 * @return string Node
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public static function getNodeFromJid($jid) {
							 | 
						||
| 
								 | 
							
										$atPos = strpos($jid, '@');
							 | 
						||
| 
								 | 
							
										if ($atPos === false) {
							 | 
						||
| 
								 | 
							
											return '';
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return substr($jid, 0, $atPos);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Append new attribute to existing DOMDocument.
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param DOMDocument $domDocument
							 | 
						||
| 
								 | 
							
									 * @param string $attributeName
							 | 
						||
| 
								 | 
							
									 * @param string $value
							 | 
						||
| 
								 | 
							
									 * @return DOMNode
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected static function getNewTextAttribute($domDocument, $attributeName, $value) {
							 | 
						||
| 
								 | 
							
										$attribute = $domDocument->createAttribute($attributeName);
							 | 
						||
| 
								 | 
							
										$attribute->appendChild($domDocument->createTextNode($value));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $attribute;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Get body node from DOMDocument
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param DOMDocument $domDocument
							 | 
						||
| 
								 | 
							
									 * @return DOMNode
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected static function getBodyFromDomDocument($domDocument) {
							 | 
						||
| 
								 | 
							
										$body = $domDocument->getElementsByTagName('body');
							 | 
						||
| 
								 | 
							
										return $body->item(0);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Parse XML and return DOMNode of the body
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @uses XmppPrebind::getBodyFromDomDocument()
							 | 
						||
| 
								 | 
							
									 * @param string $xml
							 | 
						||
| 
								 | 
							
									 * @return DOMNode
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected static function getBodyFromXml($xml) {
							 | 
						||
| 
								 | 
							
										$domDocument = new DOMDocument();
							 | 
						||
| 
								 | 
							
										$domDocument->loadXml($xml);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return self::getBodyFromDomDocument($domDocument);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Get the rid and increment it by one.
							 | 
						||
| 
								 | 
							
									 * Required by RFC
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @return int
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function getAndIncrementRid() {
							 | 
						||
| 
								 | 
							
										return $this->rid++;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Standard XmppPrebind Exception
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								class XmppPrebindException extends Exception{}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class XmppPrebindConnectionException extends XmppPrebindException{}
							 |