This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "quickfw".
The branch, master has been updated
via c8e7843959370e2207228f2760c5552ee29b5feb (commit)
from 07da8658a0698e65a4be9da195033392da7ce013 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit c8e7843959370e2207228f2760c5552ee29b5feb
Author: Ivan1986 <iva...@li...>
Date: Mon Jun 21 17:53:10 2010 +0400
Обновил xmpphp
diff --git a/lib/jabber/XMPPHP/BOSH.php b/lib/jabber/XMPPHP/BOSH.php
index befaf60..49e977d 100644
--- a/lib/jabber/XMPPHP/BOSH.php
+++ b/lib/jabber/XMPPHP/BOSH.php
@@ -27,7 +27,7 @@
*/
/** XMPPHP_XMLStream */
-require_once dirname(__FILE__) . "/XMPP.php";
+require_once dirname(__FILE__) . '/XMPP.php';
/**
* XMPPHP Main Class
diff --git a/lib/jabber/XMPPHP/DIGEST-MD5.patch b/lib/jabber/XMPPHP/DIGEST-MD5.patch
deleted file mode 100644
index 898f5c5..0000000
--- a/lib/jabber/XMPPHP/DIGEST-MD5.patch
+++ /dev/null
@@ -1,132 +0,0 @@
---- XMPP.php.old 2009-08-27 15:05:34.000000000 +0400
-+++ XMPP.php 2009-11-19 16:56:19.000000000 +0300
-@@ -99,6 +99,21 @@
- public $roster;
-
- /**
-+ * @var array supported auth mechanisms
-+ */
-+ protected $auth_mechanism_supported = array('PLAIN', 'DIGEST-MD5');
-+
-+ /**
-+ * @var string default auth mechanism
-+ */
-+ protected $auth_mechanism_default = 'PLAIN';
-+
-+ /**
-+ * @var string prefered auth mechanism
-+ */
-+ protected $auth_mechanism_preferred = 'DIGEST-MD5';
-+
-+ /**
- * Constructor
- *
- * @param string $host
-@@ -117,6 +132,7 @@
- $this->password = $password;
- $this->resource = $resource;
- if(!$server) $server = $host;
-+ $this->server = $server;
- $this->basejid = $this->user . '@' . $this->host;
-
- $this->roster = new Roster();
-@@ -132,6 +148,8 @@
- $this->addXPathHandler('{jabber:client}message', 'message_handler');
- $this->addXPathHandler('{jabber:client}presence', 'presence_handler');
- $this->addXPathHandler('iq/{jabber:iq:roster}query', 'roster_iq_handler');
-+ // For DIGEST-MD5 auth :
-+ $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}challenge', 'sasl_challenge_handler');
- }
-
- /**
-@@ -326,7 +344,33 @@
- } else {
- $this->log->log("Attempting Auth...");
- if ($this->password) {
-- $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>" . base64_encode("\x00" . $this->user . "\x00" . $this->password) . "</auth>");
-+ $mechanism = 'PLAIN'; // default;
-+ if ($xml->hasSub('mechanisms') && $xml->sub('mechanisms')->hasSub('mechanism')) {
-+ // Get the list of all available auth mechanism that we can use
-+ $available = array();
-+ foreach ($xml->sub('mechanisms')->subs as $sub) {
-+ if ($sub->name == 'mechanism') {
-+ if (in_array($sub->data, $this->auth_mechanism_supported)) {
-+ $available[$sub->data] = $sub->data;
-+ }
-+ }
-+ }
-+ if (isset($available[$this->auth_mechanism_preferred])) {
-+ $mechanism = $this->auth_mechanism_preferred;
-+ } else {
-+ // use the first available
-+ $mechanism = reset($available);
-+ }
-+ $this->log->log("Trying $mechanism (available : " . implode(',', $available) . ')');
-+ }
-+ switch ($mechanism) {
-+ case 'PLAIN':
-+ $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>" . base64_encode("\x00" . $this->user . "\x00" . $this->password) . "</auth>");
-+ break;
-+ case 'DIGEST-MD5':
-+ $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5' />");
-+ break;
-+ }
- } else {
- $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>");
- }
-@@ -357,6 +401,55 @@
- }
-
- /**
-+ * Handle challenges for DIGEST-MD5 auth
-+ *
-+ * @param string $xml
-+ */
-+ protected function sasl_challenge_handler($xml) {
-+ // Decode and parse the challenge string
-+ // (may be something like foo="bar",foo2="bar2,bar3,bar4",foo3=bar5 )
-+ $challenge = base64_decode($xml->data);
-+ $vars = array();
-+ $matches = array();
-+ preg_match_all('/(\w+)=(?:"([^"]*)|([^,]*))/', $challenge, $matches);
-+ $res = array();
-+ foreach ($matches[1] as $k => $v) {
-+ $vars[$v] = (empty($matches[2][$k])?$matches[3][$k]:$matches[2][$k]);
-+ }
-+
-+ if (isset($vars['nonce'])) {
-+ // First step
-+ $vars['cnonce'] = uniqid(mt_rand(), false);
-+ $vars['nc'] = '00000001';
-+ $vars['qop'] = 'auth'; // Force qop to auth
-+ if (!isset($vars['digest-uri'])) $vars['digest-uri'] = 'xmpp/' . $this->server;
-+
-+ // now, the magic...
-+ $a1 = sprintf('%s:%s:%s', $this->user, $vars['realm'], $this->password);
-+ if ($vars['algorithm'] == 'md5-sess') {
-+ $a1 = pack('H32',md5($a1)) . ':' . $vars['nonce'] . ':' . $vars['cnonce'];
-+ }
-+ $a2 = "AUTHENTICATE:" . $vars['digest-uri'];
-+ $password = md5($a1) . ':' . $vars['nonce'] . ':' . $vars['nc'] . ':' . $vars['cnonce'] . ':' . $vars['qop'] . ':' .md5($a2);
-+ $password = md5($password);
-+ $response = sprintf('username="%s",realm="%s",nonce="%s",cnonce="%s",nc=%s,qop=%s,digest-uri="%s",response=%s,charset=utf-8',
-+ $this->user, $vars['realm'], $vars['nonce'], $vars['cnonce'], $vars['nc'], $vars['qop'], $vars['digest-uri'], $password);
-+
-+ // Send the response
-+ $response = base64_encode($response);
-+ $this->send("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>$response</response>");
-+ } else {
-+ if (isset($vars['rspauth'])) {
-+ // Second step
-+ $this->send("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>");
-+ } else {
-+ $this->log->log("ERROR receiving challenge : " . $challenge, XMPPHP_Log::LEVEL_ERROR);
-+ }
-+
-+ }
-+ }
-+
-+ /**
- * Resource bind handler
- *
- * @param string $xml
diff --git a/lib/jabber/XMPPHP/Roster.php b/lib/jabber/XMPPHP/Roster.php
index cea9a95..30117bb 100644
--- a/lib/jabber/XMPPHP/Roster.php
+++ b/lib/jabber/XMPPHP/Roster.php
@@ -3,22 +3,22 @@
* XMPPHP: The PHP XMPP Library
* Copyright (C) 2008 Nathanael C. Fritz
* This file is part of SleekXMPP.
- *
+ *
* XMPPHP is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* XMPPHP is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with XMPPHP; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
- * @category xmpphp
+ * @category xmpphp
* @package XMPPHP
* @author Nathanael C. Fritz <JID: fr...@ne...>
* @author Stephan Wentz <JID: st...@ja...>
@@ -28,8 +28,8 @@
/**
* XMPPHP Roster Object
- *
- * @category xmpphp
+ *
+ * @category xmpphp
* @package XMPPHP
* @author Nathanael C. Fritz <JID: fr...@ne...>
* @author Stephan Wentz <JID: st...@ja...>
@@ -47,7 +47,7 @@ class Roster {
protected $roster_array = array();
/**
* Constructor
- *
+ *
*/
public function __construct($roster_array = array()) {
if ($this->verifyRoster($roster_array)) {
@@ -87,7 +87,7 @@ class Roster {
}
/**
- *
+ *
* Retrieve contact via jid
*
* @param string $jid
@@ -127,6 +127,7 @@ class Roster {
}
$this->roster_array[$jid]['presence'][$resource] = array('priority' => $priority, 'show' => $show, 'status' => $status);
} else { //Nuke unavailable resources to save memory
+ unset($this->roster_array[$jid]['resource'][$resource]);
unset($this->roster_array[$jid]['presence'][$resource]);
}
}
diff --git a/lib/jabber/XMPPHP/XMLStream.php b/lib/jabber/XMPPHP/XMLStream.php
index 4214ea2..d818881 100644
--- a/lib/jabber/XMPPHP/XMLStream.php
+++ b/lib/jabber/XMPPHP/XMLStream.php
@@ -3,22 +3,22 @@
* XMPPHP: The PHP XMPP Library
* Copyright (C) 2008 Nathanael C. Fritz
* This file is part of SleekXMPP.
- *
+ *
* XMPPHP is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* XMPPHP is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with XMPPHP; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
- * @category xmpphp
+ * @category xmpphp
* @package XMPPHP
* @author Nathanael C. Fritz <JID: fr...@ne...>
* @author Stephan Wentz <JID: st...@ja...>
@@ -33,12 +33,12 @@ require_once dirname(__FILE__) . '/Exception.php';
require_once dirname(__FILE__) . '/XMLObj.php';
/** XMPPHP_Log */
-require_once dirname(__FILE__) . '/XMPPHP_Log.php';
+require_once dirname(__FILE__) . '/Log.php';
/**
* XMPPHP XML Stream
- *
- * @category xmpphp
+ *
+ * @category xmpphp
* @package XMPPHP
* @author Nathanael C. Fritz <JID: fr...@ne...>
* @author Stephan Wentz <JID: st...@ja...>
@@ -195,7 +195,7 @@ class XMPPHP_XMLStream {
$this->disconnect();
}
}
-
+
/**
* Return the log instance
*
@@ -204,7 +204,7 @@ class XMPPHP_XMLStream {
public function getLog() {
return $this->log;
}
-
+
/**
* Get next ID
*
@@ -288,14 +288,17 @@ class XMPPHP_XMLStream {
/**
* Connect to XMPP Host
*
- * @param integer $timeout
+ * @param integer $timeout Timeout in seconds
* @param boolean $persistent
- * @param boolean $sendinit
+ * @param boolean $sendinit Send XMPP starting sequence after connect
+ * automatically
+ *
+ * @throws XMPPHP_Exception When the connection fails
*/
public function connect($timeout = 30, $persistent = false, $sendinit = true) {
$this->sent_disconnect = false;
$starttime = time();
-
+
do {
$this->disconnected = false;
$this->sent_disconnect = false;
@@ -319,7 +322,7 @@ class XMPPHP_XMLStream {
sleep(min($timeout, 5));
}
} while (!$this->socket && (time() - $starttime) < $timeout);
-
+
if ($this->socket) {
stream_set_blocking($this->socket, 1);
if($sendinit) $this->send($this->stream_start);
@@ -330,6 +333,10 @@ class XMPPHP_XMLStream {
/**
* Reconnect XMPP Host
+ *
+ * @throws XMPPHP_Exception When the connection fails
+ * @uses $reconnectTimeout
+ * @see setReconnectTimeout()
*/
public function doReconnect() {
if(!$this->is_server) {
@@ -343,7 +350,7 @@ class XMPPHP_XMLStream {
public function setReconnectTimeout($timeout) {
$this->reconnectTimeout = $timeout;
}
-
+
/**
* Disconnect from XMPP Host
*/
@@ -369,16 +376,59 @@ class XMPPHP_XMLStream {
}
/**
- * Core reading tool
- * 0 -> only read if data is immediately ready
- * NULL -> wait forever and ever
- * integer -> process for this amount of time
+ * Checks if the given string is closed with the same tag as it is
+ * opened. We try to be as fast as possible here.
+ *
+ * @param string $buff Read buffer of __process()
+ *
+ * @return boolean true if the buffer seems to be complete
*/
+ protected function bufferComplete($buff)
+ {
+ if (substr($buff, -1) != '>') {
+ return false;
+ }
+ //we always have a space since the namespace needs to be
+ //declared. could be a tab, though
+ $start = substr(
+ $buff, 1,
+ min(strpos($buff, '>', 2), strpos($buff, ' ', 2)) - 1
+ );
+ $stop = substr($buff, -strlen($start) - 3);
+
+ if ($start == '?xml') {
+ //starting with an xml tag. this means a stream is being
+ // opened, which is not much of data, so no fear it's
+ // not complete
+ return true;
+ }
+ if (substr($stop, -2) == '/>') {
+ //one tag, i.e. <success />
+ return true;
+ }
+ if ('</' . $start . '>' == $stop) {
+ return true;
+ }
- private function __process($maximum=0) {
+ return false;
+ }
+ /**
+ * Core reading tool
+ *
+ * @param mixed $maximum Limit when to return
+ * - 0: only read if data is immediately ready
+ * - NULL: wait forever and ever
+ * - integer: process for this amount of microseconds
+ * @param boolean $return_when_received Immediately return when data have been
+ * received
+ *
+ * @return boolean True when all goes well, false when something fails
+ */
+ private function __process($maximum = 5, $return_when_received = false)
+ {
$remaining = $maximum;
-
+
do {
$starttime = (microtime(true) * 1000000);
$read = array($this->socket);
@@ -387,13 +437,16 @@ class XMPPHP_XMLStream {
if (is_null($maximum)) {
$secs = NULL;
$usecs = NULL;
+ } else if ($maximum == 0) {
+ $secs = 0;
+ $usecs = 0;
} else {
$usecs = $remaining % 1000000;
- $secs = floor($remaining / 1000000);
+ $secs = floor(($remaining - $usecs) / 1000000);
}
- $updated = stream_select($read, $write, $except, $secs, $usecs);
+ $updated = @stream_select($read, $write, $except, $secs, $usecs);
if ($updated === false) {
- $this->log->log("Error on stream_select()", XMPPHP_Log::LEVEL_VERBOSE);
+ $this->log->log("Error on stream_select()", XMPPHP_Log::LEVEL_VERBOSE);
if ($this->reconnect) {
$this->doReconnect();
} else {
@@ -402,19 +455,33 @@ class XMPPHP_XMLStream {
return false;
}
} else if ($updated > 0) {
- # XXX: Is this big enough?
- $buff = @fread($this->socket, 4096);
- if(!$buff) {
- if($this->reconnect) {
- $this->doReconnect();
- } else {
- fclose($this->socket);
- $this->socket = NULL;
- return false;
+ $buff = '';
+ do {
+ if ($buff != '') {
+ //disable blocking for now because fread() will
+ // block until the 4k are full if we already
+ // read a part of the packet
+ stream_set_blocking($this->socket, 0);
}
- }
- $this->log->log("RECV: $buff", XMPPHP_Log::LEVEL_VERBOSE);
+ $part = fread($this->socket, 4096);
+ stream_set_blocking($this->socket, 1);
+ if ($part === false) {
+ if($this->reconnect) {
+ $this->doReconnect();
+ } else {
+ fclose($this->socket);
+ $this->socket = NULL;
+ return false;
+ }
+ }
+ $this->log->log("RECV: $part", XMPPHP_Log::LEVEL_VERBOSE);
+ $buff .= $part;
+ } while (!$this->bufferComplete($buff));
+
xml_parse($this->parser, $buff, false);
+ if ($return_when_received) {
+ return true;
+ }
} else {
# $updated == 0 means no changes during timeout.
}
@@ -424,7 +491,7 @@ class XMPPHP_XMLStream {
} while (is_null($maximum) || $remaining > 0);
return true;
}
-
+
/**
* Process
*
@@ -437,8 +504,11 @@ class XMPPHP_XMLStream {
/**
* Process until a timeout occurs
*
- * @param integer $timeout
+ * @param integer $timeout Time in seconds
+ *
* @return string
+ *
+ * @see __process()
*/
public function processTime($timeout=NULL) {
if (is_null($timeout)) {
@@ -451,26 +521,47 @@ class XMPPHP_XMLStream {
/**
* Process until a specified event or a timeout occurs
*
- * @param string|array $event
- * @param integer $timeout
- * @return string
+ * @param string|array $event Event name or array of event names
+ * @param integer $timeout Timeout in seconds
+ *
+ * @return array Payload
*/
- public function processUntil($event, $timeout=null) {
+ public function processUntil($event, $timeout = -1)
+ {
$start = time();
- if(!is_array($event)) $event = array($event);
+ if (!is_array($event)) {
+ $event = array($event);
+ }
+
$this->until[] = $event;
end($this->until);
$event_key = key($this->until);
reset($this->until);
+
$this->until_count[$event_key] = 0;
$updated = '';
- while(!$this->disconnected and $this->until_count[$event_key] < 1 and (time() - $start < $timeout or $timeout == null)) {
- $this->__process($timeout);
+ while (!$this->disconnected
+ && $this->until_count[$event_key] < 1
+ && ($timeout == -1 || time() - $start < $timeout)
+ ) {
+ $maximum = $timeout == -1
+ ? NULL
+ : ($timeout - (time() - $start)) * 1000000;
+ $ret = $this->__process($maximum, true);
+ if (!$ret) {
+ break;
+ }
+ }
+
+ if (array_key_exists($event_key, $this->until_payload)) {
+ $payload = $this->until_payload[$event_key];
+ unset($this->until_payload[$event_key]);
+ unset($this->until_count[$event_key]);
+ unset($this->until[$event_key]);
+ } else {
+ $payload = array();
}
- $payload = array_key_exists($event_key, $this->until_payload)?$this->until_payload[$event_key]:array();
- unset($this->until_payload[$event_key]);
- unset($this->until_count[$event_key]);
- unset($this->until[$event_key]);
+
return $payload;
}
@@ -483,7 +574,7 @@ class XMPPHP_XMLStream {
/**
* XML start callback
- *
+ *
* @see xml_set_element_handler
*
* @param resource $parser
@@ -524,7 +615,7 @@ class XMPPHP_XMLStream {
/**
* XML end callback
- *
+ *
* @see xml_set_element_handler
*
* @param resource $parser
@@ -655,7 +746,7 @@ class XMPPHP_XMLStream {
*/
public function read() {
$buff = @fread($this->socket, 1024);
- if(!$buff) {
+ if(!$buff) {
if($this->reconnect) {
$this->doReconnect();
} else {
@@ -685,13 +776,13 @@ class XMPPHP_XMLStream {
$usecs = $maximum % 1000000;
$secs = floor(($maximum - $usecs) / 1000000);
}
-
+
$read = array();
$write = array($this->socket);
$except = array();
-
+
$select = @stream_select($read, $write, $except, $secs, $usecs);
-
+
if($select === False) {
$this->log->log("ERROR sending message; reconnecting.");
$this->doReconnect();
@@ -703,7 +794,7 @@ class XMPPHP_XMLStream {
$this->log->log("Socket is not ready; break.", XMPPHP_Log::LEVEL_ERROR);
return false;
}
-
+
$sentbytes = @fwrite($this->socket, $msg);
$this->log->log("SENT: " . mb_substr($msg, 0, $sentbytes, '8bit'), XMPPHP_Log::LEVEL_VERBOSE);
if($sentbytes === FALSE) {
diff --git a/lib/jabber/XMPPHP/XMPP.php b/lib/jabber/XMPPHP/XMPP.php
index acbcc49..eed8f69 100644
--- a/lib/jabber/XMPPHP/XMPP.php
+++ b/lib/jabber/XMPPHP/XMPP.php
@@ -3,22 +3,22 @@
* XMPPHP: The PHP XMPP Library
* Copyright (C) 2008 Nathanael C. Fritz
* This file is part of SleekXMPP.
- *
+ *
* XMPPHP is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* XMPPHP is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with XMPPHP; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
- * @category xmpphp
+ * @category xmpphp
* @package XMPPHP
* @author Nathanael C. Fritz <JID: fr...@ne...>
* @author Stephan Wentz <JID: st...@ja...>
@@ -27,13 +27,13 @@
*/
/** XMPPHP_XMLStream */
-require_once dirname(__FILE__) . "/XMLStream.php";
-require_once dirname(__FILE__) . "/Roster.php";
+require_once dirname(__FILE__) . '/XMLStream.php';
+require_once dirname(__FILE__) . '/Roster.php';
/**
* XMPPHP Main Class
- *
- * @category xmpphp
+ *
+ * @category xmpphp
* @package XMPPHP
* @author Nathanael C. Fritz <JID: fr...@ne...>
* @author Stephan Wentz <JID: st...@ja...>
@@ -45,60 +45,75 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
/**
* @var string
*/
- protected $server;
+ public $server;
/**
* @var string
*/
- protected $user;
-
+ public $user;
+
/**
* @var string
*/
protected $password;
-
+
/**
* @var string
*/
protected $resource;
-
+
/**
* @var string
*/
protected $fulljid;
-
+
/**
* @var string
*/
protected $basejid;
-
+
/**
* @var boolean
*/
protected $authed = false;
protected $session_started = false;
-
+
/**
* @var boolean
*/
protected $auto_subscribe = false;
-
+
/**
* @var boolean
*/
protected $use_encryption = true;
-
+
/**
* @var boolean
*/
public $track_presence = true;
-
+
/**
* @var object
*/
public $roster;
/**
+ * @var array supported auth mechanisms
+ */
+ protected $auth_mechanism_supported = array('PLAIN', 'DIGEST-MD5');
+
+ /**
+ * @var string default auth mechanism
+ */
+ protected $auth_mechanism_default = 'PLAIN';
+
+ /**
+ * @var string prefered auth mechanism
+ */
+ protected $auth_mechanism_preferred = 'DIGEST-MD5';
+
+ /**
* Constructor
*
* @param string $host
@@ -112,19 +127,21 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
*/
public function __construct($host, $port, $user, $password, $resource, $server = null, $printlog = false, $loglevel = null) {
parent::__construct($host, $port, $printlog, $loglevel);
-
+
$this->user = $user;
$this->password = $password;
$this->resource = $resource;
if(!$server) $server = $host;
+ $this->server = $server;
$this->basejid = $this->user . '@' . $this->host;
$this->roster = new Roster();
+ $this->track_presence = true;
$this->stream_start = '<stream:stream to="' . $server . '" xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" version="1.0">';
$this->stream_end = '</stream:stream>';
$this->default_ns = 'jabber:client';
-
+
$this->addXPathHandler('{http://etherx.jabber.org/streams}features', 'features_handler');
$this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}success', 'sasl_success_handler');
$this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}failure', 'sasl_failure_handler');
@@ -132,6 +149,8 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
$this->addXPathHandler('{jabber:client}message', 'message_handler');
$this->addXPathHandler('{jabber:client}presence', 'presence_handler');
$this->addXPathHandler('iq/{jabber:iq:roster}query', 'roster_iq_handler');
+ // For DIGEST-MD5 auth :
+ $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}challenge', 'sasl_challenge_handler');
}
/**
@@ -142,7 +161,7 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
public function useEncryption($useEncryption = true) {
$this->use_encryption = $useEncryption;
}
-
+
/**
* Turn on auto-authorization of subscription requests.
*
@@ -153,15 +172,6 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
}
/**
- * Turn on track-presence of subscription requests.
- *
- * @param boolean $trackPresence
- */
- public function trackPresence($trackPresence = true) {
- $this->track_presence = $trackPresence;
- }
-
- /**
* Send XMPP Message
*
* @param string $to
@@ -174,17 +184,17 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
{
$type = 'chat';
}
-
+
$to = htmlspecialchars($to);
$body = htmlspecialchars($body);
$subject = htmlspecialchars($subject);
-
- $out = "<message from='{$this->fulljid}' to='$to' type='$type'>";
+
+ $out = "<message from=\"{$this->fulljid}\" to=\"$to\" type='$type'>";
if($subject) $out .= "<subject>$subject</subject>";
$out .= "<body>$body</body>";
if($payload) $out .= $payload;
$out .= "</message>";
-
+
$this->send($out);
}
@@ -195,16 +205,16 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
* @param string $show
* @param string $to
*/
- public function presence($status = null, $show = 'available', $to = null, $type='available', $priority = null) {
+ public function presence($status = null, $show = 'available', $to = null, $type='available', $priority=null) {
if($type == 'available') $type = '';
$to = htmlspecialchars($to);
$status = htmlspecialchars($status);
if($show == 'unavailable') $type = 'unavailable';
-
+
$out = "<presence";
- if($to) $out .= " to='$to'";
+ if($to) $out .= " to=\"$to\"";
if($type) $out .= " type='$type'";
- if($show == 'available' and !$status) {
+ if($show == 'available' and !$status and $priority !== null) {
$out .= "/>";
} else {
$out .= ">";
@@ -213,7 +223,7 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
if($priority !== null) $out .= "<priority>$priority</priority>";
$out .= "</presence>";
}
-
+
$this->send($out);
}
/**
@@ -227,6 +237,42 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
}
/**
+ * Add user to Roster
+ *
+ * @param string $jid user jid
+ * @param string $name user nickname
+ * @param string $group group to add
+ */
+ public function RosterAddUser($jid, $name=null, $group=null) {
+ $payload = "<item jid='$jid'".($name ? " name='" . htmlspecialchars($name) . "'" : '')."/>\n".
+ ($group?'<group>'.htmlspecialchars($group, ENT_QUOTES, 'UTF-8').'</group>':'');
+ $this->SendIq(NULL, 'set', "jabber:iq:roster", $payload);
+ }
+
+ /**
+ * Send ID action
+ *
+ * @param string $to to jid
+ * @param string $type type of ID
+ * @param string $xmlns xmlns name
+ * @param string $payload payload string
+ * @param string $from from jid
+ */
+ private function sendIq($to = NULL, $type = 'get', $xmlns = NULL, $payload = NULL, $from = NULL)
+ {
+ $id = $this->getID();
+ $xml = "<iq type='$type' id='$id'".
+ ($to ? " to='$to'" : '').
+ ($from ? " from='$from'" : '').
+ ">
+ <query xmlns='$xmlns'>
+ $payload
+ </query>
+ </iq>";
+ return $this->send($xml);
+ }
+
+ /**
* Message handler
*
* @param string $xml
@@ -237,14 +283,11 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
} else {
$payload['type'] = 'chat';
}
+ $body = $xml->sub('body');
$payload['from'] = $xml->attrs['from'];
- if (!$xml->hasSub('body'))
- $payload['body'] = '';
- else
- {
- $payload['body'] = $xml->sub('body')->data;
- $this->log->log('Message: '.$xml->sub('body')->data, XMPPHP_Log::LEVEL_DEBUG);
- }
+ $payload['body'] = is_object($body) ? $body->data : FALSE; // $xml->sub('body')->data;
+ $payload['xml'] = $xml;
+ $this->log->log("Message: {$payload['body']}", XMPPHP_Log::LEVEL_DEBUG);
$this->event('message', $payload);
}
@@ -260,8 +303,9 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
$payload['status'] = (isset($xml->sub('status')->data)) ? $xml->sub('status')->data : '';
$payload['priority'] = (isset($xml->sub('priority')->data)) ? intval($xml->sub('priority')->data) : 0;
$payload['xml'] = $xml;
- if($this->track_presence)
+ if($this->track_presence) {
$this->roster->setPresence($payload['from'], $payload['priority'], $payload['show'], $payload['status']);
+ }
$this->log->log("Presence: {$payload['from']} [{$payload['show']}] {$payload['status']}", XMPPHP_Log::LEVEL_DEBUG);
if(array_key_exists('type', $xml->attrs) and $xml->attrs['type'] == 'subscribe') {
if($this->auto_subscribe) {
@@ -291,10 +335,36 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
} else {
$this->log->log("Attempting Auth...");
if ($this->password) {
- $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>" . base64_encode("\x00" . $this->user . "\x00" . $this->password) . "</auth>");
+ $mechanism = 'PLAIN'; // default;
+ if ($xml->hasSub('mechanisms') && $xml->sub('mechanisms')->hasSub('mechanism')) {
+ // Get the list of all available auth mechanism that we can use
+ $available = array();
+ foreach ($xml->sub('mechanisms')->subs as $sub) {
+ if ($sub->name == 'mechanism') {
+ if (in_array($sub->data, $this->auth_mechanism_supported)) {
+ $available[$sub->data] = $sub->data;
+ }
+ }
+ }
+ if (isset($available[$this->auth_mechanism_preferred])) {
+ $mechanism = $this->auth_mechanism_preferred;
+ } else {
+ // use the first available
+ $mechanism = reset($available);
+ }
+ $this->log->log("Trying $mechanism (available : " . implode(',', $available) . ')');
+ }
+ switch ($mechanism) {
+ case 'PLAIN':
+ $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>" . base64_encode("\x00" . $this->user . "\x00" . $this->password) . "</auth>");
+ break;
+ case 'DIGEST-MD5':
+ $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5' />");
+ break;
+ }
} else {
- $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>");
- }
+ $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>");
+ }
}
}
@@ -308,7 +378,7 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
$this->authed = true;
$this->reset();
}
-
+
/**
* SASL feature handler
*
@@ -317,11 +387,61 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
protected function sasl_failure_handler($xml) {
$this->log->log("Auth failed!", XMPPHP_Log::LEVEL_ERROR);
$this->disconnect();
-
+
throw new XMPPHP_Exception('Auth failed!');
}
/**
+ * Handle challenges for DIGEST-MD5 auth
+ *
+ * @param string $xml
+ */
+ protected function sasl_challenge_handler($xml) {
+ // Decode and parse the challenge string
+ // (may be something like foo="bar",foo2="bar2,bar3,bar4",foo3=bar5 )
+ $challenge = base64_decode($xml->data);
+ $vars = array();
+ $matches = array();
+ preg_match_all('/(\w+)=(?:"([^"]*)|([^,]*))/', $challenge, $matches);
+ $res = array();
+ foreach ($matches[1] as $k => $v) {
+ $vars[$v] = (empty($matches[2][$k])?$matches[3][$k]:$matches[2][$k]);
+ }
+
+ if (isset($vars['nonce'])) {
+ // First step
+ $vars['cnonce'] = uniqid(mt_rand(), false);
+ $vars['nc'] = '00000001';
+ $vars['qop'] = 'auth'; // Force qop to auth
+ if (!isset($vars['digest-uri'])) $vars['digest-uri'] = 'xmpp/' . $this->server;
+ if (!isset($vars['realm'])) $vars['realm'] = '';
+
+ // now, the magic...
+ $a1 = sprintf('%s:%s:%s', $this->user, $vars['realm'], $this->password);
+ if ($vars['algorithm'] == 'md5-sess') {
+ $a1 = pack('H32',md5($a1)) . ':' . $vars['nonce'] . ':' . $vars['cnonce'];
+ }
+ $a2 = "AUTHENTICATE:" . $vars['digest-uri'];
+ $password = md5($a1) . ':' . $vars['nonce'] . ':' . $vars['nc'] . ':' . $vars['cnonce'] . ':' . $vars['qop'] . ':' .md5($a2);
+ $password = md5($password);
+ $response = sprintf('username="%s",realm="%s",nonce="%s",cnonce="%s",nc=%s,qop=%s,digest-uri="%s",response=%s,charset=utf-8',
+ $this->user, $vars['realm'], $vars['nonce'], $vars['cnonce'], $vars['nc'], $vars['qop'], $vars['digest-uri'], $password);
+
+ // Send the response
+ $response = base64_encode($response);
+ $this->send("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>$response</response>");
+ } else {
+ if (isset($vars['rspauth'])) {
+ // Second step
+ $this->send("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>");
+ } else {
+ $this->log->log("ERROR receiving challenge : " . $challenge, XMPPHP_Log::LEVEL_ERROR);
+ }
+
+ }
+ }
+
+ /**
* Resource bind handler
*
* @param string $xml
@@ -339,20 +459,20 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
}
/**
- * Retrieves the roster
- *
- */
+ * Retrieves the roster
+ *
+ */
public function getRoster() {
$id = $this->getID();
$this->send("<iq xmlns='jabber:client' type='get' id='$id'><query xmlns='jabber:iq:roster' /></iq>");
}
/**
- * Roster iq handler
- * Gets all packets matching XPath "iq/{jabber:iq:roster}query'
- *
- * @param string $xml
- */
+ * Roster iq handler
+ * Gets all packets matching XPath "iq/{jabber:iq:roster}query'
+ *
+ * @param string $xml
+ */
protected function roster_iq_handler($xml) {
$status = "result";
$xmlroster = $xml->sub('query');
@@ -405,9 +525,9 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
}
/**
- * Retrieves the vcard
- *
- */
+ * Retrieves the vcard
+ *
+ */
public function getVCard($jid = Null) {
$id = $this->getID();
$this->addIdHandler($id, 'vcard_get_handler');
@@ -419,10 +539,10 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
}
/**
- * VCard retrieval handler
- *
- * @param XML Object $xml
- */
+ * VCard retrieval handler
+ *
+ * @param XML Object $xml
+ */
protected function vcard_get_handler($xml) {
$vcard_array = array();
$vcard = $xml->sub('vcard');
diff --git a/lib/jabber/XMPPHP/XMPPHP_Log.php b/lib/jabber/XMPPHP/XMPPHP_Log.php
deleted file mode 100644
index b1593f5..0000000
--- a/lib/jabber/XMPPHP/XMPPHP_Log.php
+++ /dev/null
@@ -1,119 +0,0 @@
-<?php
-/**
- * XMPPHP: The PHP XMPP Library
- * Copyright (C) 2008 Nathanael C. Fritz
- * This file is part of SleekXMPP.
- *
- * XMPPHP is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * XMPPHP is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XMPPHP; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * @category xmpphp
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fr...@ne...>
- * @author Stephan Wentz <JID: st...@ja...>
- * @author Michael Garvin <JID: ga...@ne...>
- * @copyright 2008 Nathanael C. Fritz
- */
-
-/**
- * XMPPHP Log
- *
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fr...@ne...>
- * @author Stephan Wentz <JID: st...@ja...>
- * @author Michael Garvin <JID: ga...@ne...>
- * @copyright 2008 Nathanael C. Fritz
- * @version $Id$
- */
-class XMPPHP_Log {
-
- const LEVEL_ERROR = 0;
- const LEVEL_WARNING = 1;
- const LEVEL_INFO = 2;
- const LEVEL_DEBUG = 3;
- const LEVEL_VERBOSE = 4;
-
- /**
- * @var array
- */
- protected $data = array();
-
- /**
- * @var array
- */
- protected $names = array('ERROR', 'WARNING', 'INFO', 'DEBUG', 'VERBOSE');
-
- /**
- * @var integer
- */
- protected $runlevel;
-
- /**
- * @var boolean
- */
- protected $printout;
-
- /**
- * Constructor
- *
- * @param boolean $printout
- * @param string $runlevel
- */
- public function __construct($printout = false, $runlevel = self::LEVEL_INFO) {
- $this->printout = (boolean)$printout;
- $this->runlevel = (int)$runlevel;
- }
-
- /**
- * Add a message to the log data array
- * If printout in this instance is set to true, directly output the message
- *
- * @param string $msg
- * @param integer $runlevel
- */
- public function log($msg, $runlevel = self::LEVEL_INFO) {
- $time = time();
- //$this->data[] = array($this->runlevel, $msg, $time);
- if($this->printout and $runlevel <= $this->runlevel) {
- $this->writeLine($msg, $runlevel, $time);
- }
- }
-
- /**
- * Output the complete log.
- * Log will be cleared if $clear = true
- *
- * @param boolean $clear
- * @param integer $runlevel
- */
- public function printout($clear = true, $runlevel = null) {
- if($runlevel === null) {
- $runlevel = $this->runlevel;
- }
- foreach($this->data as $data) {
- if($runlevel <= $data[0]) {
- $this->writeLine($data[1], $runlevel, $data[2]);
- }
- }
- if($clear) {
- $this->data = array();
- }
- }
-
- protected function writeLine($msg, $runlevel, $time) {
- //echo date('Y-m-d H:i:s', $time)." [".$this->names[$runlevel]."]: ".$msg."\n";
- echo $time." [".$this->names[$runlevel]."]: ".$msg."\n";
- flush();
- }
-}
diff --git a/lib/jabber/XMPPHP/XMPP_Old.php b/lib/jabber/XMPPHP/XMPP_Old.php
index 43f56b1..6083dad 100644
--- a/lib/jabber/XMPPHP/XMPP_Old.php
+++ b/lib/jabber/XMPPHP/XMPP_Old.php
@@ -33,7 +33,7 @@
* The old Jabber protocol wasn't standardized, so use at your own risk.
*
*/
-require_once "XMPP.php";
+require_once dirname(__FILE__) . '/XMPP.php';
class XMPPHP_XMPPOld extends XMPPHP_XMPP {
/**
-----------------------------------------------------------------------
Summary of changes:
lib/jabber/XMPPHP/BOSH.php | 2 +-
lib/jabber/XMPPHP/DIGEST-MD5.patch | 132 ------------------
lib/jabber/XMPPHP/Roster.php | 17 ++-
lib/jabber/XMPPHP/XMLStream.php | 199 ++++++++++++++++++++--------
lib/jabber/XMPPHP/XMPP.php | 256 ++++++++++++++++++++++++++----------
lib/jabber/XMPPHP/XMPPHP_Log.php | 119 -----------------
lib/jabber/XMPPHP/XMPP_Old.php | 2 +-
7 files changed, 344 insertions(+), 383 deletions(-)
delete mode 100644 lib/jabber/XMPPHP/DIGEST-MD5.patch
delete mode 100644 lib/jabber/XMPPHP/XMPPHP_Log.php
hooks/post-receive
--
quickfw
|