* @revision 05 * @license http://creativecommons.org/licenses/by-sa/3.0/de/ Creative Commons Attribution-Share Alike 3.0 Germany * @homepage http://oss.tiggerswelt.net/xmpp * @copyright Copyright © 2009 tiggersWelt.net */ require_once ('tiggerXMPP/extension.php'); /** * Service Discovery Implementation (XEP-0030) * * @package tiggerXMPP * @class XEP_0030 * @todo Support starting disco, not just responding * @todo Support for nodes * @todo Add Support for disco#publish */ class tiggerXMPP_XEP_0030 extends tiggerXMPP_Extension { /* Our namespaces */ const NAMESPACE_INFO = 'http://jabber.org/protocol/disco#info'; const NAMESPACE_ITEM = 'http://jabber.org/protocol/disco#items'; /* Local identities */ private $Identities = array (); private $IdentityFunc = null; /* Local items */ private $Items = array (); private $ItemFunc = null; // {{{ getNamespaces /** * Retrive a list of the namespaces we handle * * @access public * @return array **/ public function getNamespaces () { return array ( self::NAMESPACE_INFO, self::NAMESPACE_ITEM, ); } // }}} // {{{ getTags /** * Retrive a list of all tags we handle for a given namespace * * @param string $Namespace * * @access public * @return array **/ public function getTags ($NS = '') { switch ($NS) { case self::NAMESPACE_INFO: return array ('query', 'identity', 'feature'); case self::NAMESPACE_ITEM: return array ('query', 'item'); } return parent::getTags ($NS); } // }}} // {{{ handle /** * Handle an incoming packet for us * * @param object $Tag Incoming packet data * * @access public * @return object */ public function handle ($Tag) { // We only handle requests at the moment if (!is_object ($p = $Tag->getParent ()) || ($p->getAttribute ('type') != 'get')) return; // Handle Disco-Info-Requests if (($Tag->getName () == 'query') && ($Tag->getNamespace () == self::NAMESPACE_INFO)) { $this->__debug (tiggerXMPP_Stream::DEBUG_DEBUG, 'Answering Disco-Info', __FUNCTION__, __LINE__, __CLASS__, __FILE__); $Identities = $this->getIdentities ($p->to, $p->from, $Tag->getAttribute ('node')); $Response = new phpEvents_Socket_Stream_XML_Tag ('query'); $Response->setNamespace (self::NAMESPACE_INFO); if (count ($Identities) < 1) { $this->__debug (tiggerXMPP_Stream::DEBUG_NOTICE, 'No identities found', __FUNCTION__, __LINE__, __CLASS__, __FILE__); return array ( $Response, new tiggerXMPP_Error (tiggerXMPP_Error::ERROR_ITEM_NOT_FOUND), ); } // Advertise our identities $Features = array (); foreach ($Identities as $Identity) { $Identity->xmlObject ($Response); if (is_array ($F = $Identity->getFeatures ()) && (count ($F) > 0)) $Features = array_merge ($Features, $F); } // Append features foreach ($Features as $Feature) if (is_object ($Feature)) { if ($Feature instanceof phpEvents_Socket_Stream_XML_Tag) $Feature->setParent ($Response); else trigger_error ('Discarding wrong object-feature'); } else { $st = new phpEvents_Socket_Stream_XML_Tag ('feature', $Response); $st->setAttribute ('var', $Feature); } return $Response; } // Handle Disco-Items if (($Tag->getName () == 'query') && ($Tag->getNamespace () == self::NAMESPACE_ITEM)) { $this->__debug (tiggerXMPP_Stream::DEBUG_DEBUG, 'Answering Disco-Item', __FUNCTION__, __LINE__, __CLASS__, __FILE__); $Response = new phpEvents_Socket_Stream_XML_Tag ('query'); $Response->setNamespace (self::NAMESPACE_ITEM); $Items = $this->getItems ($p->to, $p->from, $Tag->getAttribute ('node')); foreach ($Items as $Item) $Item->xmlObject ($Response); return $Response; } } // }}} // {{{ registerIdentityFunction /** * **/ public function registerIdentityFunction ($Function) { $this->IdentityFunc = $Function; } // }}} // {{{ registerIdentity /** * Register an identity for this client/server/component/whatever * * @param string $Name Name of identity * @param string $Category Category of identity * @param string $Type Type of identity * @param string $Parent (optional) Just show this identity below this parent * * @access public * @return void */ public function registerIdentity ($Name, $Category, $Type, $Parent = '') { $this->Identities [$Name . $Parent] = new tiggerXMPP_XEP_0030_Identity ($Name, $Category, $Type, $Parent, (is_object ($P = $this->getParent ()) ? $P->getNamespaces (true, false) : array ())); } // }}} // {{{ registerItemFunction /** * Register a callback where to get the items from * * @param callback $Function * * @access public * @return void **/ public function registerItemFunction ($Function) { $this->ItemFunc = $Function; } // }}} // {{{ registerItem /** * Register a subitem * * @param string $JID Jabber-ID of subitem * @param string $Name (optional) Description of subitem * @param string $Node (optional) Node of subitem * @param string $Parent (optional) Parent item * * @access public * @return void */ public function registerItem ($JID, $Name = '', $Node = null, $Parent = '') { $this->Items [$JID . $Parent . $Node] = new tiggerXMPP_XEP_0030_Item ($JID, $Name, $Node, $Parent); } // }}} // {{{ getIdentities /** * Retrive a list of identities matching a given JID * * @param string $JID * @param string $For * @param string $Node (optional) * * @access public * @return array */ public function getIdentities ($JID, $For, $Node = null) { $Identities = array (); foreach ($this->Identities as $Identity) if (($Identity->Parent == '') || ($Identity->Parent == $JID)) $Identities [] = $Identity; if (($this->IdentityFunc !== null) && is_callable ($this->IdentityFunc) && is_array ($cIdentities = call_user_func ($this->IdentityFunc, $JID, $For, $Node))) $Identities = array_merge ($Identities, $cIdentities); return $Identities; } // }}} // {{{ getItems /** * Retrive a list of items matching a given JID * * @param string $JID * @param string $For * @param string $Node (optional) * * @access public * @return array */ public function getItems ($JID, $For, $Node = null) { $Items = array (); foreach ($this->Items as $Item) if ((($Item->Parent == '') || ($Item->Parent == $JID)) && ($Item->Node == $Node)) $Items [] = $Item; if (($this->ItemFunc !== null) && is_callable ($this->ItemFunc) && is_array ($cItems = call_user_func ($this->ItemFunc, $JID, $For, $Node))) $Items = array_merge ($Items, $cItems); return $Items; } // }}} } /** * Object to carry XEP-0030 Identities * * @package tiggerXMPP * @class XEP_0030_Identity */ class tiggerXMPP_XEP_0030_Identity { public $Name = ''; public $Category = ''; public $Type = ''; public $Parent = ''; private $Features = array (); // {{{ __construct /** * Create a new class * * @param string $Name * @param string $Category * @param string $Type * @param string $Parent (optional) * * @access public * @return void */ public function __construct ($Name, $Category, $Type, $Parent = '', $Features = array ()) { $this->Name = $Name; $this->Category = $Category; $this->Type = $Type; $this->Parent = $Parent; $this->Features = $Features; } // }}} // {{{ xmlObject /** * Generate an XML-Object * * @param object $Parent * * @access public * @return object */ public function xmlObject ($Parent) { $Tag = new phpEvents_Socket_Stream_XML_Tag ('identity', $Parent); $Tag->setAttribute ('name', $this->Name); $Tag->setAttribute ('type', $this->Type); $Tag->setAttribute ('category', $this->Category); return $Tag; } // }}} // {{{ getFeatures /** * Retrive features of this identity * * @access public * @return array **/ public function getFeatures () { return $this->Features; } // }}} } /** * Object to carry XEP-0030 Items * * @package tiggerXML * @class XEP_0030_Item */ class tiggerXMPP_XEP_0030_Item { public $JID = ''; public $Name = ''; public $Node = null; public $Parent = ''; // {{{ __construct /** * Fill this object with values * * @param string $JID * @param string $Name * @param string $Node (optional) * @param string $Parent (optional) * * @access public * @return void */ public function __construct ($JID, $Name, $Node = null, $Parent = '') { $this->JID = $JID; $this->Name = $Name; $this->Node = $Node; $this->Parent = $Parent; } // }}} // {{{ xmlObject /** * Generate an XML-Object * * @param object $Parent * * @access public * @return object */ public function xmlObject ($Parent) { $Tag = new phpEvents_Socket_Stream_XML_Tag ('item', $Parent); $Tag->setAttribute ('name', $this->Name); $Tag->setAttribute ('jid', $this->JID); if ($this->Node !== null) $Tag->setAttribute ('node', $this->Node); return $Tag; } // }}} } ?>