Allow XMLStream handlers to accept all proper callables
Additionally, change the type of XMLStream::getId() to string as ids in XMPP can take all shapes and sizes. To override the compatible behaviour and pass a simple procedure as a callable either use an anonymous function or pass "false" as $obj.
This commit is contained in:
parent
eb648db476
commit
7cbdc99d08
@ -374,13 +374,10 @@ class XMLStream
|
|||||||
*/
|
*/
|
||||||
public function event(string $name, ?array $payload = null): void
|
public function event(string $name, ?array $payload = null): void
|
||||||
{
|
{
|
||||||
$this->log->log("EVENT: $name", Log::LEVEL_DEBUG);
|
$this->log->log("EVENT: {$name}", Log::LEVEL_DEBUG);
|
||||||
foreach ($this->eventhandlers as $handler) {
|
foreach ($this->eventhandlers as $handler) {
|
||||||
if ($name == $handler[0]) {
|
if ($handler[0] === $name) {
|
||||||
if ($handler[2] === null) {
|
call_user_func_array($handler[1], [&$payload]);
|
||||||
$handler[2] = $this;
|
|
||||||
}
|
|
||||||
$handler[2]->{$handler[1]}($payload);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ($this->until as $key => $until) {
|
foreach ($this->until as $key => $until) {
|
||||||
@ -505,12 +502,12 @@ class XMLStream
|
|||||||
/**
|
/**
|
||||||
* Get next ID
|
* Get next ID
|
||||||
*
|
*
|
||||||
* @return int
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getId(): int
|
public function getId(): string
|
||||||
{
|
{
|
||||||
$this->lastid++;
|
++$this->lastid;
|
||||||
return $this->lastid;
|
return (string) $this->lastid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -522,16 +519,45 @@ class XMLStream
|
|||||||
$this->use_ssl = $use;
|
$this->use_ssl = $use;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compose a proper callable if given legacy syntax
|
||||||
|
*
|
||||||
|
* @param callable|string $pointer
|
||||||
|
* @param object|null|bool $obj
|
||||||
|
* @return callable
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
|
protected function ensureHandler($pointer, $obj = false): callable
|
||||||
|
{
|
||||||
|
$handler = $pointer;
|
||||||
|
|
||||||
|
if (is_string($pointer)) {
|
||||||
|
if (is_object($obj)) {
|
||||||
|
$handler = [$obj, $pointer];
|
||||||
|
} elseif (is_null($obj)) {
|
||||||
|
// Questionable behaviour for backwards compatibility
|
||||||
|
$handler = [$this, $pointer];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_callable($handler)) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
'Cannot compose a proper callable'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $handler;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add ID Handler
|
* Add ID Handler
|
||||||
*
|
*
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @param string $pointer
|
* @param callable|string $pointer
|
||||||
* @param string|null $obj
|
* @param object|bool|null $obj
|
||||||
*/
|
*/
|
||||||
public function addIdHandler(int $id, string $pointer, ?string $obj = null): void
|
public function addIdHandler(string $id, $pointer, $obj = null): void
|
||||||
{
|
{
|
||||||
$this->idhandlers[$id] = [$pointer, $obj];
|
$this->idhandlers[$id] = [$this->ensureHandler($pointer, $obj)];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -540,23 +566,23 @@ class XMLStream
|
|||||||
* @param string $name
|
* @param string $name
|
||||||
* @param string $ns
|
* @param string $ns
|
||||||
* @param string $pointer
|
* @param string $pointer
|
||||||
* @param string|null $obj
|
* @param object|bool|null $obj
|
||||||
* @param int $depth
|
* @param int $depth
|
||||||
*
|
*
|
||||||
* public function addHandler(string $name, string $ns, string $pointer, ?string $obj = null, int $depth = 1): void
|
* public function addHandler(string $name, string $ns, $pointer, $obj = null, int $depth = 1): void
|
||||||
* {
|
* {
|
||||||
* #TODO deprication warning
|
* // TODO deprecation warning
|
||||||
* $this->nshandlers[] = [$name, $ns, $pointer, $obj, $depth];
|
* $this->nshandlers[] = [$name, $ns, $this->ensureHandler($pointer, $obj), $depth];
|
||||||
* }*/
|
* }*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add XPath Handler
|
* Add XPath Handler
|
||||||
*
|
*
|
||||||
* @param string $xpath
|
* @param string $xpath
|
||||||
* @param string $pointer
|
* @param callable|string $pointer
|
||||||
* @param string|null $obj
|
* @param object|bool|null $obj
|
||||||
*/
|
*/
|
||||||
public function addXPathHandler(string $xpath, string $pointer, ?string $obj = null): void
|
public function addXPathHandler(string $xpath, $pointer, $obj = null): void
|
||||||
{
|
{
|
||||||
if (preg_match_all('/\/?(\{[^\}]+\})?[^\/]+/', $xpath, $regs)) {
|
if (preg_match_all('/\/?(\{[^\}]+\})?[^\/]+/', $xpath, $regs)) {
|
||||||
$tag = $regs[0];
|
$tag = $regs[0];
|
||||||
@ -569,19 +595,20 @@ class XMLStream
|
|||||||
preg_match('/(\{([^\}]+)\})?(.*)/', $t, $regs);
|
preg_match('/(\{([^\}]+)\})?(.*)/', $t, $regs);
|
||||||
$xpath_array[] = [$regs[2], $regs[3]];
|
$xpath_array[] = [$regs[2], $regs[3]];
|
||||||
}
|
}
|
||||||
$this->xpathhandlers[] = [$xpath_array, $pointer, $obj];
|
|
||||||
|
$this->xpathhandlers[] = [$xpath_array, $this->ensureHandler($pointer, $obj)];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add Event Handler
|
* Add Event Handler
|
||||||
*
|
*
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @param string $pointer
|
* @param callable|string $pointer
|
||||||
* @param object $obj
|
* @param object|bool|null $obj
|
||||||
*/
|
*/
|
||||||
public function addEventHandler(string $name, string $pointer, object $obj)
|
public function addEventHandler(string $name, $pointer, $obj = null): void
|
||||||
{
|
{
|
||||||
$this->eventhandlers[] = [$name, $pointer, $obj];
|
$this->eventhandlers[] = [$name, $this->ensureHandler($pointer, $obj)];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -715,12 +742,8 @@ class XMLStream
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($searchxml !== null) {
|
if (!is_null($searchxml)) {
|
||||||
if ($handler[2] === null) {
|
call_user_func_array($handler[1], [&$this->xmlobj[2]]);
|
||||||
$handler[2] = $this;
|
|
||||||
}
|
|
||||||
$this->log->log("Calling {$handler[1]}", Log::LEVEL_DEBUG);
|
|
||||||
$handler[2]->{$handler[1]}($this->xmlobj[2]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -731,21 +754,25 @@ class XMLStream
|
|||||||
} elseif (is_array($this->xmlobj) and array_key_exists(2, $this->xmlobj)) {
|
} elseif (is_array($this->xmlobj) and array_key_exists(2, $this->xmlobj)) {
|
||||||
$searchxml = $this->xmlobj[2];
|
$searchxml = $this->xmlobj[2];
|
||||||
}
|
}
|
||||||
if ($searchxml !== null and $searchxml->name == $handler[0] and ($searchxml->ns == $handler[1] or (!$handler[1] and $searchxml->ns == $this->default_ns))) {
|
if (
|
||||||
if ($handler[3] === null) {
|
!is_null($searchxml)
|
||||||
$handler[3] = $this;
|
&& $searchxml->name === $handler[0]
|
||||||
}
|
&& (
|
||||||
$this->log->log("Calling {$handler[2]}", Log::LEVEL_DEBUG);
|
(!$handler[1] && $searchxml->ns === $this->default_ns)
|
||||||
$handler[3]->{$handler[2]}($this->xmlobj[2]);
|
|| $searchxml->ns === $handler[1]
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
call_user_func_array($handler[2], [&$this->xmlobj[2]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ($this->idhandlers as $id => $handler) {
|
foreach ($this->idhandlers as $id => $handler) {
|
||||||
if (array_key_exists('id', $this->xmlobj[2]->attrs) and $this->xmlobj[2]->attrs['id'] == $id) {
|
if (
|
||||||
if ($handler[1] === null) {
|
array_key_exists(2, $this->xmlobj)
|
||||||
$handler[1] = $this;
|
&& array_key_exists('id', $this->xmlobj[2]->attrs)
|
||||||
}
|
&& $this->xmlobj[2]->attrs['id'] === (string) $id
|
||||||
$handler[1]->{$handler[0]}($this->xmlobj[2]);
|
) {
|
||||||
#id handlers are only used once
|
call_user_func_array($handler[0], [&$this->xmlobj[2]]);
|
||||||
|
// id handlers are only used once
|
||||||
unset($this->idhandlers[$id]);
|
unset($this->idhandlers[$id]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -135,13 +135,34 @@ class XMPP extends XMLStream
|
|||||||
$this->stream_end = '</stream:stream>';
|
$this->stream_end = '</stream:stream>';
|
||||||
$this->default_ns = 'jabber:client';
|
$this->default_ns = 'jabber:client';
|
||||||
|
|
||||||
$this->addXPathHandler('{http://etherx.jabber.org/streams}features', 'features_handler');
|
$this->addXPathHandler(
|
||||||
$this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}success', 'sasl_success_handler');
|
'{http://etherx.jabber.org/streams}features',
|
||||||
$this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}failure', 'sasl_failure_handler');
|
[$this, 'features_handler']
|
||||||
$this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-tls}proceed', 'tls_proceed_handler');
|
);
|
||||||
$this->addXPathHandler('{jabber:client}message', 'message_handler');
|
$this->addXPathHandler(
|
||||||
$this->addXPathHandler('{jabber:client}presence', 'presence_handler');
|
'{urn:ietf:params:xml:ns:xmpp-sasl}success',
|
||||||
$this->addXPathHandler('iq/{jabber:iq:roster}query', 'roster_iq_handler');
|
[$this, 'sasl_success_handler']
|
||||||
|
);
|
||||||
|
$this->addXPathHandler(
|
||||||
|
'{urn:ietf:params:xml:ns:xmpp-sasl}failure',
|
||||||
|
[$this, 'sasl_failure_handler']
|
||||||
|
);
|
||||||
|
$this->addXPathHandler(
|
||||||
|
'{urn:ietf:params:xml:ns:xmpp-tls}proceed',
|
||||||
|
[$this, 'tls_proceed_handler']
|
||||||
|
);
|
||||||
|
$this->addXPathHandler(
|
||||||
|
'{jabber:client}message',
|
||||||
|
[$this, 'message_handler']
|
||||||
|
);
|
||||||
|
$this->addXPathHandler(
|
||||||
|
'{jabber:client}presence',
|
||||||
|
[$this, 'presence_handler']
|
||||||
|
);
|
||||||
|
$this->addXPathHandler(
|
||||||
|
'iq/{jabber:iq:roster}query',
|
||||||
|
[$this, 'roster_iq_handler']
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -326,8 +347,8 @@ class XMPP extends XMLStream
|
|||||||
*/
|
*/
|
||||||
public function getVCard(?string $jid = null): void
|
public function getVCard(?string $jid = null): void
|
||||||
{
|
{
|
||||||
$id = $this->getID();
|
$id = $this->getId();
|
||||||
$this->addIdHandler($id, 'vcard_get_handler');
|
$this->addIdHandler($id, [$this, 'vcard_get_handler']);
|
||||||
if ($jid) {
|
if ($jid) {
|
||||||
$this->send("<iq type='get' id='$id' to='$jid'><vCard xmlns='vcard-temp' /></iq>");
|
$this->send("<iq type='get' id='$id' to='$jid'><vCard xmlns='vcard-temp' /></iq>");
|
||||||
} else {
|
} else {
|
||||||
@ -347,7 +368,7 @@ class XMPP extends XMLStream
|
|||||||
$this->send("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required /></starttls>");
|
$this->send("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required /></starttls>");
|
||||||
} elseif ($xml->hasSub('bind') and $this->authed) {
|
} elseif ($xml->hasSub('bind') and $this->authed) {
|
||||||
$id = $this->getId();
|
$id = $this->getId();
|
||||||
$this->addIdHandler($id, 'resource_bind_handler');
|
$this->addIdHandler($id, [$this, 'resource_bind_handler']);
|
||||||
$this->send("<iq xmlns=\"jabber:client\" type=\"set\" id=\"$id\"><bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"><resource>{$this->resource}</resource></bind></iq>");
|
$this->send("<iq xmlns=\"jabber:client\" type=\"set\" id=\"$id\"><bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"><resource>{$this->resource}</resource></bind></iq>");
|
||||||
} else {
|
} else {
|
||||||
$this->log->log("Attempting Auth...");
|
$this->log->log("Attempting Auth...");
|
||||||
@ -401,7 +422,7 @@ class XMPP extends XMLStream
|
|||||||
$this->jid = $jidarray[0];
|
$this->jid = $jidarray[0];
|
||||||
}
|
}
|
||||||
$id = $this->getId();
|
$id = $this->getId();
|
||||||
$this->addIdHandler($id, 'session_start_handler');
|
$this->addIdHandler($id, [$this, 'session_start_handler']);
|
||||||
$this->send("<iq xmlns='jabber:client' type='set' id='$id'><session xmlns='urn:ietf:params:xml:ns:xmpp-session' /></iq>");
|
$this->send("<iq xmlns='jabber:client' type='set' id='$id'><session xmlns='urn:ietf:params:xml:ns:xmpp-session' /></iq>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user