<?php
/**
* Jaxl (Jabber XMPP Library)
*
* Copyright (c) 2009-2010, Abhinav Singh <hide@address.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Abhinav Singh nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package jaxl
* @subpackage xmpp
* @author Abhinav Singh <hide@address.com>
* @copyright Abhinav Singh
* @link http://code.google.com/p/jaxl
*/
// include required classes
jaxl_require(array(
'JAXLPlugin',
'JAXLUtil',
'JAXLog'
));
/**
* XMPP Send Class
* Provide methods for sending all kind of xmpp stream and stanza's
*/
class XMPPSend {
public static function startStream($jaxl) {
$xml = '<stream:stream xmlns:stream="http://etherx.jabber.org/streams" version="1.0" xmlns="jabber:client" to="'.$jaxl->domain.'" xml:lang="en" xmlns:xml="http://www.w3.org/XML/1998/namespace">';
return $jaxl->sendXML($xml);
}
public static function endStream($jaxl) {
$xml = '</stream:stream>';
return $jaxl->sendXML($xml, true);
}
public static function startTLS($jaxl) {
$xml = '<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>';
return $jaxl->sendXML($xml);
}
public static function startAuth($jaxl) {
$type = $jaxl->authType;
$xml = '<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="'.$type.'">';
switch($type) {
case 'DIGEST-MD5':
break;
case 'PLAIN':
$xml .= base64_encode("\x00".$jaxl->user."\x00".$jaxl->pass);
break;
case 'ANONYMOUS':
break;
case 'X-FACEBOOK-PLATFORM':
break;
case 'CRAM-MD5':
break;
case 'SCRAM-SHA-1':
$xml .= base64_encode("n,,n=".$jaxl->user.",r=".base64_encode(JAXLUtil::generateNonce()));
break;
default:
break;
}
$xml .= '</auth>';
$jaxl->log("[[XMPPSend]] Performing Auth type: ".$type);
return $jaxl->sendXML($xml);
}
public static function startSession($jaxl, $callback) {
$payload = '<session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>';
return self::iq($jaxl, "set", $payload, $jaxl->domain, false, $callback);
}
public static function startBind($jaxl, $callback) {
$payload = '<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">';
$payload .= '<resource>'.$jaxl->resource.'</resource>';
$payload .= '</bind>';
return self::iq($jaxl, "set", $payload, false, false, $callback);
}
public static function message($jaxl, $to, $from=false, $child=false, $type='normal', $id=false, $ns='jabber:client') {
$xml = '';
if(is_array($to)) {
foreach($to as $key => $value) {
$xml .= self::prepareMessage($jaxl, $to[$key], $from[$key], $child[$key], $type[$key], $id[$key], $ns[$key]);
}
}
else {
$xml .= self::prepareMessage($jaxl, $to, $from, $child, $type, $id, $ns);
}
$jaxl->executePlugin('jaxl_send_message', $xml);
return $jaxl->sendXML($xml);
}
public static function prepareMessage($jaxl, $to, $from, $child, $type, $id, $ns) {
$xml = '<message';
if($from) $xml .= ' from="'.$from.'"';
$xml .= ' to="'.htmlspecialchars($to).'"';
if($type) $xml .= ' type="'.$type.'"';
if($id) $xml .= ' id="'.$id.'"';
$xml .= '>';
if($child) {
if(isset($child['subject'])) $xml .= '<subject>'.JAXLUtil::xmlentities($child['subject']).'</subject>';
if(isset($child['body'])) $xml .= '<body>'.JAXLUtil::xmlentities($child['body']).'</body>';
if(isset($child['thread'])) $xml .= '<thread>'.$child['thread'].'</thread>';
if(isset($child['payload'])) $xml .= $child['payload'];
}
$xml .= '</message>';
return $xml;
}
public static function presence($jaxl, $to=false, $from=false, $child=false, $type=false, $id=false, $ns='jabber:client') {
$xml = '';
if(is_array($to)) {
foreach($to as $key => $value) {
$xml .= self::preparePresence($jaxl, $to[$key], $from[$key], $child[$key], $type[$key], $id[$key], $ns[$key]);
}
}
else {
$xml .= self::preparePresence($jaxl, $to, $from, $child, $type, $id, $ns);
}
$jaxl->executePlugin('jaxl_send_presence', $xml);
return $jaxl->sendXML($xml);
}
public static function preparePresence($jaxl, $to, $from, $child, $type, $id, $ns) {
$xml = '<presence';
if($type) $xml .= ' type="'.$type.'"';
if($from) $xml .= ' from="'.$from.'"';
if($to) $xml .= ' to="'.htmlspecialchars($to).'"';
if($id) $xml .= ' id="'.$id.'"';
$xml .= '>';
if($child) {
if(isset($child['show'])) $xml .= '<show>'.$child['show'].'</show>';
if(isset($child['status'])) $xml .= '<status>'.JAXLUtil::xmlentities($child['status']).'</status>';
if(isset($child['priority'])) $xml .= '<priority>'.$child['priority'].'</priority>';
// if(isset($child['payload'])) $xml .= $child['payload'];
}
// A little patch to allow Movim to receive Microbloging + PEP stanzas
$xml .= '<c xmlns="http://jabber.org/protocol/caps" hash="sha1" node="http://code.google.com/p/jaxl" ver="gHGosFLOsho3lu2BzyDJ04j78wQ="/>';
$xml.= '</presence>';
return $xml;
}
public static function iq($jaxl, $type, $payload=false, $to=false, $from=false, $callback=false, $id=false, $ns='jabber:client') {
if($type == 'get' || $type == 'set') {
$id = $jaxl->getId();
if($callback) {
$jaxl->addPlugin('jaxl_get_iq_'.$id, $callback);
// In bosh environment following scenario needs to be taken care:
// request-1 pinging for new data
// request-2 sends an iq get request
// request-1 receives iq result response
// callback registered during request-2 is unavailable in request-1 loop
// as a result user application doesn't receive any callback for data
}
}
$types = array('get','set','result','error');
$xml = '';
$xml .= '<iq';
$xml .= ' type="'.$type.'"';
$xml .= ' id="'.$id.'"';
if($to) $xml .= ' to="'.$to.'"';
if($from) $xml .= ' from="'.$from.'"';
$xml .= '>';
if($payload) $xml .= $payload;
$xml .= '</iq>';
$jaxl->sendXML($xml);
if($type == 'get' || $type == 'set') return $id;
else return true;
}
}
?>