Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/jabber/XMPP/XMPP.php
Go to the documentation of this file.
00001 <?php
00030 require_once dirname(__FILE__) . "/XMLStream.php";
00031 require_once dirname(__FILE__) . "/Roster.php";
00032 
00044 class XMPPHP_XMPP extends XMPPHP_XMLStream {
00048         public $server;
00049 
00053         public $user;
00054         
00058         protected $password;
00059         
00063         protected $resource;
00064         
00068         protected $fulljid;
00069         
00073         protected $basejid;
00074         
00078         protected $authed = false;
00079         protected $session_started = false;
00080         
00084         protected $auto_subscribe = false;
00085         
00089         protected $use_encryption = true;
00090         
00094         public $track_presence = true;
00095         
00099         public $roster;
00100 
00113         public function __construct($host, $port, $user, $password, $resource, $server = null, $printlog = false, $loglevel = null) {
00114                 parent::__construct($host, $port, $printlog, $loglevel);
00115                 
00116                 $this->user      = $user;
00117                 $this->password = $password;
00118                 $this->resource = $resource;
00119                 if(!$server) $server = $host;
00120                 $this->basejid = $this->user . '@' . $this->host;
00121 
00122                 $this->roster = new Roster();
00123                 $this->track_presence = true;
00124 
00125                 $this->stream_start = '<stream:stream to="' . $server . '" xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" version="1.0">';
00126                 $this->stream_end   = '</stream:stream>';
00127                 $this->default_ns   = 'jabber:client';
00128                 
00129                 $this->addXPathHandler('{http://etherx.jabber.org/streams}features', 'features_handler');
00130                 $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}success', 'sasl_success_handler');
00131                 $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}failure', 'sasl_failure_handler');
00132                 $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-tls}proceed', 'tls_proceed_handler');
00133                 $this->addXPathHandler('{jabber:client}message', 'message_handler');
00134                 $this->addXPathHandler('{jabber:client}presence', 'presence_handler');
00135                 $this->addXPathHandler('iq/{jabber:iq:roster}query', 'roster_iq_handler');
00136         }
00137 
00143         public function useEncryption($useEncryption = true) {
00144                 $this->use_encryption = $useEncryption;
00145         }
00146         
00152         public function autoSubscribe($autoSubscribe = true) {
00153                 $this->auto_subscribe = $autoSubscribe;
00154         }
00155 
00164         public function message($to, $body, $type = 'chat', $subject = null, $payload = null) {
00165             if(is_null($type))
00166             {
00167                 $type = 'chat';
00168             }
00169             
00170                 $to       = htmlspecialchars($to);
00171                 $body   = htmlspecialchars($body);
00172                 $subject = htmlspecialchars($subject);
00173                 
00174                 $out = "<message from=\"{$this->fulljid}\" to=\"$to\" type='$type'>";
00175                 if($subject) $out .= "<subject>$subject</subject>";
00176                 $out .= "<body>$body</body>";
00177                 if($payload) $out .= $payload;
00178                 $out .= "</message>";
00179                 
00180                 $this->send($out);
00181         }
00182 
00190         public function presence($status = null, $show = 'available', $to = null, $type='available', $priority=0) {
00191                 if($type == 'available') $type = '';
00192                 $to      = htmlspecialchars($to);
00193                 $status = htmlspecialchars($status);
00194                 if($show == 'unavailable') $type = 'unavailable';
00195                 
00196                 $out = "<presence";
00197                 if($to) $out .= " to=\"$to\"";
00198                 if($type) $out .= " type='$type'";
00199                 if($show == 'available' and !$status) {
00200                         $out .= "/>";
00201                 } else {
00202                         $out .= ">";
00203                         if($show != 'available') $out .= "<show>$show</show>";
00204                         if($status) $out .= "<status>$status</status>";
00205                         if($priority) $out .= "<priority>$priority</priority>";
00206                         $out .= "</presence>";
00207                 }
00208                 
00209                 $this->send($out);
00210         }
00216         public function subscribe($jid) {
00217                 $this->send("<presence type='subscribe' to='{$jid}' from='{$this->fulljid}' />");
00218                 #$this->send("<presence type='subscribed' to='{$jid}' from='{$this->fulljid}' />");
00219         }
00220 
00226         public function message_handler($xml) {
00227                 if(isset($xml->attrs['type'])) {
00228                         $payload['type'] = $xml->attrs['type'];
00229                 } else {
00230                         $payload['type'] = 'chat';
00231                 }
00232                 $payload['from'] = $xml->attrs['from'];
00233                 $payload['body'] = $xml->sub('body')->data;
00234                 $payload['xml'] = $xml;
00235                 $this->log->log("Message: {$xml->sub('body')->data}", XMPPHP_Log::LEVEL_DEBUG);
00236                 $this->event('message', $payload);
00237         }
00238 
00244         public function presence_handler($xml) {
00245                 $payload['type'] = (isset($xml->attrs['type'])) ? $xml->attrs['type'] : 'available';
00246                 $payload['show'] = (isset($xml->sub('show')->data)) ? $xml->sub('show')->data : $payload['type'];
00247                 $payload['from'] = $xml->attrs['from'];
00248                 $payload['status'] = (isset($xml->sub('status')->data)) ? $xml->sub('status')->data : '';
00249                 $payload['priority'] = (isset($xml->sub('priority')->data)) ? intval($xml->sub('priority')->data) : 0;
00250                 $payload['xml'] = $xml;
00251                 if($this->track_presence) {
00252                         $this->roster->setPresence($payload['from'], $payload['priority'], $payload['show'], $payload['status']);
00253                 }
00254                 $this->log->log("Presence: {$payload['from']} [{$payload['show']}] {$payload['status']}",  XMPPHP_Log::LEVEL_DEBUG);
00255                 if(array_key_exists('type', $xml->attrs) and $xml->attrs['type'] == 'subscribe') {
00256                         if($this->auto_subscribe) {
00257                                 $this->send("<presence type='subscribed' to='{$xml->attrs['from']}' from='{$this->fulljid}' />");
00258                                 $this->send("<presence type='subscribe' to='{$xml->attrs['from']}' from='{$this->fulljid}' />");
00259                         }
00260                         $this->event('subscription_requested', $payload);
00261                 } elseif(array_key_exists('type', $xml->attrs) and $xml->attrs['type'] == 'subscribed') {
00262                         $this->event('subscription_accepted', $payload);
00263                 } else {
00264                         $this->event('presence', $payload);
00265                 }
00266         }
00267 
00273         protected function features_handler($xml) {
00274                 if($xml->hasSub('starttls') and $this->use_encryption) {
00275                         $this->send("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required /></starttls>");
00276                 } elseif($xml->hasSub('bind') and $this->authed) {
00277                         $id = $this->getId();
00278                         $this->addIdHandler($id, 'resource_bind_handler');
00279                         $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>");
00280                 } else {
00281                         $this->log->log("Attempting Auth...");
00282                         if ($this->password) {
00283                         $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>" . base64_encode("\x00" . $this->user . "\x00" . $this->password) . "</auth>");
00284                         } else {
00285                         $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>");
00286                         }       
00287                 }
00288         }
00289 
00295         protected function sasl_success_handler($xml) {
00296                 $this->log->log("Auth success!");
00297                 $this->authed = true;
00298                 $this->reset();
00299         }
00300         
00306         protected function sasl_failure_handler($xml) {
00307                 $this->log->log("Auth failed!",  XMPPHP_Log::LEVEL_ERROR);
00308                 $this->disconnect();
00309                 
00310                 throw new XMPPHP_Exception('Auth failed!');
00311         }
00312 
00318         protected function resource_bind_handler($xml) {
00319                 if($xml->attrs['type'] == 'result') {
00320                         $this->log->log("Bound to " . $xml->sub('bind')->sub('jid')->data);
00321                         $this->fulljid = $xml->sub('bind')->sub('jid')->data;
00322                         $jidarray = explode('/',$this->fulljid);
00323                         $this->jid = $jidarray[0];
00324                 }
00325                 $id = $this->getId();
00326                 $this->addIdHandler($id, 'session_start_handler');
00327                 $this->send("<iq xmlns='jabber:client' type='set' id='$id'><session xmlns='urn:ietf:params:xml:ns:xmpp-session' /></iq>");
00328         }
00329 
00334         public function getRoster() {
00335                 $id = $this->getID();
00336                 $this->send("<iq xmlns='jabber:client' type='get' id='$id'><query xmlns='jabber:iq:roster' /></iq>");
00337         }
00338 
00345         protected function roster_iq_handler($xml) {
00346                 $status = "result";
00347                 $xmlroster = $xml->sub('query');
00348                 foreach($xmlroster->subs as $item) {
00349                         $groups = array();
00350                         if ($item->name == 'item') {
00351                                 $jid = $item->attrs['jid']; //REQUIRED
00352                                 $name = $item->attrs['name']; //MAY
00353                                 $subscription = $item->attrs['subscription'];
00354                                 foreach($item->subs as $subitem) {
00355                                         if ($subitem->name == 'group') {
00356                                                 $groups[] = $subitem->data;
00357                                         }
00358                                 }
00359                                 $contacts[] = array($jid, $subscription, $name, $groups); //Store for action if no errors happen
00360                         } else {
00361                                 $status = "error";
00362                         }
00363                 }
00364                 if ($status == "result") { //No errors, add contacts
00365                         foreach($contacts as $contact) {
00366                                 $this->roster->addContact($contact[0], $contact[1], $contact[2], $contact[3]);
00367                         }
00368                 }
00369                 if ($xml->attrs['type'] == 'set') {
00370                         $this->send("<iq type=\"reply\" id=\"{$xml->attrs['id']}\" to=\"{$xml->attrs['from']}\" />");
00371                 }
00372         }
00373 
00379         protected function session_start_handler($xml) {
00380                 $this->log->log("Session started");
00381                 $this->session_started = true;
00382                 $this->event('session_start');
00383         }
00384 
00390         protected function tls_proceed_handler($xml) {
00391                 $this->log->log("Starting TLS encryption");
00392                 stream_socket_enable_crypto($this->socket, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT);
00393                 $this->reset();
00394         }
00395 
00400         public function getVCard($jid = Null) {
00401                 $id = $this->getID();
00402                 $this->addIdHandler($id, 'vcard_get_handler');
00403                 if($jid) {
00404                         $this->send("<iq type='get' id='$id' to='$jid'><vCard xmlns='vcard-temp' /></iq>");
00405                 } else {
00406                         $this->send("<iq type='get' id='$id'><vCard xmlns='vcard-temp' /></iq>");
00407                 }
00408         }
00409 
00415         protected function vcard_get_handler($xml) {
00416                 $vcard_array = array();
00417                 $vcard = $xml->sub('vcard');
00418                 // go through all of the sub elements and add them to the vcard array
00419                 foreach ($vcard->subs as $sub) {
00420                         if ($sub->subs) {
00421                                 $vcard_array[$sub->name] = array();
00422                                 foreach ($sub->subs as $sub_child) {
00423                                         $vcard_array[$sub->name][$sub_child->name] = $sub_child->data;
00424                                 }
00425                         } else {
00426                                 $vcard_array[$sub->name] = $sub->data;
00427                         }
00428                 }
00429                 $vcard_array['from'] = $xml->attrs['from'];
00430                 $this->event('vcard', $vcard_array);
00431         }
00432 }
 All Data Structures Namespaces Files Functions Variables Enumerations