[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/jabber/XMPP/ -> XMPP.php (source)

   1  <?php
   2  /**
   3   * XMPPHP: The PHP XMPP Library
   4   * Copyright (C) 2008  Nathanael C. Fritz
   5   * This file is part of SleekXMPP.
   6   * 
   7   * XMPPHP is free software; you can redistribute it and/or modify
   8   * it under the terms of the GNU General Public License as published by
   9   * the Free Software Foundation; either version 2 of the License, or
  10   * (at your option) any later version.
  11   * 
  12   * XMPPHP is distributed in the hope that it will be useful,
  13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15   * GNU General Public License for more details.
  16   * 
  17   * You should have received a copy of the GNU General Public License
  18   * along with XMPPHP; if not, write to the Free Software
  19   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  20   *
  21   * @category   xmpphp 
  22   * @package    XMPPHP
  23   * @author     Nathanael C. Fritz <JID: fritzy@netflint.net>
  24   * @author     Stephan Wentz <JID: stephan@jabber.wentz.it>
  25   * @author     Michael Garvin <JID: gar@netflint.net>
  26   * @copyright  2008 Nathanael C. Fritz
  27   */
  28  
  29  /** XMPPHP_XMLStream */
  30  require_once dirname(__FILE__) . "/XMLStream.php";
  31  require_once dirname(__FILE__) . "/Roster.php";
  32  
  33  /**
  34   * XMPPHP Main Class
  35   * 
  36   * @category   xmpphp 
  37   * @package    XMPPHP
  38   * @author     Nathanael C. Fritz <JID: fritzy@netflint.net>
  39   * @author     Stephan Wentz <JID: stephan@jabber.wentz.it>
  40   * @author     Michael Garvin <JID: gar@netflint.net>
  41   * @copyright  2008 Nathanael C. Fritz
  42   * @version    $Id$
  43   */
  44  class XMPPHP_XMPP extends XMPPHP_XMLStream {
  45      /**
  46       * @var string
  47       */
  48      public $server;
  49  
  50      /**
  51       * @var string
  52       */
  53      public $user;
  54      
  55      /**
  56       * @var string
  57       */
  58      protected $password;
  59      
  60      /**
  61       * @var string
  62       */
  63      protected $resource;
  64      
  65      /**
  66       * @var string
  67       */
  68      protected $fulljid;
  69      
  70      /**
  71       * @var string
  72       */
  73      protected $basejid;
  74      
  75      /**
  76       * @var boolean
  77       */
  78      protected $authed = false;
  79      protected $session_started = false;
  80      
  81      /**
  82       * @var boolean
  83       */
  84      protected $auto_subscribe = false;
  85      
  86      /**
  87       * @var boolean
  88       */
  89      protected $use_encryption = true;
  90      
  91      /**
  92       * @var boolean
  93       */
  94      public $track_presence = true;
  95      
  96      /**
  97       * @var object
  98       */
  99      public $roster;
 100  
 101      /**
 102       * Constructor
 103       *
 104       * @param string  $host
 105       * @param integer $port
 106       * @param string  $user
 107       * @param string  $password
 108       * @param string  $resource
 109       * @param string  $server
 110       * @param boolean $printlog
 111       * @param string  $loglevel
 112       */
 113  	public function __construct($host, $port, $user, $password, $resource, $server = null, $printlog = false, $loglevel = null) {
 114          parent::__construct($host, $port, $printlog, $loglevel);
 115          
 116          $this->user     = $user;
 117          $this->password = $password;
 118          $this->resource = $resource;
 119          if(!$server) $server = $host;
 120          $this->basejid = $this->user . '@' . $this->host;
 121  
 122          $this->roster = new Roster();
 123          $this->track_presence = true;
 124  
 125          $this->stream_start = '<stream:stream to="' . $server . '" xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" version="1.0">';
 126          $this->stream_end   = '</stream:stream>';
 127          $this->default_ns   = 'jabber:client';
 128          
 129          $this->addXPathHandler('{http://etherx.jabber.org/streams}features', 'features_handler');
 130          $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}success', 'sasl_success_handler');
 131          $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}failure', 'sasl_failure_handler');
 132          $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-tls}proceed', 'tls_proceed_handler');
 133          $this->addXPathHandler('{jabber:client}message', 'message_handler');
 134          $this->addXPathHandler('{jabber:client}presence', 'presence_handler');
 135          $this->addXPathHandler('iq/{jabber:iq:roster}query', 'roster_iq_handler');
 136      }
 137  
 138      /**
 139       * Turn encryption on/ff
 140       *
 141       * @param boolean $useEncryption
 142       */
 143  	public function useEncryption($useEncryption = true) {
 144          $this->use_encryption = $useEncryption;
 145      }
 146      
 147      /**
 148       * Turn on auto-authorization of subscription requests.
 149       *
 150       * @param boolean $autoSubscribe
 151       */
 152  	public function autoSubscribe($autoSubscribe = true) {
 153          $this->auto_subscribe = $autoSubscribe;
 154      }
 155  
 156      /**
 157       * Send XMPP Message
 158       *
 159       * @param string $to
 160       * @param string $body
 161       * @param string $type
 162       * @param string $subject
 163       */
 164  	public function message($to, $body, $type = 'chat', $subject = null, $payload = null) {
 165          if(is_null($type))
 166          {
 167              $type = 'chat';
 168          }
 169          
 170          $to      = htmlspecialchars($to);
 171          $body    = htmlspecialchars($body);
 172          $subject = htmlspecialchars($subject);
 173          
 174          $out = "<message from=\"{$this->fulljid}\" to=\"$to\" type='$type'>";
 175          if($subject) $out .= "<subject>$subject</subject>";
 176          $out .= "<body>$body</body>";
 177          if($payload) $out .= $payload;
 178          $out .= "</message>";
 179          
 180          $this->send($out);
 181      }
 182  
 183      /**
 184       * Set Presence
 185       *
 186       * @param string $status
 187       * @param string $show
 188       * @param string $to
 189       */
 190  	public function presence($status = null, $show = 'available', $to = null, $type='available', $priority=0) {
 191          if($type == 'available') $type = '';
 192          $to     = htmlspecialchars($to);
 193          $status = htmlspecialchars($status);
 194          if($show == 'unavailable') $type = 'unavailable';
 195          
 196          $out = "<presence";
 197          if($to) $out .= " to=\"$to\"";
 198          if($type) $out .= " type='$type'";
 199          if($show == 'available' and !$status) {
 200              $out .= "/>";
 201          } else {
 202              $out .= ">";
 203              if($show != 'available') $out .= "<show>$show</show>";
 204              if($status) $out .= "<status>$status</status>";
 205              if($priority) $out .= "<priority>$priority</priority>";
 206              $out .= "</presence>";
 207          }
 208          
 209          $this->send($out);
 210      }
 211      /**
 212       * Send Auth request
 213       *
 214       * @param string $jid
 215       */
 216  	public function subscribe($jid) {
 217          $this->send("<presence type='subscribe' to='{$jid}' from='{$this->fulljid}' />");
 218          #$this->send("<presence type='subscribed' to='{$jid}' from='{$this->fulljid}' />");
 219      }
 220  
 221      /**
 222       * Message handler
 223       *
 224       * @param string $xml
 225       */
 226  	public function message_handler($xml) {
 227          if(isset($xml->attrs['type'])) {
 228              $payload['type'] = $xml->attrs['type'];
 229          } else {
 230              $payload['type'] = 'chat';
 231          }
 232          $payload['from'] = $xml->attrs['from'];
 233          $payload['body'] = $xml->sub('body')->data;
 234          $payload['xml'] = $xml;
 235          $this->log->log("Message: {$xml->sub('body')->data}", XMPPHP_Log::LEVEL_DEBUG);
 236          $this->event('message', $payload);
 237      }
 238  
 239      /**
 240       * Presence handler
 241       *
 242       * @param string $xml
 243       */
 244  	public function presence_handler($xml) {
 245          $payload['type'] = (isset($xml->attrs['type'])) ? $xml->attrs['type'] : 'available';
 246          $payload['show'] = (isset($xml->sub('show')->data)) ? $xml->sub('show')->data : $payload['type'];
 247          $payload['from'] = $xml->attrs['from'];
 248          $payload['status'] = (isset($xml->sub('status')->data)) ? $xml->sub('status')->data : '';
 249          $payload['priority'] = (isset($xml->sub('priority')->data)) ? intval($xml->sub('priority')->data) : 0;
 250          $payload['xml'] = $xml;
 251          if($this->track_presence) {
 252              $this->roster->setPresence($payload['from'], $payload['priority'], $payload['show'], $payload['status']);
 253          }
 254          $this->log->log("Presence: {$payload['from']} [{$payload['show']}] {$payload['status']}",  XMPPHP_Log::LEVEL_DEBUG);
 255          if(array_key_exists('type', $xml->attrs) and $xml->attrs['type'] == 'subscribe') {
 256              if($this->auto_subscribe) {
 257                  $this->send("<presence type='subscribed' to='{$xml->attrs['from']}' from='{$this->fulljid}' />");
 258                  $this->send("<presence type='subscribe' to='{$xml->attrs['from']}' from='{$this->fulljid}' />");
 259              }
 260              $this->event('subscription_requested', $payload);
 261          } elseif(array_key_exists('type', $xml->attrs) and $xml->attrs['type'] == 'subscribed') {
 262              $this->event('subscription_accepted', $payload);
 263          } else {
 264              $this->event('presence', $payload);
 265          }
 266      }
 267  
 268      /**
 269       * Features handler
 270       *
 271       * @param string $xml
 272       */
 273  	protected function features_handler($xml) {
 274          if($xml->hasSub('starttls') and $this->use_encryption) {
 275              $this->send("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required /></starttls>");
 276          } elseif($xml->hasSub('bind') and $this->authed) {
 277              $id = $this->getId();
 278              $this->addIdHandler($id, 'resource_bind_handler');
 279              $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>");
 280          } else {
 281              $this->log->log("Attempting Auth...");
 282              if ($this->password) {
 283              $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>" . base64_encode("\x00" . $this->user . "\x00" . $this->password) . "</auth>");
 284              } else {
 285                          $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>");
 286              }    
 287          }
 288      }
 289  
 290      /**
 291       * SASL success handler
 292       *
 293       * @param string $xml
 294       */
 295  	protected function sasl_success_handler($xml) {
 296          $this->log->log("Auth success!");
 297          $this->authed = true;
 298          $this->reset();
 299      }
 300      
 301      /**
 302       * SASL feature handler
 303       *
 304       * @param string $xml
 305       */
 306  	protected function sasl_failure_handler($xml) {
 307          $this->log->log("Auth failed!",  XMPPHP_Log::LEVEL_ERROR);
 308          $this->disconnect();
 309          
 310          throw new XMPPHP_Exception('Auth failed!');
 311      }
 312  
 313      /**
 314       * Resource bind handler
 315       *
 316       * @param string $xml
 317       */
 318  	protected function resource_bind_handler($xml) {
 319          if($xml->attrs['type'] == 'result') {
 320              $this->log->log("Bound to " . $xml->sub('bind')->sub('jid')->data);
 321              $this->fulljid = $xml->sub('bind')->sub('jid')->data;
 322              $jidarray = explode('/',$this->fulljid);
 323              $this->jid = $jidarray[0];
 324          }
 325          $id = $this->getId();
 326          $this->addIdHandler($id, 'session_start_handler');
 327          $this->send("<iq xmlns='jabber:client' type='set' id='$id'><session xmlns='urn:ietf:params:xml:ns:xmpp-session' /></iq>");
 328      }
 329  
 330      /**
 331      * Retrieves the roster
 332      *
 333      */
 334  	public function getRoster() {
 335          $id = $this->getID();
 336          $this->send("<iq xmlns='jabber:client' type='get' id='$id'><query xmlns='jabber:iq:roster' /></iq>");
 337      }
 338  
 339      /**
 340      * Roster iq handler
 341      * Gets all packets matching XPath "iq/{jabber:iq:roster}query'
 342      *
 343      * @param string $xml
 344      */
 345  	protected function roster_iq_handler($xml) {
 346          $status = "result";
 347          $xmlroster = $xml->sub('query');
 348          foreach($xmlroster->subs as $item) {
 349              $groups = array();
 350              if ($item->name == 'item') {
 351                  $jid = $item->attrs['jid']; //REQUIRED
 352                  $name = $item->attrs['name']; //MAY
 353                  $subscription = $item->attrs['subscription'];
 354                  foreach($item->subs as $subitem) {
 355                      if ($subitem->name == 'group') {
 356                          $groups[] = $subitem->data;
 357                      }
 358                  }
 359                  $contacts[] = array($jid, $subscription, $name, $groups); //Store for action if no errors happen
 360              } else {
 361                  $status = "error";
 362              }
 363          }
 364          if ($status == "result") { //No errors, add contacts
 365              foreach($contacts as $contact) {
 366                  $this->roster->addContact($contact[0], $contact[1], $contact[2], $contact[3]);
 367              }
 368          }
 369          if ($xml->attrs['type'] == 'set') {
 370              $this->send("<iq type=\"reply\" id=\"{$xml->attrs['id']}\" to=\"{$xml->attrs['from']}\" />");
 371          }
 372      }
 373  
 374      /**
 375       * Session start handler
 376       *
 377       * @param string $xml
 378       */
 379  	protected function session_start_handler($xml) {
 380          $this->log->log("Session started");
 381          $this->session_started = true;
 382          $this->event('session_start');
 383      }
 384  
 385      /**
 386       * TLS proceed handler
 387       *
 388       * @param string $xml
 389       */
 390  	protected function tls_proceed_handler($xml) {
 391          $this->log->log("Starting TLS encryption");
 392          stream_socket_enable_crypto($this->socket, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT);
 393          $this->reset();
 394      }
 395  
 396      /**
 397      * Retrieves the vcard
 398      *
 399      */
 400  	public function getVCard($jid = Null) {
 401          $id = $this->getID();
 402          $this->addIdHandler($id, 'vcard_get_handler');
 403          if($jid) {
 404              $this->send("<iq type='get' id='$id' to='$jid'><vCard xmlns='vcard-temp' /></iq>");
 405          } else {
 406              $this->send("<iq type='get' id='$id'><vCard xmlns='vcard-temp' /></iq>");
 407          }
 408      }
 409  
 410      /**
 411      * VCard retrieval handler
 412      *
 413      * @param XML Object $xml
 414      */
 415  	protected function vcard_get_handler($xml) {
 416          $vcard_array = array();
 417          $vcard = $xml->sub('vcard');
 418          // go through all of the sub elements and add them to the vcard array
 419          foreach ($vcard->subs as $sub) {
 420              if ($sub->subs) {
 421                  $vcard_array[$sub->name] = array();
 422                  foreach ($sub->subs as $sub_child) {
 423                      $vcard_array[$sub->name][$sub_child->name] = $sub_child->data;
 424                  }
 425              } else {
 426                  $vcard_array[$sub->name] = $sub->data;
 427              }
 428          }
 429          $vcard_array['from'] = $xml->attrs['from'];
 430          $this->event('vcard', $vcard_array);
 431      }
 432  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1