* everything working
git-svn-id: svn://netflint.net/xmpphp@7 ef36c318-a008-4979-b6e8-6b496270793b
This commit is contained in:
parent
ce6cae7f4a
commit
962226c573
30
cli_longrun_example.php
Normal file
30
cli_longrun_example.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
include("xmpp.php");
|
||||
$conn = new XMPP('talk.google.com', 5222, 'user', 'password', 'xmpphp', 'gmail.com', $printlog=True, $loglevel=LOGGING_VERBOSE);
|
||||
$conn->connect();
|
||||
while(!$conn->disconnected) {
|
||||
$payloads = $conn->processUntil(array('message', 'presence', 'end_stream', 'session_start'));
|
||||
foreach($payloads as $event) {
|
||||
$pl = $event[1];
|
||||
switch($event[0]) {
|
||||
case 'message':
|
||||
print "---------------------------------------------------------------------------------\n";
|
||||
print "Message from: {$pl['from']}\n";
|
||||
if($pl['subject']) print "Subject: {$pl['subject']}\n";
|
||||
print $pl['body'] . "\n";
|
||||
print "---------------------------------------------------------------------------------\n";
|
||||
$conn->message($pl['from'], $body="Thanks for sending me \"{$pl['body']}\".", $type=$pl['type']);
|
||||
if($pl['body'] == 'quit') $conn->disconnect();
|
||||
if($pl['body'] == 'break') $conn->send("</end>");
|
||||
break;
|
||||
case 'presence':
|
||||
print "Presence: {$pl['from']} [{$pl['show']}] {$pl['status']}\n";
|
||||
break;
|
||||
case 'session_start':
|
||||
$conn->presence($status="Cheese!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
include "cjp.php";
|
||||
$client = new XMPP('talk.google.com', 5222, 'username', 'password', 'ChicXMPP', 'gmail.com');
|
||||
$client->connect();
|
||||
$client->process();
|
||||
|
||||
?>
|
36
logging.php
Normal file
36
logging.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
define('LOGGING_ERROR', 0);
|
||||
define('LOGGING_WARNING', 1);
|
||||
define('LOGGING_INFO', 2);
|
||||
define('LOGGING_DEBUG', 3);
|
||||
define('LOGGING_VERBOSE', 4);
|
||||
|
||||
class Logging {
|
||||
var $data = array();
|
||||
var $names = array();
|
||||
var $runlevel;
|
||||
var $printout;
|
||||
|
||||
function Logging($printout = False, $runlevel=LOGGING_INFO) {
|
||||
$this->names = array('ERROR ', 'WARNING', 'INFO ', 'DEBUG ', 'VERBOSE');
|
||||
$this->runlevel = $runlevel;
|
||||
$this->printout = $printout;
|
||||
}
|
||||
|
||||
function log($msg, $runlevel=Null) {
|
||||
if(!$runlevel) $runlevel = LOGGING_INFO;
|
||||
$data[] = array($this->runlevel, $msg);
|
||||
if($this->printout and $runlevel <= $this->runlevel) print "{$this->names[$runlevel]}: $msg\n";
|
||||
}
|
||||
|
||||
function printout($clear=True, $runlevel=Null) {
|
||||
if(!$runlevel) $runlevel = $this->runlevel;
|
||||
foreach($this->data as $data) {
|
||||
if($runlevel <= $data[0]) print "{$this->names[$runlevel]}: $data[1]\n";
|
||||
}
|
||||
if($clear) $this->data = array();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
9
sendmessage_example.php
Normal file
9
sendmessage_example.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
include("xmpp.php");
|
||||
$conn = new XMPP('talk.google.com', 5222, 'username', 'password', 'xmpphp', 'gmail.com', $printlog=False, $loglevel=LOGGING_INFO);
|
||||
$conn->connect();
|
||||
$conn->processUntil('session_start');
|
||||
$conn->message('someguy@someserver.net', 'This is a test message!');
|
||||
$conn->disconnect();
|
||||
|
||||
?>
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
require_once("xmlobj.php");
|
||||
require_once("logging.php");
|
||||
|
||||
class XMLStream {
|
||||
var $socket;
|
||||
@ -9,7 +10,8 @@ class XMLStream {
|
||||
var $host;
|
||||
var $port;
|
||||
var $stream_start = '<stream>';
|
||||
var $disconnect = false;
|
||||
var $stream_end = '</stream';
|
||||
var $disconnected = false;
|
||||
var $ns_map = array();
|
||||
var $current_ns = array();
|
||||
var $xmlobj = Null;
|
||||
@ -21,13 +23,19 @@ class XMLStream {
|
||||
var $until;
|
||||
var $until_happened = False;
|
||||
var $until_payload = array();
|
||||
var $log;
|
||||
var $reconnect = True;
|
||||
var $been_reset = False;
|
||||
|
||||
function XMLStream($host, $port) {
|
||||
function XMLStream($host, $port, $log=False, $loglevel=Null) {
|
||||
#$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
|
||||
$this->reconnect = True;
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
#set up the parser
|
||||
$this->setupParser();
|
||||
#set up logger
|
||||
$this->log = new Logging($log, $loglevel);
|
||||
}
|
||||
|
||||
function getId() {
|
||||
@ -47,42 +55,50 @@ class XMLStream {
|
||||
$this->eventhanders[] = array($name, $pointer, $obj);
|
||||
}
|
||||
|
||||
function connect($persistent=False) {
|
||||
#if(socket_connect($this->socket, $this->host, $this->port)) {
|
||||
# socket_write($this->socket, $this->stream_start);
|
||||
#}
|
||||
function connect($persistent=False, $sendinit=True) {
|
||||
$this->disconnected = False;
|
||||
if($persistent) {
|
||||
$conflag = STREAM_CLIENT_PERSISTENT;
|
||||
} else {
|
||||
$conflag = STREAM_CLIENT_CONNECT;
|
||||
}
|
||||
print "connecting to tcp://{$this->host}:{$this->port}\n";
|
||||
$this->log->log("Connecting to tcp://{$this->host}:{$this->port}");
|
||||
$this->socket = stream_socket_client("tcp://{$this->host}:{$this->port}", $flags=$conflag);
|
||||
$this->send($this->stream_start);
|
||||
if($sendinit) $this->send($this->stream_start);
|
||||
}
|
||||
|
||||
function apply_socket($socket) {
|
||||
$this->socket = $socket;
|
||||
}
|
||||
|
||||
function process() {
|
||||
$updated = '';
|
||||
while(!$this->disconnect) {
|
||||
#$buff = socket_read($this->socket, 1024);
|
||||
$buff = fread($this->socket, 1024);
|
||||
print "RECV: $buff\n";
|
||||
xml_parse($this->parser, $buff, False);
|
||||
# parse whatever we get out of the socket
|
||||
$read = array($this->socket);
|
||||
$write = NULL;
|
||||
$except = NULL;
|
||||
$updated = stream_select($read, $write, $except, 1);
|
||||
if ($updated > 0) {
|
||||
$buff = fread($this->socket, 1024);
|
||||
if(!$buff and $this->reconnect) $this->doReconnect();
|
||||
$this->log->log("RECV: $buff", LOGGING_VERBOSE);
|
||||
xml_parse($this->parser, $buff, False);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processTime($timeout=-1) {
|
||||
$start = time();
|
||||
$updated = '';
|
||||
while($timeout == -1 or time() - $start < $timeout) {
|
||||
$timeleft = $timeout - (time() - $start);
|
||||
while(!$this->disconnected and ($timeout == -1 or time() - $start < $timeout)) {
|
||||
$read = array($this->socket);
|
||||
$write = NULL;
|
||||
$except = NULL;
|
||||
$updated = stream_select($read, $write, $except, intval($timeleft));
|
||||
$updated = stream_select($read, $write, $except, 1);
|
||||
if ($updated > 0) {
|
||||
$buff = fread($this->socket, 1024);
|
||||
print "RECV: $buff\n";
|
||||
if(!$buff and $this->reconnect) $this->doReconnect();
|
||||
$this->log->log("RECV: $buff", LOGGING_VERBOSE);
|
||||
xml_parse($this->parser, $buff, False);
|
||||
}
|
||||
}
|
||||
@ -94,14 +110,15 @@ class XMLStream {
|
||||
$this->until = $event;
|
||||
$this->until_happened = False;
|
||||
$updated = '';
|
||||
while(!$this->until_happened and (time() - $start < $timeout or $timeout == -1)) {
|
||||
while(!$this->disconnected and !$this->until_happened and (time() - $start < $timeout or $timeout == -1)) {
|
||||
$read = array($this->socket);
|
||||
$write = NULL;
|
||||
$except = NULL;
|
||||
$updated = stream_select($read, $write, $except, 1);
|
||||
if ($updated > 0) {
|
||||
$buff = fread($this->socket, 1024);
|
||||
print "RECV: $buff\n";
|
||||
if(!$buff and $this->reconnect) $this->doReconnect();
|
||||
$this->log->log("RECV: $buff", LOGGING_VERBOSE);
|
||||
xml_parse($this->parser, $buff, False);
|
||||
}
|
||||
}
|
||||
@ -111,6 +128,10 @@ class XMLStream {
|
||||
}
|
||||
|
||||
function startXML($parser, $name, $attr) {
|
||||
if($this->been_reset) {
|
||||
$this->been_reset = False;
|
||||
$this->xml_depth = 0;
|
||||
}
|
||||
$this->xml_depth++;
|
||||
if(array_key_exists('XMLNS', $attr)) {
|
||||
$this->current_ns[$this->xml_depth] = $attr['XMLNS'];
|
||||
@ -139,14 +160,15 @@ class XMLStream {
|
||||
}
|
||||
|
||||
function endXML($parser, $name) {
|
||||
if($this->been_reset) {
|
||||
$this->been_reset = False;
|
||||
$this->xml_depth = 0;
|
||||
}
|
||||
$this->xml_depth--;
|
||||
print "{$this->xml_depth}: $name\n";
|
||||
if($this->xml_depth == 1) {
|
||||
#clean-up old objects
|
||||
$found = False;
|
||||
foreach($this->nshandlers as $handler) {
|
||||
print $this->xml_depth;
|
||||
print "::::{$this->xmlobj[2]->name}:{$this->xmlobj[2]->ns}\n";
|
||||
if($this->xmlobj[2]->name == $handler[0] and ($this->xmlobj[2]->ns == $handler[1] or (!$handler[1] and $this->xmlobj[2]->ns == $this->default_ns))) {
|
||||
if($handler[3] === Null) $handler[3] = $this;
|
||||
call_user_method($handler[2], $handler[3], $this->xmlobj[2]);
|
||||
@ -166,16 +188,37 @@ class XMLStream {
|
||||
$this->xmlobj[0]->subs = Null;
|
||||
}
|
||||
}
|
||||
if($this->xml_depth == 0 and !$this->been_reset) {
|
||||
if(!$this->disconnected) {
|
||||
$this->send($this->stream_end);
|
||||
$this->disconnected = True;
|
||||
fclose($this->socket);
|
||||
if($this->reconnect) {
|
||||
$this->doReconnect();
|
||||
}
|
||||
}
|
||||
$this->event('end_stream');
|
||||
}
|
||||
}
|
||||
|
||||
function doReconnect() {
|
||||
$this->connect(False, False);
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
$this->reconnect = False;
|
||||
$this->send($this->stream_end);
|
||||
$this->processUntil('end_stream', 5);
|
||||
$this->disconnected = True;
|
||||
}
|
||||
|
||||
function event($name, $payload=Null) {
|
||||
print "EVENT: $name\n";
|
||||
$this->log->log("EVENT: $name", LOGGING_DEBUG);
|
||||
foreach($this->eventhandlers as $handler) {
|
||||
print "$name {$handler[0]}\n";
|
||||
if($name == $handler[0]) {
|
||||
if($handler[2] === Null) $handler[2] = $this;
|
||||
call_user_method($handler[1], $handler[2], $payload);
|
||||
print "Called {$handler[1]}\n";
|
||||
}
|
||||
}
|
||||
if(in_array($name, $this->until)) {
|
||||
@ -185,12 +228,12 @@ class XMLStream {
|
||||
}
|
||||
|
||||
function charXML($parser, $data) {
|
||||
$this->xmlobj[$this->xml_depth]->data = $data;
|
||||
$this->xmlobj[$this->xml_depth]->data .= $data;
|
||||
}
|
||||
|
||||
function send($msg) {
|
||||
#socket_write($this->socket, $msg);
|
||||
print "SENT: $msg \n";
|
||||
$this->log->log("SENT: $msg", LOGGING_VERBOSE);
|
||||
fwrite($this->socket, $msg);
|
||||
}
|
||||
|
||||
@ -199,6 +242,7 @@ class XMLStream {
|
||||
$this->xmlobj = Null;
|
||||
$this->setupParser();
|
||||
$this->send($this->stream_start);
|
||||
$this->been_reset = True;
|
||||
}
|
||||
|
||||
function setupParser() {
|
67
xmpp.php
67
xmpp.php
@ -1,20 +1,23 @@
|
||||
<?php
|
||||
require_once("xmlobj.php");
|
||||
require_once("xmlstream.php");
|
||||
require_once("logging.php");
|
||||
|
||||
class XMPP extends XMLStream {
|
||||
var $server;
|
||||
var $user;
|
||||
var $password;
|
||||
var $resource;
|
||||
var $fulljid;
|
||||
|
||||
function XMPP($host, $port, $user, $password, $resource, $server=Null) {
|
||||
$this->XMLStream($host, $port);
|
||||
function XMPP($host, $port, $user, $password, $resource, $server=Null, $printlog=False, $loglevel=Null) {
|
||||
$this->XMLStream($host, $port, $loglevel, $loglevel);
|
||||
$this->user = $user;
|
||||
$this->password = $password;
|
||||
$this->resource = $resource;
|
||||
if(!$server) $server = $host;
|
||||
$this->stream_start = '<stream:stream to="' . $server . '" xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" version="1.0">\n';
|
||||
$this->stream_end = '</stream:stream>';
|
||||
$this->addHandler('features', 'http://etherx.jabber.org/streams', 'features_handler');
|
||||
$this->addHandler('success', 'urn:ietf:params:xml:ns:xmpp-sasl', 'sasl_success_handler');
|
||||
$this->addHandler('failure', 'urn:ietf:params:xml:ns:xmpp-sasl', 'sasl_failure_handler');
|
||||
@ -25,10 +28,51 @@ class XMPP extends XMLStream {
|
||||
}
|
||||
|
||||
function message_handler($xml) {
|
||||
print "Message: {$xml->sub('body')->data}\n";
|
||||
$payload['type'] = $xml->attrs['type'];
|
||||
if(!$paytload['type']) $payload['type'] = 'chat';
|
||||
$payload['from'] = $xml->attrs['from'];
|
||||
$payload['body'] = $xml->sub('body')->data;
|
||||
$this->log->log("Message: {$xml->sub('body')->data}", LOGGING_DEBUG);
|
||||
$this->event('message', $payload);
|
||||
}
|
||||
|
||||
function message($to, $body, $type='chat', $subject=Null) {
|
||||
$to = htmlentities($to);
|
||||
$body = htmlentities($body);
|
||||
$subject = htmlentities($subject);
|
||||
$out = "<message from='{$this->fulljid}' to='$to' type='$type'>";
|
||||
if($subject) $out .= "<subject>$subject</subject>";
|
||||
$out .= "<body>$body</body></message>";
|
||||
$this->send($out);
|
||||
}
|
||||
|
||||
function presence($status=Null, $show='available', $to=Null) {
|
||||
$to = htmlentities($to);
|
||||
$status = htmlentities($status);
|
||||
if($show == 'unavailable') $type = 'unavailable';
|
||||
$out = "<presence";
|
||||
if($to) $out .= " to='$to'";
|
||||
if($type) $out .= " type='$type'";
|
||||
if($show == 'available' and !$status) {
|
||||
$out .= "/>";
|
||||
} else {
|
||||
$out .= ">";
|
||||
if($show != 'available') $out .= "<show>$show</show>";
|
||||
if($status) $out .= "<status>$status</status>";
|
||||
$out .= "</presence>";
|
||||
}
|
||||
$this->send($out);
|
||||
}
|
||||
|
||||
function presence_handler($xml) {
|
||||
$payload['type'] = $xml->attrs['type'];
|
||||
if(!$payload['type']) $payload['type'] = 'available';
|
||||
$payload['show'] = $xml->sub('show')->data;
|
||||
if(!$payload['show']) $payload['show'] = $payload['type'];
|
||||
$payload['from'] = $xml->attrs['from'];
|
||||
$payload['status'] = $xml->sub('status')->data;
|
||||
$this->log->log("Presence: {$payload['from']} [{$payload['show']}] {$payload['status']}", LOGGING_DEBUG);
|
||||
$this->event('presence', $payload);
|
||||
}
|
||||
|
||||
function features_handler($xml) {
|
||||
@ -36,40 +80,41 @@ class XMPP extends XMLStream {
|
||||
$this->send("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required /></starttls>");
|
||||
} elseif($xml->hassub('bind')) {
|
||||
$id = $this->getId();
|
||||
print "ok, we can bind $id\n";
|
||||
$this->addIdHandler($id, '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>");
|
||||
} else {
|
||||
print "Attempting Auth...\n";
|
||||
$this->log->log("Attempting Auth...");
|
||||
$this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>" . base64_encode("\x00" . $this->user . "\x00" . $this->password) . "</auth>");
|
||||
}
|
||||
}
|
||||
|
||||
function sasl_success_handler($xml) {
|
||||
print "Auth success!\n";
|
||||
$this->log->log("Auth success!");
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
function sasl_failure_handler($xml) {
|
||||
print "Auth failed!\n";
|
||||
$this->log->log("Auth failed!", LOGGING_ERROR);
|
||||
}
|
||||
|
||||
function resource_bind_handler($xml) {
|
||||
if($xml->attrs['type'] == 'result') print "Bound to " . $xml->sub('bind')->sub('jid')->data . "\n";
|
||||
if($xml->attrs['type'] == 'result') {
|
||||
$this->log->log("Bound to " . $xml->sub('bind')->sub('jid')->data);
|
||||
$this->fulljid = $xml->sub('bind')->sub('jid')->data;
|
||||
}
|
||||
$id = $this->getId();
|
||||
$this->addIdHandler($id, 'session_start_handler');
|
||||
$this->send("<iq xmlns='jabber:client' type='set' id='$id'><session xmlns='urn:ietf:params:xml:ns:xmpp-session' /></iq>");
|
||||
}
|
||||
|
||||
function session_start_handler($xml) {
|
||||
print "session started\n";
|
||||
$this->log->log("Session started");
|
||||
$this->event('session_start');
|
||||
}
|
||||
|
||||
function tls_proceed_handler($xml) {
|
||||
print "Starting TLS connection\n";
|
||||
$this->log->log("Starting TLS encryption");
|
||||
stream_socket_enable_crypto($this->socket, True, STREAM_CRYPTO_METHOD_TLS_CLIENT);
|
||||
print stream_socket_get_name($this->socket, True) . "\n";
|
||||
$this->reset();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user