Page MenuHomePhabricator

D5873.diff
No OneTemporary

D5873.diff

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: externals/JAXL/.gitignore
===================================================================
--- /dev/null
+++ externals/JAXL/.gitignore
@@ -0,0 +1,6 @@
+.buildpath
+.project
+.jaxl
+.pydevproject
+.settings/
+docs/_build
Index: externals/JAXL/LICENSE
===================================================================
--- /dev/null
+++ externals/JAXL/LICENSE
@@ -0,0 +1,33 @@
+Jaxl (Jabber XMPP Library)
+
+Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
Index: externals/JAXL/README.md
===================================================================
--- /dev/null
+++ externals/JAXL/README.md
@@ -0,0 +1,30 @@
+Jaxl v3.x:
+-----------
+Jaxl v3.x is a successor of v2.x (and is NOT backward compatible),
+carrying a lot of code from v2.x while throwing away the ugly parts.
+A lot of components have been re-written keeping in mind the feedback from
+the developer community over the last 4 years. Also Jaxl shares a few
+philosophies from my experience with erlang and python languages.
+
+Jaxl is an asynchronous, non-blocking I/O, event based PHP library
+for writing custom TCP/IP client and server implementations.
+From it's previous versions, library inherits a full blown stable support
+for [XMPP protocol stack](https://github.com/abhinavsingh/JAXL/tree/v3.x/xmpp).
+In v3.0, support for [HTTP protocol stack](https://github.com/abhinavsingh/JAXL/tree/v3.x/http)
+has also been added.
+
+At the heart of every protocol stack sits the [Core stack](https://github.com/abhinavsingh/JAXL/tree/v3.x/core).
+It contains all the building blocks for everything that we aim to do with Jaxl library.
+Both XMPP and HTTP protocol stacks are written on top of the Core stack.
+Infact the source code of protocol implementations knows nothing
+about the standard (inbuilt) PHP socket and stream methods.
+
+[Examples](https://github.com/abhinavsingh/JAXL/tree/v3.x/examples/)
+
+[Documentation](http://jaxl.readthedocs.org/)
+
+[Group and Mailing List](https://groups.google.com/forum/#!forum/jaxl)
+
+[Create a bug/issue](https://github.com/abhinavsingh/JAXL/issues/new)
+
+[Author](http://abhinavsingh.com/)
Index: externals/JAXL/composer.json
===================================================================
--- /dev/null
+++ externals/JAXL/composer.json
@@ -0,0 +1,23 @@
+{
+ "name": "abhinavsingh/jaxl",
+ "type": "library",
+ "description": "Jaxl - Async, Non-Blocking, Event based Networking Library in PHP.",
+ "keywords": ["xmpp", "jabber", "http", "asynchronous", "non blocking", "event loop", "php", "jaxl", "abhinavsingh"],
+ "homepage": "http://jaxl.readthedocs.org/en/latest/index.html",
+ "license": "MIT",
+
+ "authors": [
+ {
+ "name": "Abhinavsingh",
+ "homepage": "https://abhinavsingh.com/"
+ }
+ ],
+
+ "require": {
+ "php": ">=5.2.4"
+ },
+
+ "autoload": {
+ "files": ["jaxl.php"]
+ }
+}
\ No newline at end of file
Index: externals/JAXL/core/README.md
===================================================================
--- /dev/null
+++ externals/JAXL/core/README.md
@@ -0,0 +1,17 @@
+Jaxl Core Stack:
+----------------
+Core stack implementation includes:
+
+* JAXLLoop - Event Loop
+* JAXLClock - Time and Periodic Job server
+* JAXLSocketClient - Generic Non-Blocking Socket Client
+* JAXLSocketServer - Generic Non-Blocking Socket Server
+* JAXLCli - Generic Non-Blocking Command Line Interface
+* JAXLEvent - Generic Event Emitter
+* JAXLFsm - Generic Finite State Machine
+* JAXLLogger - Logging utilities
+* JAXLPipe - Bidirectional Communication between Processes using Unix Pipes
+* JAXLSock5 - SOCKS5 RFC Implementation
+* JAXLXml - Light Weight XML Representation
+* JAXLXmlStream - Streaming XML Parser
+* JAXLException - Error, Exception and Shutdown handler
\ No newline at end of file
Index: externals/JAXL/core/jaxl_cli.php
===================================================================
--- /dev/null
+++ externals/JAXL/core/jaxl_cli.php
@@ -0,0 +1,97 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/core/jaxl_loop.php';
+
+class JAXLCli {
+
+ public static $counter = 0;
+ private $in = null;
+
+ private $quit_cb = null;
+ private $recv_cb = null;
+ private $recv_chunk_size = 1024;
+
+ public function __construct($recv_cb=null, $quit_cb=null) {
+ $this->recv_cb = $recv_cb;
+ $this->quit_cb = $quit_cb;
+
+ // catch read event on stdin
+ $this->in = fopen('php://stdin', 'r');
+ stream_set_blocking($this->in, false);
+ JAXLLoop::watch($this->in, array(
+ 'read' => array(&$this, 'on_read_ready')
+ ));
+ }
+
+ public function __destruct() {
+ @fclose($this->in);
+ }
+
+ public function stop() {
+ JAXLLoop::unwatch($this->in, array(
+ 'read' => true
+ ));
+ }
+
+ public function on_read_ready($in) {
+ $raw = @fread($in, $this->recv_chunk_size);
+
+ if(ord($raw) == 10) {
+ // enter key
+ JAXLCli::prompt(false);
+ return;
+ }
+ else if(trim($raw) == 'quit') {
+ $this->stop();
+ $this->in = null;
+ if($this->quit_cb) call_user_func($this->quit_cb);
+ return;
+ }
+
+ if($this->recv_cb) call_user_func($this->recv_cb, $raw);
+ }
+
+ public static function prompt($inc=true) {
+ if($inc) ++self::$counter;
+ echo "jaxl ".self::$counter."> ";
+ }
+
+}
+
+?>
Index: externals/JAXL/core/jaxl_clock.php
===================================================================
--- /dev/null
+++ externals/JAXL/core/jaxl_clock.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+class JAXLClock {
+
+ // current clock time in microseconds
+ private $tick = 0;
+
+ // current Unix timestamp with microseconds
+ public $time = null;
+
+ // scheduled jobs
+ public $jobs = array();
+
+ public function __construct() {
+ $this->time = microtime(true);
+ }
+
+ public function __destruct() {
+ _info("shutting down clock server...");
+ }
+
+ public function tick($by=null) {
+ // update clock
+ if($by) {
+ $this->tick += $by;
+ $this->time += $by / pow(10,6);
+ }
+ else {
+ $time = microtime(true);
+ $by = $time - $this->time;
+ $this->tick += $by * pow(10, 6);
+ $this->time = $time;
+ }
+
+ // run scheduled jobs
+ foreach($this->jobs as $ref=>$job) {
+ if($this->tick >= $job['scheduled_on'] + $job['after']) {
+ //_debug("running job#".($ref+1)." at tick ".$this->tick.", scheduled on ".$job['scheduled_on']." after ".$job['after'].", periodic ".$job['is_periodic']);
+ call_user_func($job['cb'], $job['args']);
+ if(!$job['is_periodic']) {
+ unset($this->jobs[$ref]);
+ }
+ else {
+ $job['scheduled_on'] = $this->tick;
+ $job['runs']++;
+ $this->jobs[$ref] = $job;
+ }
+ }
+ }
+ }
+
+ // calculate execution time of callback
+ public function tc($callback, $args=null) {
+
+ }
+
+ // callback after $time microseconds
+ public function call_fun_after($time, $callback, $args=null) {
+ $this->jobs[] = array(
+ 'scheduled_on' => $this->tick,
+ 'after' => $time,
+ 'cb' => $callback,
+ 'args' => $args,
+ 'is_periodic' => false,
+ 'runs' => 0
+ );
+ return sizeof($this->jobs);
+ }
+
+ // callback periodically after $time microseconds
+ public function call_fun_periodic($time, $callback, $args=null) {
+ $this->jobs[] = array(
+ 'scheduled_on' => $this->tick,
+ 'after' => $time,
+ 'cb' => $callback,
+ 'args' => $args,
+ 'is_periodic' => true,
+ 'runs' => 0
+ );
+ return sizeof($this->jobs);
+ }
+
+ // cancel a previously scheduled callback
+ public function cancel_fun_call($ref) {
+ unset($this->jobs[$ref-1]);
+ }
+
+}
+
+?>
Index: externals/JAXL/core/jaxl_event.php
===================================================================
--- /dev/null
+++ externals/JAXL/core/jaxl_event.php
@@ -0,0 +1,121 @@
+<?php
+/**
+* Jaxl (Jabber XMPP Library)
+*
+* Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+*
+*/
+
+/**
+ * following kind of events are possible:
+ * 1) hook i.e. if a callback for such an event is registered, calling function is responsible for the workflow from their on
+ * 2) filter i.e. calling function will manipulate passed arguments and modified arguments will be passed to next chain of filter
+ *
+ * As a rule of thumb, only 1 hook can be registered for an event, while more than 1 filter is allowed for an event
+ * hook and filter both cannot be applied on an event
+ *
+ * @author abhinavsingh
+ *
+ */
+class JAXLEvent {
+
+ protected $common = array();
+ public $reg = array();
+
+ public function __construct($common) {
+ $this->common = $common;
+ }
+
+ public function __destruct() {
+
+ }
+
+ // add callback on a event
+ // returns a reference to be used while deleting callback
+ // callback'd method must return TRUE to be persistent
+ // if none returned or FALSE, callback will be removed automatically
+ public function add($ev, $cb, $pri) {
+ if(!isset($this->reg[$ev]))
+ $this->reg[$ev] = array();
+
+ $ref = sizeof($this->reg[$ev]);
+ $this->reg[$ev][] = array($pri, $cb);
+ return $ev."-".$ref;
+ }
+
+ // emit event to notify registered callbacks
+ // is a pqueue required here for performance enhancement
+ // in case we have too many cbs on a specific event?
+ public function emit($ev, $data=array()) {
+ $data = array_merge($this->common, $data);
+ $cbs = array();
+
+ if(!isset($this->reg[$ev])) return $data;
+
+ foreach($this->reg[$ev] as $cb) {
+ if(!isset($cbs[$cb[0]]))
+ $cbs[$cb[0]] = array();
+ $cbs[$cb[0]][] = $cb[1];
+ }
+
+ foreach($cbs as $pri => $cb) {
+ foreach($cb as $c) {
+ $ret = call_user_func_array($c, $data);
+ // this line is for fixing situation where callback function doesn't return an array type
+ // in such cases next call of call_user_func_array will report error since $data is not an array type as expected
+ // things will change in future, atleast put the callback inside a try/catch block
+ // here we only check if there was a return, if yes we update $data with return value
+ // this is bad design, need more thoughts, should work as of now
+ if($ret) $data = $ret;
+ }
+ }
+
+ unset($cbs);
+ return $data;
+ }
+
+ // remove previous registered callback
+ public function del($ref) {
+ $ref = explode("-", $ref);
+ unset($this->reg[$ref[0]][$ref[1]]);
+ }
+
+ public function exists($ev) {
+ $ret = isset($this->reg[$ev]);
+ //_debug("event ".$ev." callback ".($ret ? "exists" : "do not exists"));
+ return $ret;
+ }
+
+}
+
+?>
Index: externals/JAXL/core/jaxl_exception.php
===================================================================
--- /dev/null
+++ externals/JAXL/core/jaxl_exception.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+error_reporting(E_ALL | E_STRICT);
+
+/**
+ *
+ * @author abhinavsingh
+ */
+class JAXLException extends Exception {
+
+ public function __construct($message = null, $code = null, $file = null, $line = null) {
+ _notice("got jaxl exception construct with $message, $code, $file, $line");
+ if($code === null) {
+ parent::__construct($message);
+ }
+ else {
+ parent::__construct($message, $code);
+ }
+
+ if($file !== null) {
+ $this->file = $file;
+ }
+
+ if($line !== null) {
+ $this->line = $line;
+ }
+ }
+
+ public static function error_handler($errno, $error, $file, $line, $vars) {
+ _debug("error handler called with $errno, $error, $file, $line");
+ if($errno === 0 || ($errno & error_reporting()) === 0) {
+ return;
+ }
+
+ throw new JAXLException($error, $errno, $file, $line);
+ }
+
+ public static function exception_handler($e) {
+ _debug("exception handler catched ".json_encode($e));
+
+ // TODO: Pretty print backtrace
+ //print_r(debug_backtrace());
+ }
+
+ public static function shutdown_handler() {
+ try {
+ _debug("got shutdown handler");
+ if(null !== ($error = error_get_last())) {
+ throw new JAXLException($error['message'], $error['type'], $error['file'], $error['line']);
+ }
+ }
+ catch(Exception $e) {
+ _debug("shutdown handler catched with exception ".json_encode($e));
+ }
+ }
+}
+
+?>
Index: externals/JAXL/core/jaxl_fsm.php
===================================================================
--- /dev/null
+++ externals/JAXL/core/jaxl_fsm.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+abstract class JAXLFsm {
+
+ protected $state = null;
+
+ // abstract method
+ abstract public function handle_invalid_state($r);
+
+ public function __construct($state) {
+ $this->state = $state;
+ }
+
+ // returned value from state callbacks can be:
+ // 1) array() <-- is_callable method
+ // 2) array([0]=>'new_state', [1]=>'return value for current callback') <-- is_not_callable method
+ // 3) array([0]=>'new_state')
+ // 4) 'new_state'
+ //
+ // for case 1) new state will be an array
+ // for other cases new state will be a string
+ public function __call($event, $args) {
+ if($this->state) {
+ // call state method
+ _debug("calling state handler '".(is_array($this->state) ? $this->state[1] : $this->state)."' for incoming event '".$event."'");
+ $call = is_callable($this->state) ? $this->state : (method_exists($this, $this->state) ? array(&$this, $this->state): $this->state);
+ $r = call_user_func($call, $event, $args);
+
+ // 4 cases of possible return value
+ if(is_callable($r)) $this->state = $r;
+ else if(is_array($r) && sizeof($r) == 2) list($this->state, $ret) = $r;
+ else if(is_array($r) && sizeof($r) == 1) $this->state = $r[0];
+ else if(is_string($r)) $this->state = $r;
+ else $this->handle_invalid_state($r);
+ _debug("current state '".(is_array($this->state) ? $this->state[1] : $this->state)."'");
+
+ // return case
+ if(!is_callable($r) && is_array($r) && sizeof($r) == 2)
+ return $ret;
+ }
+ else {
+ _debug("invalid state found, nothing called for event ".$event."");
+ }
+ }
+
+}
+
+?>
Index: externals/JAXL/core/jaxl_logger.php
===================================================================
--- /dev/null
+++ externals/JAXL/core/jaxl_logger.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// log level
+define('JAXL_ERROR', 1);
+define('JAXL_WARNING', 2);
+define('JAXL_NOTICE', 3);
+define('JAXL_INFO', 4);
+define('JAXL_DEBUG', 5);
+
+// generic global logging shortcuts for different level of verbosity
+function _error($msg) { JAXLLogger::log($msg, JAXL_ERROR); }
+function _warning($msg) { JAXLLogger::log($msg, JAXL_WARNING); }
+function _notice($msg) { JAXLLogger::log($msg, JAXL_NOTICE); }
+function _info($msg) { JAXLLogger::log($msg, JAXL_INFO); }
+function _debug($msg) { JAXLLogger::log($msg, JAXL_DEBUG); }
+
+// generic global terminal output colorize method
+// finally sends colorized message to terminal using error_log/1
+// this method is mainly to escape $msg from file:line and time
+// prefix done by _debug, _error, ... methods
+function _colorize($msg, $verbosity) { error_log(JAXLLogger::colorize($msg, $verbosity)); }
+
+class JAXLLogger {
+
+ public static $level = JAXL_DEBUG;
+ public static $path = null;
+ public static $max_log_size = 1000;
+
+ protected static $colors = array(
+ 1 => 31, // error: red
+ 2 => 34, // warning: blue
+ 3 => 33, // notice: yellow
+ 4 => 32, // info: green
+ 5 => 37 // debug: white
+ );
+
+ public static function log($msg, $verbosity=1) {
+ if($verbosity <= self::$level) {
+ $bt = debug_backtrace(); array_shift($bt); $callee = array_shift($bt);
+ $msg = basename($callee['file'], '.php').":".$callee['line']." - ".@date('Y-m-d H:i:s')." - ".$msg;
+
+ $size = strlen($msg);
+ if($size > self::$max_log_size) $msg = substr($msg, 0, self::$max_log_size) . ' ...';
+
+ if(isset(self::$path)) error_log($msg . PHP_EOL, 3, self::$path);
+ else error_log(self::colorize($msg, $verbosity));
+ }
+ }
+
+ public static function colorize($msg, $verbosity) {
+ return "\033[".self::$colors[$verbosity]."m".$msg."\033[0m";
+ }
+
+}
+
+?>
Index: externals/JAXL/core/jaxl_loop.php
===================================================================
--- /dev/null
+++ externals/JAXL/core/jaxl_loop.php
@@ -0,0 +1,159 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/core/jaxl_logger.php';
+require_once JAXL_CWD.'/core/jaxl_clock.php';
+
+/**
+ *
+ * Enter description here ...
+ * @author abhinavsingh
+ *
+ */
+class JAXLLoop {
+
+ public static $clock = null;
+
+ private static $is_running = false;
+ private static $active_read_fds = 0;
+ private static $active_write_fds = 0;
+
+ private static $read_fds = array();
+ private static $read_cbs = array();
+ private static $write_fds = array();
+ private static $write_cbs = array();
+
+ public static $secs = 0;
+ public static $usecs = 30000;
+
+ private function __construct() {}
+ private function __clone() {}
+
+ public static function watch($fd, $opts) {
+ if(isset($opts['read'])) {
+ $fdid = (int) $fd;
+ self::$read_fds[$fdid] = $fd;
+ self::$read_cbs[$fdid] = $opts['read'];
+ ++self::$active_read_fds;
+ }
+
+ if(isset($opts['write'])) {
+ $fdid = (int) $fd;
+ self::$write_fds[$fdid] = $fd;
+ self::$write_cbs[$fdid] = $opts['write'];
+ ++self::$active_write_fds;
+ }
+
+ _debug("active read fds: ".self::$active_read_fds.", write fds: ".self::$active_write_fds);
+ }
+
+ public static function unwatch($fd, $opts) {
+ if(isset($opts['read'])) {
+ $fdid = (int) $fd;
+ if(isset(self::$read_fds[$fdid])) {
+ unset(self::$read_fds[$fdid]);
+ unset(self::$read_cbs[$fdid]);
+ --self::$active_read_fds;
+ }
+ }
+
+ if(isset($opts['write'])) {
+ $fdid = (int) $fd;
+ if(isset(self::$write_fds[$fdid])) {
+ unset(self::$write_fds[$fdid]);
+ unset(self::$write_cbs[$fdid]);
+ --self::$active_write_fds;
+ }
+ }
+
+ _debug("active read fds: ".self::$active_read_fds.", write fds: ".self::$active_write_fds);
+ }
+
+ public static function run() {
+ if(!self::$is_running) {
+ self::$is_running = true;
+ self::$clock = new JAXLClock();
+
+ while((self::$active_read_fds + self::$active_write_fds) > 0)
+ self::select();
+
+ _debug("no more active fd's to select");
+ self::$is_running = false;
+ }
+ }
+
+ public static function select() {
+ $read = self::$read_fds;
+ $write = self::$write_fds;
+ $except = null;
+
+ $changed = @stream_select($read, $write, $except, self::$secs, self::$usecs);
+ if($changed === false) {
+ _error("error in the event loop, shutting down...");
+ /*foreach(self::$read_fds as $fd) {
+ if(is_resource($fd))
+ print_r(stream_get_meta_data($fd));
+ }*/
+ exit;
+ }
+ else if($changed > 0) {
+ // read callback
+ foreach($read as $r) {
+ $fdid = array_search($r, self::$read_fds);
+ if(isset(self::$read_fds[$fdid]))
+ call_user_func(self::$read_cbs[$fdid], self::$read_fds[$fdid]);
+ }
+
+ // write callback
+ foreach($write as $w) {
+ $fdid = array_search($w, self::$write_fds);
+ if(isset(self::$write_fds[$fdid]))
+ call_user_func(self::$write_cbs[$fdid], self::$write_fds[$fdid]);
+ }
+
+ self::$clock->tick();
+ }
+ else if($changed === 0) {
+ //_debug("nothing changed while selecting for read");
+ self::$clock->tick((self::$secs * pow(10,6)) + self::$usecs);
+ }
+ }
+
+}
+
+?>
Index: externals/JAXL/core/jaxl_pipe.php
===================================================================
--- /dev/null
+++ externals/JAXL/core/jaxl_pipe.php
@@ -0,0 +1,115 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/core/jaxl_event.php';
+require_once JAXL_CWD.'/core/jaxl_loop.php';
+
+/**
+ * bidirectional communication pipes for processes
+ *
+ * This is how this will be (when complete):
+ * $pipe = new JAXLPipe() will return an array of size 2
+ * $pipe[0] represents the read end of the pipe
+ * $pipe[1] represents the write end of the pipe
+ *
+ * Proposed functionality might even change (currently consider this as experimental)
+ *
+ * @author abhinavsingh
+ *
+ */
+class JAXLPipe {
+
+ protected $perm = 0600;
+
+ protected $recv_cb = null;
+ protected $fd = null;
+ protected $client = null;
+
+ public $name = null;
+
+ public function __construct($name, $read_cb=null) {
+ $pipes_folder = JAXL_CWD.'/.jaxl/pipes';
+ if(!is_dir($pipes_folder)) mkdir($pipes_folder);
+
+ $this->ev = new JAXLEvent();
+ $this->name = $name;
+ $this->read_cb = $read_cb;
+
+ $pipe_path = $this->get_pipe_file_path();
+ if(!file_exists($pipe_path)) {
+ posix_mkfifo($pipe_path, $this->perm);
+ $this->fd = fopen($pipe_path, 'r+');
+ if(!$this->fd) {
+ _error("unable to open pipe");
+ }
+ else {
+ _debug("pipe opened using path $pipe_path");
+ _notice("Usage: $ echo 'Hello World!' > $pipe_path");
+
+ $this->client = new JAXLSocketClient();
+ $this->client->connect($this->fd);
+ $this->client->set_callback(array(&$this, 'on_data'));
+ }
+ }
+ else {
+ _error("pipe with name $name already exists");
+ }
+ }
+
+ public function __destruct() {
+ @fclose($this->fd);
+ @unlink($this->get_pipe_file_path());
+ _debug("unlinking pipe file");
+ }
+
+ public function get_pipe_file_path() {
+ return JAXL_CWD.'/.jaxl/pipes/jaxl_'.$this->name.'.pipe';
+ }
+
+ public function set_callback($recv_cb) {
+ $this->recv_cb = $recv_cb;
+ }
+
+ public function on_data($data) {
+ // callback
+ if($this->recv_cb) call_user_func($this->recv_cb, $data);
+ }
+
+}
+
+?>
Index: externals/JAXL/core/jaxl_sock5.php
===================================================================
--- /dev/null
+++ externals/JAXL/core/jaxl_sock5.php
@@ -0,0 +1,128 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/core/jaxl_socket_client.php';
+
+/**
+ * TODO: convert into a finite state machine
+ *
+ * @author abhinavsingh
+ *
+ */
+class JAXLSock5 {
+
+ private $client = null;
+
+ protected $transport = null;
+ protected $ip = null;
+ protected $port = null;
+
+ public function __construct($transport='tcp') {
+ $this->transport = $transport;
+ $this->client = new JAXLSocketClient();
+ $this->client->set_callback(array(&$this, 'on_response'));
+ }
+
+ public function __destruct() {
+
+ }
+
+ public function connect($ip, $port=1080) {
+ $this->ip = $ip;
+ $this->port = $port;
+ $sock_path = $this->_sock_path();
+
+ if($this->client->connect($sock_path)) {
+ _debug("established connection to $sock_path");
+ return true;
+ }
+ else {
+ _error("unable to connect $sock_path");
+ return false;
+ }
+ }
+
+ //
+ // Three phases of SOCK5
+ //
+
+ // Negotiation pkt consists of 3 part:
+ // 0x05 => Sock protocol version
+ // 0x01 => Number of method identifier octet
+ //
+ // Following auth methods are defined:
+ // 0x00 => No authentication required
+ // 0x01 => GSSAPI
+ // 0x02 => USERNAME/PASSWORD
+ // 0x03 to 0x7F => IANA ASSIGNED
+ // 0x80 to 0xFE => RESERVED FOR PRIVATE METHODS
+ // 0xFF => NO ACCEPTABLE METHODS
+ public function negotiate() {
+ $pkt = pack("C3", 0x05, 0x01, 0x00);
+ $this->client->send($pkt);
+
+ // enter sub-negotiation state
+ }
+
+ public function relay_request() {
+ // enter wait for reply state
+ }
+
+ public function send_data() {
+
+ }
+
+ //
+ // Socket client callback
+ //
+
+ public function on_response($raw) {
+ _debug($raw);
+ }
+
+ //
+ // Private
+ //
+
+ protected function _sock_path() {
+ return $this->transport.'://'.$this->ip.':'.$this->port;
+ }
+
+}
+
+?>
Index: externals/JAXL/core/jaxl_socket_client.php
===================================================================
--- /dev/null
+++ externals/JAXL/core/jaxl_socket_client.php
@@ -0,0 +1,219 @@
+<?php
+/**
+* Jaxl (Jabber XMPP Library)
+*
+* Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+*
+*/
+
+require_once JAXL_CWD.'/core/jaxl_loop.php';
+
+/**
+ *
+ * Enter description here ...
+ * @author abhinavsingh
+ *
+ */
+class JAXLSocketClient {
+
+ private $host = null;
+ private $port = null;
+ private $transport = null;
+ private $stream_context = null;
+ private $blocking = false;
+
+ public $fd = null;
+
+ public $errno = null;
+ public $errstr = null;
+ private $timeout = 10;
+
+ private $ibuffer = "";
+ private $obuffer = "";
+ private $compressed = false;
+
+ private $recv_bytes = 0;
+ private $send_bytes = 0;
+
+ private $recv_cb = null;
+ private $recv_chunk_size = 1024;
+ private $writing = false;
+
+ public function __construct($stream_context=null) {
+ $this->stream_context = $stream_context;
+ }
+
+ public function __destruct() {
+ //_debug("cleaning up xmpp socket...");
+ $this->disconnect();
+ }
+
+ public function set_callback($recv_cb) {
+ $this->recv_cb = $recv_cb;
+ }
+
+ /**
+ * @param string | resource $socket_path
+ */
+ public function connect($socket_path) {
+ if(gettype($socket_path) == "string") {
+ $path_parts = explode(":", $socket_path);
+ $this->transport = $path_parts[0];
+ $this->host = substr($path_parts[1], 2, strlen($path_parts[1]));
+ if(sizeof($path_parts) == 3) $this->port = $path_parts[2];
+
+ _info("trying ".$socket_path);
+ if($this->stream_context) $this->fd = @stream_socket_client($socket_path, $this->errno, $this->errstr, $this->timeout, STREAM_CLIENT_CONNECT, $this->stream_context);
+ else $this->fd = @stream_socket_client($socket_path, $this->errno, $this->errstr, $this->timeout);
+ }
+ else {
+ $this->fd = &$socket_path;
+ }
+
+ if($this->fd) {
+ _debug("connected to ".$socket_path."");
+ stream_set_blocking($this->fd, $this->blocking);
+
+ // watch descriptor for read/write events
+ JAXLLoop::watch($this->fd, array(
+ 'read' => array(&$this, 'on_read_ready')
+ ));
+
+ return true;
+ }
+ else {
+ _error("unable to connect ".$socket_path." with error no: ".$this->errno.", error str: ".$this->errstr."");
+ $this->disconnect();
+ return false;
+ }
+ }
+
+ public function disconnect() {
+ JAXLLoop::unwatch($this->fd, array(
+ 'read' => true,
+ 'write' => true
+ ));
+ @fclose($this->fd);
+ $this->fd = null;
+ }
+
+ public function compress() {
+ $this->compressed = true;
+ //stream_filter_append($this->fd, 'zlib.inflate', STREAM_FILTER_READ);
+ //stream_filter_append($this->fd, 'zlib.deflate', STREAM_FILTER_WRITE);
+ }
+
+ public function crypt() {
+ // set blocking (since tls negotiation fails if stream is non-blocking)
+ stream_set_blocking($this->fd, true);
+
+ $ret = stream_socket_enable_crypto($this->fd, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
+ if($ret == false) {
+ $ret = stream_socket_enable_crypto($this->fd, true, STREAM_CRYPTO_METHOD_SSLv3_CLIENT);
+ if($ret == false) {
+ $ret = stream_socket_enable_crypto($this->fd, true, STREAM_CRYPTO_METHOD_SSLv2_CLIENT);
+ if($ret == false) {
+ $ret = stream_socket_enable_crypto($this->fd, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT);
+ }
+ }
+ }
+
+ // switch back to non-blocking
+ stream_set_blocking($this->fd, false);
+ return $ret;
+ }
+
+ public function send($data) {
+ $this->obuffer .= $data;
+
+ // add watch for write events
+ if($this->writing) return;
+ JAXLLoop::watch($this->fd, array(
+ 'write' => array(&$this, 'on_write_ready')
+ ));
+ $this->writing = true;
+ }
+
+ public function on_read_ready($fd) {
+ //_debug("on read ready called");
+ $raw = @fread($fd, $this->recv_chunk_size);
+ $bytes = strlen($raw);
+
+ if($bytes === 0) {
+ $meta = stream_get_meta_data($fd);
+ if($meta['eof'] === TRUE) {
+ _warning("socket eof, disconnecting");
+ JAXLLoop::unwatch($fd, array(
+ 'read' => true
+ ));
+ $this->disconnect();
+ return;
+ }
+ }
+
+ $this->recv_bytes += $bytes;
+ $total = $this->ibuffer.$raw;
+
+ $this->ibuffer = "";
+ _debug("read ".$bytes."/".$this->recv_bytes." of data");
+ if($bytes > 0) _debug($raw);
+
+ // callback
+ if($this->recv_cb) call_user_func($this->recv_cb, $raw);
+ }
+
+ public function on_write_ready($fd) {
+ //_debug("on write ready called");
+ $total = strlen($this->obuffer);
+ $bytes = @fwrite($fd, $this->obuffer);
+ $this->send_bytes += $bytes;
+
+ _debug("sent ".$bytes."/".$this->send_bytes." of data");
+ _debug(substr($this->obuffer, 0, $bytes));
+
+ $this->obuffer = substr($this->obuffer, $bytes, $total-$bytes);
+
+ // unwatch for write if obuffer is empty
+ if(strlen($this->obuffer) === 0) {
+ JAXLLoop::unwatch($fd, array(
+ 'write' => true
+ ));
+ $this->writing = false;
+ }
+
+ //_debug("current obuffer size: ".strlen($this->obuffer)."");
+ }
+
+}
+
+?>
Index: externals/JAXL/core/jaxl_socket_server.php
===================================================================
--- /dev/null
+++ externals/JAXL/core/jaxl_socket_server.php
@@ -0,0 +1,258 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/core/jaxl_loop.php';
+
+class JAXLSocketServer {
+
+ public $fd = null;
+
+ private $clients = array();
+ private $recv_chunk_size = 1024;
+ private $send_chunk_size = 8092;
+ private $accept_cb = null;
+ private $request_cb = null;
+ private $blocking = false;
+ private $backlog = 200;
+
+ public function __construct($path, $accept_cb, $request_cb) {
+ $this->accept_cb = $accept_cb;
+ $this->request_cb = $request_cb;
+
+ $ctx = stream_context_create(array('socket'=>array('backlog'=>$this->backlog)));
+ if(($this->fd = @stream_socket_server($path, $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctx)) !== false) {
+ if(@stream_set_blocking($this->fd, $this->blocking)) {
+ JAXLLoop::watch($this->fd, array(
+ 'read' => array(&$this, 'on_server_accept_ready')
+ ));
+ _info("socket ready to accept on path ".$path);
+ }
+ else {
+ _error("unable to set non block flag");
+ }
+ }
+ else {
+ _error("unable to establish socket server, errno: ".$errno.", errstr: ".$errstr);
+ }
+ }
+
+ public function __destruct() {
+ _info("shutting down socket server");
+ }
+
+ public function read($client_id) {
+ //_debug("reactivating read on client sock");
+ $this->add_read_cb($client_id);
+ }
+
+ public function send($client_id, $data) {
+ $this->clients[$client_id]['obuffer'] .= $data;
+ $this->add_write_cb($client_id);
+ }
+
+ public function close($client_id) {
+ $this->clients[$client_id]['close'] = true;
+ $this->add_write_cb($client_id);
+ }
+
+ public function on_server_accept_ready($server) {
+ //_debug("got server accept");
+ $client = @stream_socket_accept($server, 0, $addr);
+ if(!$client) {
+ _error("unable to accept new client conn");
+ return;
+ }
+
+ if(@stream_set_blocking($client, $this->blocking)) {
+ $client_id = (int) $client;
+ $this->clients[$client_id] = array(
+ 'fd' => $client,
+ 'ibuffer' => '',
+ 'obuffer' => '',
+ 'addr' => trim($addr),
+ 'close' => false,
+ 'closed' => false,
+ 'reading' => false,
+ 'writing' => false
+ );
+
+ _debug("accepted connection from client#".$client_id.", addr:".$addr);
+
+ // if accept callback is registered
+ // callback and let user land take further control of what to do
+ if($this->accept_cb) {
+ call_user_func($this->accept_cb, $client_id, $this->clients[$client_id]['addr']);
+ }
+ // if no accept callback is registered
+ // close the accepted connection
+ else {
+ @fclose($client);
+ $this->clients[$client_id]['closed'] = true;
+ unset($this->clients[$client_id]);
+ }
+ }
+ else {
+ _error("unable to set non block flag");
+ }
+ }
+
+ public function on_client_read_ready($client) {
+ // deactive socket for read
+ $client_id = (int) $client;
+ //_debug("client#$client_id is read ready");
+ $this->del_read_cb($client_id);
+
+ $raw = fread($client, $this->recv_chunk_size);
+ $bytes = strlen($raw);
+
+ _debug("recv $bytes bytes from client#$client_id");
+ //_debug($raw);
+
+ if($bytes === 0) {
+ $meta = stream_get_meta_data($client);
+ if($meta['eof'] === TRUE) {
+ _debug("socket eof client#".$client_id.", closing");
+ $this->del_read_cb($client_id);
+
+ @fclose($client);
+ unset($this->clients[$client_id]);
+ return;
+ }
+ }
+
+ $total = $this->clients[$client_id]['ibuffer'] . $raw;
+ if($this->request_cb)
+ call_user_func($this->request_cb, $client_id, $total);
+ $this->clients[$client_id]['ibuffer'] = '';
+ }
+
+ public function on_client_write_ready($client) {
+ $client_id = (int) $client;
+ _debug("client#$client_id is write ready");
+
+ try {
+ // send in chunks
+ $total = $this->clients[$client_id]['obuffer'];
+ $written = @fwrite($client, substr($total, 0, $this->send_chunk_size));
+
+ if($written === false) {
+ // fwrite failed
+ _warning("====> fwrite failed");
+ $this->clients[$client_id]['obuffer'] = $total;
+ }
+ else if($written == strlen($total) || $written == $this->send_chunk_size) {
+ // full chunk written
+ //_debug("full chunk written");
+ $this->clients[$client_id]['obuffer'] = substr($total, $this->send_chunk_size);
+ }
+ else {
+ // partial chunk written
+ //_debug("partial chunk $written written");
+ $this->clients[$client_id]['obuffer'] = substr($total, $written);
+ }
+
+ // if no more stuff to write, remove write handler
+ if(strlen($this->clients[$client_id]['obuffer']) === 0) {
+ $this->del_write_cb($client_id);
+
+ // if scheduled for close and not closed do it and clean up
+ if($this->clients[$client_id]['close'] && !$this->clients[$client_id]['closed']) {
+ @fclose($client);
+ $this->clients[$client_id]['closed'] = true;
+ unset($this->clients[$client_id]);
+
+ _debug("closed client#".$client_id);
+ }
+ }
+ }
+ catch(JAXLException $e) {
+ _debug("====> got fwrite exception");
+ }
+ }
+
+ //
+ // client sock event register utils
+ //
+
+ protected function add_read_cb($client_id) {
+ if($this->clients[$client_id]['reading'])
+ return;
+
+ JAXLLoop::watch($this->clients[$client_id]['fd'], array(
+ 'read' => array(&$this, 'on_client_read_ready')
+ ));
+
+ $this->clients[$client_id]['reading'] = true;
+ }
+
+ protected function add_write_cb($client_id) {
+ if($this->clients[$client_id]['writing'])
+ return;
+
+ JAXLLoop::watch($this->clients[$client_id]['fd'], array(
+ 'write' => array(&$this, 'on_client_write_ready')
+ ));
+
+ $this->clients[$client_id]['writing'] = true;
+ }
+
+ protected function del_read_cb($client_id) {
+ if(!$this->clients[$client_id]['reading'])
+ return;
+
+ JAXLLoop::unwatch($this->clients[$client_id]['fd'], array(
+ 'read' => true
+ ));
+
+ $this->clients[$client_id]['reading'] = false;
+ }
+
+ protected function del_write_cb($client_id) {
+ if(!$this->clients[$client_id]['writing'])
+ return;
+
+ JAXLLoop::unwatch($this->clients[$client_id]['fd'], array(
+ 'write' => true
+ ));
+
+ $this->clients[$client_id]['writing'] = false;
+ }
+
+}
+
+?>
Index: externals/JAXL/core/jaxl_util.php
===================================================================
--- /dev/null
+++ externals/JAXL/core/jaxl_util.php
@@ -0,0 +1,67 @@
+<?php
+/**
+* Jaxl (Jabber XMPP Library)
+*
+* Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+*
+*/
+
+/**
+ *
+ * @author abhinavsingh
+ *
+ */
+class JAXLUtil {
+
+ public static function get_nonce($binary=true) {
+ $nce = '';
+ mt_srand((double) microtime()*10000000);
+ for($i=0; $i<32; $i++) $nce .= chr(mt_rand(0, 255));
+ return $binary ? $nce : base64_encode($nce);
+ }
+
+ public static function get_dns_srv($domain) {
+ $rec = dns_get_record("_xmpp-client._tcp.".$domain, DNS_SRV);
+ if(is_array($rec)) {
+ if(sizeof($rec) == 0) return array($domain, 5222);
+ if(sizeof($rec) > 0) return array($rec[0]['target'], $rec[0]['port']);
+ }
+ }
+
+ public static function pbkdf2($data, $secret, $iteration, $dkLen=32, $algo='sha1') {
+ return '';
+ }
+
+}
+
+?>
Index: externals/JAXL/core/jaxl_xml.php
===================================================================
--- /dev/null
+++ externals/JAXL/core/jaxl_xml.php
@@ -0,0 +1,199 @@
+<?php
+/**
+* Jaxl (Jabber XMPP Library)
+*
+* Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+*
+*/
+
+/**
+ *
+ * Details: http://abhinavsingh.com/blog/2012/09/jaxlxml-strophe-style-xml-builder-working-with-jaxl-a-networking-library-in-php-part-2/
+ * Doc: http://jaxl.readthedocs.org/en/latest/users/xml_objects.html#jaxlxml
+ *
+ * @author abhinavsingh
+ *
+ */
+class JAXLXml {
+
+ public $name;
+ public $ns = null;
+ public $attrs = array();
+ public $text = null;
+
+ public $childrens = array();
+ public $parent = null;
+ public $rover = null;
+
+ public function __construct() {
+ $argv = func_get_args();
+ $argc = sizeof($argv);
+
+ $this->name = $argv[0];
+
+ switch($argc) {
+ case 4:
+ $this->ns = $argv[1];
+ $this->attrs = $argv[2];
+ $this->text = $argv[3];
+ break;
+ case 3:
+ if(is_array($argv[1])) {
+ $this->attrs = $argv[1];
+ $this->text = $argv[2];
+ }
+ else {
+ $this->ns = $argv[1];
+ if(is_array($argv[2])) {
+ $this->attrs = $argv[2];
+ }
+ else {
+ $this->text = $argv[2];
+ }
+ }
+ break;
+ case 2:
+ if(is_array($argv[1])) {
+ $this->attrs = $argv[1];
+ }
+ else {
+ $this->ns = $argv[1];
+ }
+ break;
+ default:
+ break;
+ }
+
+ $this->rover = &$this;
+ }
+
+ public function __destruct() {
+
+ }
+
+ public function attrs($attrs) {
+ $this->rover->attrs = array_merge($this->rover->attrs, $attrs);
+ return $this;
+ }
+
+ public function match_attrs($attrs) {
+ $matches = true;
+ foreach($attrs as $k=>$v) {
+ if($this->attrs[$k] !== $v) {
+ $matches = false;
+ break;
+ }
+ }
+ return $matches;
+ }
+
+ public function t($text, $append=FALSE) {
+ if(!$append) {
+ $this->rover->text = $text;
+ }
+ else {
+ if($this->rover->text === null)
+ $this->rover->text = '';
+ $this->rover->text .= $text;
+ }
+ return $this;
+ }
+
+ public function c($name, $ns=null, $attrs=array(), $text=null) {
+ $node = new JAXLXml($name, $ns, $attrs, $text);
+ $node->parent = &$this->rover;
+ $this->rover->childrens[] = &$node;
+ $this->rover = &$node;
+ return $this;
+ }
+
+ public function cnode($node) {
+ $node->parent = &$this->rover;
+ $this->rover->childrens[] = &$node;
+ $this->rover = &$node;
+ return $this;
+ }
+
+ public function up() {
+ if($this->rover->parent) $this->rover = &$this->rover->parent;
+ return $this;
+ }
+
+ public function top() {
+ $this->rover = &$this;
+ return $this;
+ }
+
+ public function exists($name, $ns=null, $attrs=array()) {
+ foreach($this->childrens as $child) {
+ if($ns) {
+ if($child->name == $name && $child->ns == $ns && $child->match_attrs($attrs))
+ return $child;
+ }
+ else if($child->name == $name && $child->match_attrs($attrs)) {
+ return $child;
+ }
+ }
+ return false;
+ }
+
+ public function update($name, $ns=null, $attrs=array(), $text=null) {
+ foreach($this->childrens as $k=>$child) {
+ if($child->name == $name) {
+ $child->ns = $ns;
+ $child->attrs($attrs);
+ $child->text = $text;
+ $this->childrens[$k] = $child;
+ break;
+ }
+ }
+ }
+
+ public function to_string($parent_ns=null) {
+ $xml = '';
+
+ $xml .= '<'.$this->name;
+ if($this->ns && $this->ns != $parent_ns) $xml .= ' xmlns="'.$this->ns.'"';
+ foreach($this->attrs as $k=>$v) if(!is_null($v) && $v !== FALSE) $xml .= ' '.$k.'="'.htmlspecialchars($v).'"';
+ $xml .= '>';
+
+ foreach($this->childrens as $child) $xml .= $child->to_string($this->ns);
+
+ if($this->text) $xml .= htmlspecialchars($this->text);
+ $xml .= '</'.$this->name.'>';
+ return $xml;
+ }
+
+}
+
+?>
Index: externals/JAXL/core/jaxl_xml_stream.php
===================================================================
--- /dev/null
+++ externals/JAXL/core/jaxl_xml_stream.php
@@ -0,0 +1,191 @@
+<?php
+/**
+* Jaxl (Jabber XMPP Library)
+*
+* Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+*
+*/
+
+/**
+ *
+ * Enter description here ...
+ * @author abhinavsingh
+ *
+ */
+class JAXLXmlStream {
+
+ private $delimiter = '\\';
+ private $ns;
+ private $parser;
+ private $stanza;
+ private $depth = -1;
+
+ private $start_cb;
+ private $stanza_cb;
+ private $end_cb;
+
+ public function __construct() {
+ $this->init_parser();
+ }
+
+ private function init_parser() {
+ $this->depth = -1;
+ $this->parser = xml_parser_create_ns("UTF-8", $this->delimiter);
+
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
+ xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, 1);
+ xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
+
+ xml_set_character_data_handler($this->parser, array(&$this, "handle_character"));
+ xml_set_element_handler($this->parser, array(&$this, "handle_start_tag"), array(&$this, "handle_end_tag"));
+ }
+
+ public function __destruct() {
+ //_debug("cleaning up xml parser...");
+ @xml_parser_free($this->parser);
+ }
+
+ public function reset_parser() {
+ $this->parse_final(null);
+ @xml_parser_free($this->parser);
+ $this->parser = null;
+ $this->init_parser();
+ }
+
+ public function set_callback($start_cb, $end_cb, $stanza_cb) {
+ $this->start_cb = $start_cb;
+ $this->end_cb = $end_cb;
+ $this->stanza_cb = $stanza_cb;
+ }
+
+ public function parse($str) {
+ xml_parse($this->parser, $str, false);
+ }
+
+ public function parse_final($str) {
+ xml_parse($this->parser, $str, true);
+ }
+
+ protected function handle_start_tag($parser, $name, $attrs) {
+ $name = $this->explode($name);
+ //echo "start of tag ".$name[1]." with ns ".$name[0].PHP_EOL;
+
+ // replace ns with prefix
+ foreach($attrs as $key=>$v) {
+ $k = $this->explode($key);
+
+ // no ns specified
+ if($k[0] == null) {
+ $attrs[$k[1]] = $v;
+ }
+ // xml ns
+ else if($k[0] == NS_XML) {
+ unset($attrs[$key]);
+ $attrs['xml:'.$k[1]] = $v;
+ }
+ else {
+ _error("==================> unhandled ns prefix on attribute");
+ // remove attribute else will cause error with bad stanza format
+ // report to developer if above error message is ever encountered
+ unset($attrs[$key]);
+ }
+ }
+
+ if($this->depth <= 0) {
+ $this->depth = 0;
+ $this->ns = $name[1];
+
+ if($this->start_cb) {
+ $stanza = new JAXLXml($name[1], $name[0], $attrs);
+ call_user_func($this->start_cb, $stanza);
+ }
+ }
+ else {
+ if(!$this->stanza) {
+ $stanza = new JAXLXml($name[1], $name[0], $attrs);
+ $this->stanza = &$stanza;
+ }
+ else {
+ $this->stanza->c($name[1], $name[0], $attrs);
+ }
+ }
+
+ ++$this->depth;
+ }
+
+ protected function handle_end_tag($parser, $name) {
+ $name = explode($this->delimiter, $name);
+ $name = sizeof($name) == 1 ? array('', $name[0]) : $name;
+
+ //echo "depth ".$this->depth.", $name[1] tag ended".PHP_EOL.PHP_EOL;
+
+ if($this->depth == 1) {
+ if($this->end_cb) {
+ $stanza = new JAXLXml($name[1], $this->ns);
+ call_user_func($this->end_cb, $stanza);
+ }
+ }
+ else if($this->depth > 1) {
+ if($this->stanza) $this->stanza->up();
+
+ if($this->depth == 2) {
+ if($this->stanza_cb) {
+ call_user_func($this->stanza_cb, $this->stanza);
+ $this->stanza = null;
+ }
+ }
+ }
+
+ --$this->depth;
+ }
+
+ protected function handle_character($parser, $data) {
+ //echo "depth ".$this->depth.", character ".$data." for stanza ".$this->stanza->name.PHP_EOL;
+ if($this->stanza) {
+ $this->stanza->t(htmlentities($data, ENT_COMPAT, "UTF-8"), TRUE);
+ }
+ }
+
+ private function implode($data) {
+ return implode($this->delimiter, $data);
+ }
+
+ private function explode($data) {
+ $data = explode($this->delimiter, $data);
+ $data = sizeof($data) == 1 ? array(null, $data[0]) : $data;
+ return $data;
+ }
+
+}
+
+?>
Index: externals/JAXL/docs/Makefile
===================================================================
--- /dev/null
+++ externals/JAXL/docs/Makefile
@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Jaxl.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Jaxl.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/Jaxl"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Jaxl"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
Index: externals/JAXL/docs/conf.py
===================================================================
--- /dev/null
+++ externals/JAXL/docs/conf.py
@@ -0,0 +1,242 @@
+# -*- coding: utf-8 -*-
+#
+# Jaxl documentation build configuration file, created by
+# sphinx-quickstart on Sun Jul 15 03:08:42 2012.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.pngmath', 'sphinx.ext.viewcode']
+# , 'sphinxcontrib.phpdomain'
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Jaxl'
+copyright = u'2012, Abhinav Singh'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '3.0'
+# The full version, including alpha/beta/rc tags.
+release = '3.0.1'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+show_authors = True
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'pastie'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'nature'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Jaxldoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'Jaxl.tex', u'Jaxl Documentation',
+ u'Abhinav Singh', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'jaxl', u'Jaxl Documentation',
+ [u'Abhinav Singh'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('index', 'Jaxl', u'Jaxl Documentation',
+ u'Abhinav Singh', 'Jaxl', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
Index: externals/JAXL/docs/developers/core_stack.rst
===================================================================
--- /dev/null
+++ externals/JAXL/docs/developers/core_stack.rst
@@ -0,0 +1,34 @@
+Core Stack
+==========
+That has a paragraph about a main subject and is set when the '='
+is at least the same length of the title itself.
+
+Main Event Loop
+----------------
+
+Finite State Machine
+--------------------
+
+TCP/IP Socket Client
+--------------------
+
+TCP/IP Socket Server
+--------------------
+
+Event Emitter
+-------------
+
+Streaming XML Parser
+--------------------
+
+XML Objects
+-----------
+
+Timed Job Dispatcher
+--------------------
+
+Inter-Process Communication (IPC)
+---------------------------------
+
+Remote Shell & Debug Console
+-----------------------------
\ No newline at end of file
Index: externals/JAXL/docs/developers/http_stack.rst
===================================================================
--- /dev/null
+++ externals/JAXL/docs/developers/http_stack.rst
@@ -0,0 +1,14 @@
+HTTP Stack
+==========
+
+Request Object
+--------------
+
+Bit by Bit Pushing
+------------------
+
+Multipart Form Data
+-------------------
+
+Chunked Encoding
+----------------
Index: externals/JAXL/docs/developers/introduction.rst
===================================================================
--- /dev/null
+++ externals/JAXL/docs/developers/introduction.rst
@@ -0,0 +1,10 @@
+.. _developer-introduction:
+
+Introduction
+============
+
+Design Philosophy
+-----------------
+
+Contributing to the library
+---------------------------
\ No newline at end of file
Index: externals/JAXL/docs/developers/xmpp_stack.rst
===================================================================
--- /dev/null
+++ externals/JAXL/docs/developers/xmpp_stack.rst
@@ -0,0 +1,8 @@
+XMPP Stack
+==========
+
+XMPP Streams
+------------
+
+XMPP Stanza
+-----------
\ No newline at end of file
Index: externals/JAXL/docs/index.rst
===================================================================
--- /dev/null
+++ externals/JAXL/docs/index.rst
@@ -0,0 +1,51 @@
+Welcome to Jaxl's documentation!
+================================
+Jaxl v3.x is a successor of v2.x (and is NOT backward compatible),
+carrying a lot of code from v2.x while throwing away the ugly parts.
+A lot of components have been re-written keeping in mind the feedback from
+the developer community over the last 4 years. Also Jaxl now shares a few
+philosophies from my experience with erlang and python languages.
+
+Jaxl is an asynchronous, non-blocking I/O, event based PHP library
+for writing custom TCP/IP client and server implementations.
+From it's previous versions, library inherits a full blown stable support
+for XMPP protocol stack. In v3.0, support for HTTP protocol stack was
+also added.
+
+At the heart of every protocol stack sits a Core stack. It contains all the
+building blocks for everything that we aim to do with Jaxl library. Both
+XMPP and HTTP protocol stacks are written on top of the Core stack. Infact
+the source code of protocol implementations knows nothing about the
+standard (inbuilt) PHP socket and stream methods.
+
+Users Guide
+------------
+
+.. toctree::
+ :maxdepth: 2
+
+ users/getting_started
+ users/jaxl_instance
+ users/jaxlctl
+ users/logging
+ users/cron_jobs
+
+XMPP Users Guide:
+-----------------
+
+.. toctree::
+ :maxdepth: 2
+
+ users/xmpp_examples
+ users/xml_objects
+ users/xmpp_extensions
+
+HTTP Users Guide:
+-----------------
+
+.. toctree::
+ :maxdepth: 2
+
+ users/http_examples
+ users/http_extensions
+
\ No newline at end of file
Index: externals/JAXL/docs/users/cron_jobs.rst
===================================================================
--- /dev/null
+++ externals/JAXL/docs/users/cron_jobs.rst
@@ -0,0 +1,61 @@
+Cron Jobs
+=========
+``JAXLClock`` maintains a global clock which is updated after every iteration of the :ref:`main select loop <jaxl-instance>`.
+During the clock tick phase, ``JAXLClock`` also dispatches any scheduled cron jobs.
+
+Lets try some cron job scheduling using Jaxl interactive shell:
+
+ >>> ./jaxlctl shell
+ jaxl 1>
+ jaxl 1> function do_job($params) {
+ ....... echo "cron job called";
+ ....... }
+ jaxl 2>
+ jaxl 2> $ref = JAXLLoop::$clock->call_fun_after(
+ ....... 4000,
+ ....... 'do_job',
+ ....... 'some_parameters'
+ ....... );
+ jaxl 3> echo $ref;
+ 1
+ jaxl 4>
+ cron job called
+ jaxl 5> quit
+ >>>
+
+We just saw a live example of a cron job. Using ``JAXLClock::call_fun_after/3`` we were able to
+call our ``do_job`` function after 4000 microseconds.
+
+.. note::
+
+ Since cron jobs are called inside main select loop, do not execute long running cron jobs using
+ ``JAXLClock`` else the main select loop will not be able to detect any new activity on
+ watched file descriptors. In short, these cron job callbacks are blocking.
+
+ In future, cron jobs might get executed in a seperate process space, overcoming the above limitation.
+ Until then know what your jobs are doing and for how long or execute them in a seperate process space
+ yourself. You have been warned !!!
+
+one time jobs
+-------------
+``call_fun_after($time, $callback, $args)``
+
+schedules $callback with $args after $time microseconds
+
+periodic jobs
+-------------
+``call_fun_periodic($time, $callback, $args)``
+
+schedules periodic $callback with $args after $time microseconds
+
+cancel a job
+------------
+``cancel_fun_call($ref)``
+
+cancels a previously scheduled $callback
+
+detecting bottlenecks
+---------------------
+``tc($callback, $args)``
+
+calculate execution time of a $callback with $args
Index: externals/JAXL/docs/users/getting_started.rst
===================================================================
--- /dev/null
+++ externals/JAXL/docs/users/getting_started.rst
@@ -0,0 +1,161 @@
+Getting Started
+===============
+
+Requirements
+------------
+No external component or library is required.
+You simply need a standard PHP installation to work with Jaxl.
+
+Library has been developed and tested extensively on
+linux operating systems. But there is no reason why it should
+not work on other OS. File an `issue <https://github.com/abhinavsingh/JAXL/issues/new>`_ if you face any glitches.
+
+Download & Install
+------------------
+Download a stable tagged v3.x release from `https://github.com/abhinavsingh/JAXL/tags <https://github.com/abhinavsingh/JAXL/tags>`_
+
+You can also checkout git branch and switch to a tag of your choice:
+
+ >>> git clone git://github.com/abhinavsingh/JAXL.git
+ >>> cd JAXL/
+ >>> git tag -l
+ >>> git checkout some-tag-name
+
+To install Jaxl library globally, simply append path of the downloaded ``JAXL`` folder
+to ``include_path`` directive inside your ``php.ini``. This will allow us to use Jaxl
+library simply by doing:
+
+``require 'jaxl.php';``
+
+Alternately, if you don't want to edit ``php.ini`` or in case you don't have
+access to the ini file, simply use:
+
+``require '/full/path/to/JAXL/jaxl.php';``
+
+to start using Jaxl library.
+
+Library Structure
+-----------------
+Jaxl library comprises of following packages:
+
+ * ``jaxl-core``
+
+ contains generic networking and eventing components
+
+ * ``jaxl-xmpp``
+
+ contains xmpp rfc implementation
+
+ * ``jaxl-xmpp-xep``
+
+ contains various xmpp xep implementation
+
+ * ``jaxl-http``
+
+ contains http rfc implementation
+
+ * ``jaxl-docs``
+
+ this documentation comes from this package
+
+ * ``jaxl-tests``
+
+ test suites for all the above packages
+
+Inside Jaxl everything that you will interact with will be an object which
+will emit events and callbacks which we will be able to catch in our applications
+for custom processing and routing. Listed below are a few main objects:
+
+ #. Core Stack
+
+ * ``JAXLLoop``
+
+ main select loop
+
+ * ``JAXLClock``
+
+ timed job/callback dispatcher
+
+ * ``JAXLEvent``
+
+ event registry and emitter
+
+ * ``JAXLFsm``
+
+ generic finite state machine
+
+ * ``JAXLSocketClient``
+
+ generic tcp/udp client
+
+ * ``JAXLSocketServer``
+
+ generic tcp/udp server
+
+ * ``JAXLXmlStream``
+
+ streaming XML parser
+
+ * ``JAXLXml``
+
+ custom XML object implementation
+
+ * ``JAXLLogger``
+
+ logging facility
+
+ #. XMPP Stack
+
+ * ``XMPPStream``
+
+ base xmpp rfc implementation
+
+ * ``XMPPStanza``
+
+ provides easy access patterns over xmpp stanza (wraps ``JAXLXml``)
+
+ * ``XMPPIq``
+
+ xmpp iq stanza object (extends ``XMPPStanza``)
+
+ * ``XMPPMsg``
+
+ xmpp msg stanza object (extends ``XMPPStanza``)
+
+ * ``XMPPPres``
+
+ xmpp pres stanza object (extends ``XMPPStanza``)
+
+ * ``XMPPXep``
+
+ abstract xmpp extension (extended by XEP implementations)
+
+ * ``XMPPJid``
+
+ xmpp jid object
+
+ #. HTTP Stack
+
+ * ``HTTPServer``
+
+ http server implementation
+
+ * ``HTTPClient``
+
+ http client implementation
+
+ * ``HTTPRequest``
+
+ http request object
+
+ * ``HTTPResponse``
+
+ http response object
+
+Questions, Bugs and Issues
+--------------------------
+If you have any questions kindly post them on `google groups <https://groups.google.com/forum/#!forum/jaxl>`_. Groups are the quickest
+way to get an answer to your questions which is actively monitored by core developers.
+
+If you are facing a bug or issue, please report that it on `github issue tracker <https://github.com/abhinavsingh/JAXL/issues/new>`_.
+You can even :ref:`contribute to the library <developer-introduction>` if you already have fixed the bug.
Index: externals/JAXL/docs/users/http_examples.rst
===================================================================
--- /dev/null
+++ externals/JAXL/docs/users/http_examples.rst
@@ -0,0 +1,102 @@
+HTTP Examples
+=============
+
+Writing HTTP Server
+-------------------
+Intialize an ``HTTPServer`` instance
+
+.. code-block:: ruby
+
+ require_once 'jaxl.php';
+ require_once JAXL_CWD.'/http/http_server.php';
+ $http = new HTTPServer();
+
+By default ``HTTPServer`` will listen on port 9699. You can pass a port number as first parameter to change this.
+
+Define a callback method that will accept all incoming ``HTTPRequest`` objects
+
+.. code-block:: ruby
+
+ function on_request($request) {
+ if($request->method == 'GET') {
+ $body = json_encode($request);
+ $request->ok($body, array('Content-Type'=>'application:json'));
+ }
+ else {
+ $request->not_found();
+ }
+ }
+
+``on_request`` callback method will receive a ``HTTPRequest`` object instance.
+For this example, we will simply echo back json encoded ``$request`` object for
+every http GET request.
+
+Start http server:
+
+.. code-block:: ruby
+
+ $http->start('on_request');
+
+We pass ``on_request`` method as first parameter to ``HTTPServer::start/1``.
+If nothing is passed, requests will fail with a default 404 not found error message
+
+Writing REST API Server
+-----------------------
+Intialize an ``HTTPServer`` instance
+
+.. code-block:: ruby
+
+ require_once 'jaxl.php';
+ require_once JAXL_CWD.'/http/http_server.php';
+ $http = new HTTPServer();
+
+By default ``HTTPServer`` will listen on port 9699. You can pass a port number as first parameter to change this.
+
+Define our REST resources callback methods:
+
+.. code-block:: ruby
+
+ function index($request) {
+ $request->send_response(
+ 200, array('Content-Type'=>'text/html'),
+ '<html><head/><body><h1>Jaxl Http Server</h1><a href="/upload">upload a file</a></body></html>'
+ );
+ $request->close();
+ }
+
+ function upload($request) {
+ if($request->method == 'GET') {
+ $request->send_response(
+ 200, array('Content-Type'=>'text/html'),
+ '<html><head/><body><h1>Jaxl Http Server</h1><form enctype="multipart/form-data" method="POST" action=""><input type="file" name="file"/><input type="submit" value="upload"/></form></body></html>'
+ );
+ }
+ else if($request->method == 'POST') {
+ if($request->body === null && $request->expect) {
+ $request->recv_body();
+ }
+ else {
+ // got upload body, save it
+ _debug("file upload complete, got ".strlen($request->body)." bytes of data");
+ $request->close();
+ }
+ }
+ }
+
+Next we need to register dispatch rules for our callbacks above:
+
+.. code-block:: ruby
+
+ $index = array('index', '^/$');
+ $upload = array('upload', '^/upload', array('GET', 'POST'));
+ $rules = array($index, $upload);
+ $http->dispatch($rules);
+
+Start REST api server:
+
+.. code-block:: ruby
+
+ $http->start();
+
+Make an HTTP request
+--------------------
Index: externals/JAXL/docs/users/http_extensions.rst
===================================================================
--- /dev/null
+++ externals/JAXL/docs/users/http_extensions.rst
@@ -0,0 +1,49 @@
+HTTP Extensions
+===============
+
+Dispatch Rules
+--------------
+Dispatch rules are convinient way of redirecting callback for a specific request pattern to a custom
+methods inside your application. A dispatch rule consists of following 4 match information:
+
+ * ``$callback``
+
+ reference to a method that will be callback'd when a matching request is received
+
+ * ``$pattern``
+
+ a regular expression for matching on url path
+
+ * ``$methods``
+
+ (optional) if not specified rule will match for all HTTP Methods.
+ if specified, must be an array of HTTP Method in uppercase.
+
+ * ``$extra``
+
+ (reserved) this is for future where we will allow matching on
+ headers, session, cookies etc.
+
+Below are a few examples of dispatch rules:
+
+.. code-block:: ruby
+
+ $index = array('serve_index_page', '^/');
+ $upload_form = array('serve_upload_form', '^/upload', array('GET'));
+ $upload_handler = array('handle_upload_form', '^/upload', array('POST'));
+
+Some REST CRUD dispatch rules:
+
+.. code-block:: ruby
+
+ $event_create = array('create_event', '^/event/create/$', array('PUT'));
+ $event_read = array('read_event', '^/event/(?P<pk>\d+)/$', array('GET', 'HEAD'));
+ $event_update = array('update_event', '^/event/(?P<pk>\d+)/$', array('POST'));
+ $event_delete = array('delete_event', '^/event/(?P<pk>\d+)/$', array('DELETE'));
+
+Finally don't forget to active these dispatch rules by doing:
+
+.. code-block:: ruby
+
+ $rules = array($index, $upload_form, $upload_handler, $event_create, $event_read, $event_update, $event_delete);
+ $http->dispatch($rules);
Index: externals/JAXL/docs/users/jaxl_instance.rst
===================================================================
--- /dev/null
+++ externals/JAXL/docs/users/jaxl_instance.rst
@@ -0,0 +1,166 @@
+.. _jaxl-instance:
+
+JAXL Instance
+=============
+``JAXL`` instance configure/manage other :ref:`sub-packages <jaxl-instance>`.
+It provides an event based callback methodology on various underlying object. Whenever required
+``JAXL`` instance will itself perform the configured defaults.
+
+Constructor options
+-------------------
+
+ #. ``jid``
+ #. ``pass``
+ #. ``resource``
+
+ If not passed Jaxl will use a random resource value
+
+ #. ``auth_type``
+
+ DIGEST-MD5, PLAIN (default), CRAM-MD5, ANONYMOUS, X-FACEBOOK-PLATFORM
+
+ #. ``host``
+ #. ``port``
+ #. ``bosh_url``
+ #. ``log_path``
+ #. ``log_level``
+
+ ``JAXL_ERROR``, ``JAXL_WARNING``, ``JAXL_NOTICE``, ``JAXL_INFO`` (default), ``JAXL_DEBUG``
+
+ #. ``fb_access_token``
+
+ required when using X-FACEBOOK-PLATFORM auth mechanism
+
+ #. ``fb_app_key``
+
+ required when using X-FACEBOOK-PLATFORM auth mechanism
+
+ #. ``force_tls``
+ #. ``stream_context``
+ #. ``priv_dir``
+
+ Jaxl creates 4 directories names ``log``, ``tmp``, ``run`` and ``sock`` inside a private directory
+ which defaults to ``JAXL_CWD.'/.jaxl'``. If this option is passed, it will overwrite default private
+ directory.
+
+ .. note::
+
+ Jaxl currently doesn't check upon the permissions of passed ``priv_dir``. Make sure Jaxl library
+ have sufficient permissions to create above mentioned directories.
+
+Available Event Callbacks
+-------------------------
+
+Following ``$ev`` are available on ``JAXL`` lifecycle for registering callbacks:
+
+ #. ``on_connect``
+
+ ``JAXL`` instance has connected successfully
+
+ #. ``on_connect_error``
+
+ ``JAXL`` instance failed to connect
+
+ #. ``on_stream_start``
+
+ ``JAXL`` instance has successfully initiated XMPP stream with the jabber server
+
+ #. ``on_stream_features``
+
+ ``JAXL`` instance has received supported stream features
+
+ #. ``on_auth_success``
+
+ authentication successful
+
+ #. ``on_auth_failure``
+
+ authentication failed
+
+ #. ``on_presence_stanza``
+
+ ``JAXL`` instance has received a presence stanza
+
+ #. ``on_{$type}_message``
+
+ ``JAXL`` instance has received a message stanza. ``$type`` can be ``chat``, ``groupchat``, ``headline``, ``normal``, ``error``
+
+ #. ``on_stanza_id_{$id}``
+
+ Useful when dealing with iq stanza. This event is fired when ``JAXL`` instance has received response to a particular
+ xmpp stanza id
+
+ #. ``on_{$name}_stanza``
+
+ Useful when dealing with custom xmpp stanza
+
+ #. ``on_disconnect``
+
+ ``JAXL`` instance has disconnected from the jabber server
+
+Available Methods
+-----------------
+
+Following methods are available on initialized ``JAXL`` instance object:
+
+ #. ``get_pid_file_path()``
+
+ returns path of ``JAXL`` instance pid file
+
+ #. ``get_sock_file_path()``
+
+ returns path to ``JAXL`` ipc unix socket domain
+
+ #. ``require_xep($xeps=array())``
+
+ autoload and initialize passed XEP's
+
+ #. ``add_cb($ev, $cb, $pri=1)``
+
+ add a callback to function ``$cb`` on event ``$ev``, returns a reference of added callback
+
+ #. ``del_cb($ref)``
+
+ delete previously registered event callback
+
+ #. ``set_status($status, $show, $priority)``
+
+ send a presence status stanza
+
+ #. ``send_chat_msg($to, $body, $thread=null, $subject=null)``
+
+ send a message stanza of type chat
+
+ #. ``get_vcard($jid=null, $cb=null)``
+
+ fetch vcard for bare ``$jid``, passed ``$cb`` will be called with received vcard stanza
+
+ #. ``get_roster($cb=null)``
+
+ fetch roster list of connected jabber client, passed ``$cb`` will be called with received roster stanza
+
+ #. ``start($opts=array())``
+
+ start configured ``JAXL`` instance, optionally accepts two options specified below:
+
+ #. ``--with-debug-shell``
+
+ start ``JAXL`` instance and enter an interactive console
+
+ #. ``--with-unix-sock``
+
+ start ``JAXL`` instance with support for IPC and remote debugging
+
+ #. ``send($stanza)``
+
+ send an instance of JAXLXml packet over connected socket
+
+ #. ``send_raw($data)``
+
+ send raw payload over connected socket
+
+ #. ``get_msg_pkt($attrs, $body=null, $thread=null, $subject=null, $payload=null)``
+
+ #. ``get_pres_pkt($attrs, $status=null, $show=null, $priority=null, $payload=null)``
+
+ #. ``get_iq_pkt($attrs, $payload)``
\ No newline at end of file
Index: externals/JAXL/docs/users/jaxlctl.rst
===================================================================
--- /dev/null
+++ externals/JAXL/docs/users/jaxlctl.rst
@@ -0,0 +1,50 @@
+./jaxlctl
+=========
+Usage: ``./jaxlctl command [options...]``
+
+``jaxlctl`` is a control script that can be seen as a useful tool for:
+
+ * debugging daemons running in the background
+ * customize daemons on the fly
+ * monitoring daemons
+ * as a playground for learning XMPP/HTTP and Jaxl library itself
+
+Type ``./jaxlctl help`` to see list of available commands.
+
+.. note::
+
+ Various commands are still experimental. Know what you are doing before
+ using them in production. You have been warned !!!
+
+Interactive Shell
+------------------
+
+ >>> ./jaxlctl shell
+ jaxl 1>
+ jaxl 1> // create a test message object
+ jaxl 1> $msg = new XMPPMsg(array('to'=>'friend@gmail.com'), 'Hello World!');
+ jaxl 2>
+ jaxl 2> // object to string conversion
+ jaxl 2> print_r($msg->to_string());
+ <message to="friend@gmail.com"><body>Hello World!</body></message>
+ jaxl 3>
+
+Debug Running Instances
+------------------------
+
+ >>> ./jaxlctl attach XXXXX
+ jaxl 1>
+ jaxl 1> // create a message to be sent
+ jaxl 1> $msg = new XMPPMsg(array('to'=>'friend@gmail.com'), 'Hello World!');
+ jaxl 2>
+ jaxl 2> // this client is from the echo bot example
+ jaxl 2> global $client;
+ jaxl 3>
+ jaxl 3> // send the message packet
+ jaxl 3> $client->send($msg);
+ jaxl 4>
+ jaxl 4> // or we can directly do
+ jaxl 4> $client->send_chat_msg('friend@gmail.com', 'Hello World!');
+ jaxl 5>
+
+Where ``XXXXX`` is the pid of running ``JAXL`` instance.
Index: externals/JAXL/docs/users/logging.rst
===================================================================
--- /dev/null
+++ externals/JAXL/docs/users/logging.rst
@@ -0,0 +1,29 @@
+Logging Interface
+=================
+``JAXLLogger`` provides all the logging facilities that we will ever require.
+When logging to ``STDOUT`` it also colorizes the log message depending upon its severity level.
+When logging to a file it can also do periodic log rotation.
+
+log levels
+----------
+
+ * JAXL_ERROR (red)
+ * JAXL_WARNING (blue)
+ * JAXL_NOTICE (yellow)
+ * JAXL_INFO (green)
+ * JAXL_DEBUG (white)
+
+global logging methods
+----------------------
+Following global methods for logging are available:
+
+ * ``_error($msg)``
+ * ``_warning($msg)``
+ * ``_notice($msg)``
+ * ``_info($msg)``
+ * ``_debug($msg)``
+
+_colorize/2
+-----------
+All the above global logging methods internally use ``_colorize($msg, $verbosity)`` to output colored
+log message on the terminal.
\ No newline at end of file
Index: externals/JAXL/docs/users/xml_objects.rst
===================================================================
--- /dev/null
+++ externals/JAXL/docs/users/xml_objects.rst
@@ -0,0 +1,121 @@
+.. _xml-objects:
+
+Xml Objects
+===========
+Jaxl library works with custom XML implementation which is similar to
+inbuild PHP XML functions but is lightweight and easy to work with.
+
+JAXLXml
+-------
+``JAXLXml`` is the base XML object. Open up :ref:`Jaxl interactive shell <jaxl-instance>` and try some xml object creation/manipulation:
+
+ >>> ./jaxlctl shell
+ jaxl 1>
+ jaxl 1> $xml = new JAXLXml(
+ ....... 'dummy',
+ ....... 'dummy:packet',
+ ....... array('attr1'=>'friend@gmail.com', 'attr2'=>''),
+ ....... 'Hello World!'
+ ....... );
+ jaxl 2> echo $xml->to_string();
+ <dummy xmlns="dummy:packet" attr1="friend@gmail.com" attr2="">Hello World!</dummy>
+ jaxl 3>
+
+``JAXLXml`` constructor instance accepts following parameters:
+
+ * ``JAXLXml($name, $ns, $attrs, $text)``
+ * ``JAXLXml($name, $ns, $attrs)``
+ * ``JAXLXml($name, $ns, $text)``
+ * ``JAXLXml($name, $attrs, $text)``
+ * ``JAXLXml($name, $attrs)``
+ * ``JAXLXml($name, $ns)``
+ * ``JAXLXml($name)``
+
+``JAXLXml`` draws inspiration from StropheJS XML Builder class. Below are available methods
+for modifying and manipulating an ``JAXLXml`` object:
+
+ * ``t($text, $append=FALSE)``
+
+ update text of current rover
+
+ * ``c($name, $ns=null, $attrs=array(), $text=null)``
+
+ append a child node at current rover
+
+ * ``cnode($node)``
+
+ append a JAXLXml child node at current rover
+
+ * ``up()``
+
+ move rover to one step up the xml tree
+
+ * ``top()``
+
+ move rover back to top element in the xml tree
+
+ * ``exists($name, $ns=null, $attrs=array())``
+
+ checks if a child with $name exists, return child ``JAXLXml`` if found otherwise false. This function returns at first matching child.
+
+ * ``update($name, $ns=null, $attrs=array(), $text=null)``
+
+ update specified child element
+
+ * ``attrs($attrs)``
+
+ merge new attrs with attributes of current rover
+
+ * ``match_attrs($attrs)``
+
+ pass a kv pair of ``$attrs``, return bool if all passed keys matches their respective values in the xml packet
+
+ * ``to_string()``
+
+ get string representation of the object
+
+``JAXLXml`` maintains a rover which points to the current level down the XML tree where
+manipulation is performed.
+
+XMPPStanza
+----------
+In the world of XMPP where everything incoming and outgoing payload is an ``JAXLXml`` instance code can become nasty,
+developers can get lost in dirty XML manipulations spreaded all over the application code base and what not.
+XML structures are not only unreadable for humans but even for machine.
+
+While an instance of ``JAXLXml`` provide direct access to XML ``name``, ``ns`` and ``text``, it can become painful and
+time consuming when trying to retrieve or modify a particular ``attrs`` or ``childrens``. I was fed up of doing
+``getAttributeByName``, ``setAttributeByName``, ``getChild`` etc everytime i had to access common XMPP Stanza attributes.
+
+``XMPPStanza`` is a wrapper on top of ``JAXLXml`` objects. Preserving all the functionalities of base ``JAXLXml``
+instance it also provide direct access to most common XMPP Stanza attributes like ``to``, ``from``, ``id``, ``type`` etc.
+It also provides a framework for adding custom access patterns.
+
+``XMPPMsg``, ``XMPPPres`` and ``XMPPIq`` extends ``XMPPStanza`` and also add a few custom access patterns like
+``body``, ``thread``, ``subject``, ``status``, ``show`` etc.
+
+Here is a list of default access patterns:
+
+ #. ``name``
+ #. ``ns``
+ #. ``text``
+ #. ``attrs``
+ #. ``childrens``
+ #. ``to``
+ #. ``from``
+ #. ``id``
+ #. ``type``
+ #. ``to_node``
+ #. ``to_domain``
+ #. ``to_resource``
+ #. ``from_node``
+ #. ``from_domain``
+ #. ``from_resource``
+ #. ``status``
+ #. ``show``
+ #. ``priority``
+ #. ``body``
+ #. ``thread``
+ #. ``subject``
+
+
Index: externals/JAXL/docs/users/xmpp_examples.rst
===================================================================
--- /dev/null
+++ externals/JAXL/docs/users/xmpp_examples.rst
@@ -0,0 +1,120 @@
+XMPP Examples
+=============
+
+Echo Bot Client
+---------------
+include ``jaxl.php`` and initialize a new ``JAXL`` instance:
+
+.. code-block:: ruby
+
+ require 'jaxl.php';
+ $client = new JAXL(array(
+ 'jid' => 'user@domain.tld',
+ 'pass' => 'password'
+ ));
+
+We just initialized a new ``JAXL`` instance by passing our jabber client ``jid`` and ``pass``.
+
+View list of :ref:`available options <jaxl-instance>` that can be passed to ``JAXL`` constructor.
+
+Next we need to register callbacks on events of interest using ``JAXL::add_cb/2`` method as shown below:
+
+.. code-block:: ruby
+
+ $client->add_cb('on_auth_success', function() {
+ global $client;
+ $client->set_status("available!"); // set your status
+ $client->get_vcard(); // fetch your vcard
+ $client->get_roster(); // fetch your roster list
+ });
+
+ $client->add_cb('on_chat_message', function($msg) {
+ global $client;
+
+ // echo back
+ $msg->to = $msg->from;
+ $msg->from = $client->full_jid->to_string();
+ $client->send($msg);
+ });
+
+ $client->add_cb('on_disconnect', function() {
+ _debug("got on_disconnect cb");
+ });
+
+We just registered callbacks on ``on_auth_success``, ``on_chat_message`` and ``on_disconnect`` events
+that will occur inside our configured ``JAXL`` instance lifecycle.
+We also passed a method that will be called (with parameters if any) when the event has been detected.
+
+See list of :ref:`available event callbacks <jaxl-instance>` that we can hook to inside ``JAXL`` instance lifecycle.
+
+Received ``$msg`` parameter with ``on_chat_message`` event callback above, will be an instance of ``XMPPMsg`` which
+extends ``XMPPStanza`` class, that allows us easy to use access patterns to common XMPP stanza attributes like
+``to``, ``from``, ``type``, ``id`` to name a few.
+
+We were also able to access our xmpp client full jabber id by calling ``$client->full_jid``. This attribute of
+``JAXL`` instance is available from ``on_auth_success`` event. ``full_jid`` attribute is an instance of ``XMPPJid``.
+
+To send our echo back ``$msg`` packet we called ``JAXL::send/1`` which accepts a single parameter which MUST be
+an instance of ``JAXLXml``. Since ``XMPPStanza`` is a wrapper upon ``JAXLXml`` we can very well pass our modified
+``$msg`` object to the send method.
+
+Read more about various :ref:`XML Objects <xml-objects>` and how they make writing XMPP applications fun and easy.
+You can also :ref:`add custom access patterns <xml-objects>` upon received ``XMPPStanza`` objects. Since all access
+patterns are evaluated upon first access and cached for later usage, adding hundreds of custom access patterns that
+retrieves information from 100th child of received XML packet will not be an issue.
+
+We will finally start our xmpp client by calling:
+
+.. code-block:: ruby
+
+ $client->start();
+
+See list of :ref:`available options <jaxl-instance>` that can be passed to the ``JAXL::start/2`` method.
+These options are particularly useful for debugging and monitoring.
+
+Echo Bot BOSH Client
+--------------------
+Everything goes same for a cli BOSH client. To run above echo bot client example as a bosh client simply
+pass additional parameters to ``JAXL`` constructor:
+
+.. code-block:: ruby
+
+ require 'jaxl.php';
+ $client = new JAXL(array(
+ 'jid' => 'user@domain.tld',
+ 'pass' => 'password',
+ 'bosh_url' => 'http://localhost:5280/http-bind'
+ ));
+
+You can even pass custom values for ``hold``, ``wait`` and other attributes.
+
+View list of :ref:`available options <jaxl-instance>` that can be passed to ``JAXL`` constructor.
+
+Echo Bot External Component
+---------------------------
+Again almost everything goes same for an external component except a few custom ``JAXL`` constructor
+parameter as shown below:
+
+.. code-block:: ruby
+
+ require_once 'jaxl.php';
+ $comp = new JAXL(array(
+ // (required) component host and secret
+ 'jid' => $argv[1],
+ 'pass' => $argv[2],
+
+ // (required) destination socket
+ 'host' => $argv[3],
+ 'port' => $argv[4]
+ ));
+
+We will also need to include ``XEP0114`` which implements Jabber Component XMPP Extension.
+
+.. code-block:: ruby
+
+ // (required)
+ $comp->require_xep(array(
+ '0114' // jabber component protocol
+ ));
+
+``JAXL::require_xep/1`` accepts an array of XEP numbers passed as strings.
Index: externals/JAXL/docs/users/xmpp_extensions.rst
===================================================================
--- /dev/null
+++ externals/JAXL/docs/users/xmpp_extensions.rst
@@ -0,0 +1,32 @@
+XMPP Extensions (XEP)
+=====================
+
+Writing Custom XMPP Extension
+-----------------------------
+
+Entity Discovery
+----------------
+
+Multi-User Chat
+---------------
+
+Direct MUC Invitation
+---------------------
+
+Publish-Subscribe
+-----------------
+
+In-Band User Registration
+-------------------------
+
+External Jabber Component
+-------------------------
+
+Entity Capabilities
+-------------------
+
+Delayed Delivery
+----------------
+
+XMPP Over HTTP (Bosh)
+---------------------
Index: externals/JAXL/examples/curl.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/curl.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+if($argc < 2) {
+ echo "Usage: $argv[0] url\n";
+ exit;
+}
+
+require_once 'jaxl.php';
+JAXLLogger::$level = JAXL_DEBUG;
+require_once JAXL_CWD.'/http/http_client.php';
+
+$request = new HTTPClient($argv[1]);
+$request->start();
+
+?>
Index: externals/JAXL/examples/echo_bosh_bot.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/echo_bosh_bot.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+if($argc < 3) {
+ echo "Usage: $argv[0] jid pass\n";
+ exit;
+}
+
+//
+// initialize JAXL object with initial config
+//
+require_once 'jaxl.php';
+$client = new JAXL(array(
+ // (required) credentials
+ 'jid' => $argv[1],
+ 'pass' => $argv[2],
+
+ // (required)
+ 'bosh_url' => 'http://localhost:5280/http-bind',
+
+ // (optional) srv lookup is done if not provided
+ // for bosh client 'host' value is used for 'route' attribute
+ //'host' => 'xmpp.domain.tld',
+
+ // (optional) result from srv lookup used by default
+ // for bosh client 'port' value is used for 'route' attribute
+ //'port' => 5222,
+
+ // (optional)
+ //'resource' => 'resource',
+
+ // (optional) defaults to PLAIN if supported, else other methods will be automatically tried
+ 'auth_type' => @$argv[3] ? $argv[3] : 'PLAIN',
+
+ 'log_level' => JAXL_INFO
+));
+
+//
+// add necessary event callbacks here
+//
+
+$client->add_cb('on_auth_success', function() {
+ global $client;
+ _info("got on_auth_success cb, jid ".$client->full_jid->to_string());
+ $client->set_status("available!", "dnd", 10);
+});
+
+$client->add_cb('on_auth_failure', function($reason) {
+ global $client;
+ $client->send_end_stream();
+ _info("got on_auth_failure cb with reason $reason");
+});
+
+$client->add_cb('on_chat_message', function($stanza) {
+ global $client;
+
+ // echo back incoming message stanza
+ $stanza->to = $stanza->from;
+ $stanza->from = $client->full_jid->to_string();
+ $client->send($stanza);
+});
+
+$client->add_cb('on_disconnect', function() {
+ _info("got on_disconnect cb");
+});
+
+//
+// finally start configured xmpp stream
+//
+$client->start();
+echo "done\n";
+
+?>
Index: externals/JAXL/examples/echo_bot.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/echo_bot.php
@@ -0,0 +1,149 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// Run as:
+// php examples/echo_bot.php root@localhost password
+// php examples/echo_bot.php root@localhost password DIGEST-MD5
+// php examples/echo_bot.php localhost "" ANONYMOUS
+if($argc < 3) {
+ echo "Usage: $argv[0] jid pass auth_type\n";
+ exit;
+}
+
+//
+// initialize JAXL object with initial config
+//
+require_once 'jaxl.php';
+$client = new JAXL(array(
+ // (required) credentials
+ 'jid' => $argv[1],
+ 'pass' => $argv[2],
+
+ // (optional) srv lookup is done if not provided
+ //'host' => 'xmpp.domain.tld',
+
+ // (optional) result from srv lookup used by default
+ //'port' => 5222,
+
+ // (optional) defaults to false
+ //'force_tls' => true,
+
+ // (optional)
+ //'resource' => 'resource',
+
+ // (optional) defaults to PLAIN if supported, else other methods will be automatically tried
+ 'auth_type' => @$argv[3] ? $argv[3] : 'PLAIN',
+
+ 'log_level' => JAXL_INFO
+));
+
+//
+// required XEP's
+//
+$client->require_xep(array(
+ '0199' // XMPP Ping
+));
+
+//
+// add necessary event callbacks here
+//
+
+$client->add_cb('on_auth_success', function() {
+ global $client;
+ _info("got on_auth_success cb, jid ".$client->full_jid->to_string());
+
+ // fetch roster list
+ $client->get_roster();
+
+ // fetch vcard
+ $client->get_vcard();
+
+ // set status
+ $client->set_status("available!", "dnd", 10);
+});
+
+// by default JAXL instance catches incoming roster list results and updates
+// roster list is parsed/cached and an event 'on_roster_update' is emitted
+$client->add_cb('on_roster_update', function() {
+ //global $client;
+ //print_r($client->roster);
+});
+
+$client->add_cb('on_auth_failure', function($reason) {
+ global $client;
+ _info("got on_auth_failure cb with reason $reason");
+ $client->send_end_stream();
+});
+
+$client->add_cb('on_chat_message', function($stanza) {
+ global $client;
+
+ // echo back incoming chat message stanza
+ $stanza->to = $stanza->from;
+ $stanza->from = $client->full_jid->to_string();
+ $client->send($stanza);
+});
+
+$client->add_cb('on_presence_stanza', function($stanza) {
+ global $client;
+
+ $type = ($stanza->type ? $stanza->type : "available");
+ $show = ($stanza->show ? $stanza->show : "???");
+ _info($stanza->from." is now ".$type." ($show)");
+
+ if($type == "available") {
+ // fetch vcard
+ $client->get_vcard($stanza->from);
+ }
+});
+
+$client->add_cb('on_disconnect', function() {
+ _info("got on_disconnect cb");
+});
+
+//
+// finally start configured xmpp stream
+//
+
+$client->start(array(
+ '--with-debug-shell' => true,
+ '--with-unix-sock' => true
+));
+echo "done\n";
+
+?>
Index: externals/JAXL/examples/echo_component_bot.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/echo_component_bot.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+if($argc != 5) {
+ echo "Usage: $argv[0] jid pass host port\n";
+ exit;
+}
+
+//
+// initialize JAXL object with initial config
+//
+require_once 'jaxl.php';
+$comp = new JAXL(array(
+ // (required) component host and secret
+ 'jid' => $argv[1],
+ 'pass' => $argv[2],
+
+ // (required)
+ 'host' => @$argv[3],
+ 'port' => $argv[4],
+
+ 'log_level' => JAXL_INFO
+));
+
+//
+// XEP's required (required)
+//
+$comp->require_xep(array(
+ '0114' // jabber component protocol
+));
+
+//
+// add necessary event callbacks here
+//
+
+$comp->add_cb('on_auth_success', function() {
+ _info("got on_auth_success cb");
+});
+
+$comp->add_cb('on_auth_failure', function($reason) {
+ global $comp;
+ $comp->send_end_stream();
+ _info("got on_auth_failure cb with reason $reason");
+});
+
+$comp->add_cb('on_chat_message', function($stanza) {
+ global $comp;
+
+ // echo back incoming message stanza
+ $stanza->to = $stanza->from;
+ $stanza->from = $comp->jid->to_string();
+ $comp->send($stanza);
+});
+
+$comp->add_cb('on_disconnect', function() {
+ _info("got on_disconnect cb");
+});
+
+//
+// finally start configured xmpp stream
+//
+$comp->start();
+echo "done\n";
+
+?>
Index: externals/JAXL/examples/echo_http_server.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/echo_http_server.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// include and configure logger
+require_once 'jaxl.php';
+JAXLLogger::$level = JAXL_INFO;
+
+// print usage notice and parse addr/port parameters if passed
+_colorize("Usage: $argv[0] port (default: 9699)", JAXL_NOTICE);
+$port = ($argc == 2 ? $argv[1] : 9699);
+
+// initialize http server
+require_once JAXL_CWD.'/http/http_server.php';
+$http = new HTTPServer($port);
+
+// catch all incoming requests here
+function on_request($request) {
+ $body = json_encode($request);
+ $request->ok($body, array('Content-Type'=>'application/json'));
+}
+
+// start http server
+$http->start('on_request');
+
+?>
Index: externals/JAXL/examples/echo_unix_sock_server.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/echo_unix_sock_server.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+if($argc < 2) {
+ echo "Usage: $argv[0] /path/to/server.sock\n";
+ exit;
+}
+
+require_once 'jaxl.php';
+JAXLLogger::$level = JAXL_INFO;
+
+$server = null;
+
+function on_request($client, $raw) {
+ global $server;
+ $server->send($client, $raw);
+ _info("got client callback ".$raw);
+}
+
+@unlink($argv[1]);
+$server = new JAXLSocketServer('unix://'.$argv[1], NULL, 'on_request');
+
+JAXLLoop::run();
+echo "done\n";
+
+?>
Index: externals/JAXL/examples/http_bind.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/http_bind.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+if(!isset($_GET['jid']) || !isset($_GET['pass'])) {
+ echo "invalid input";
+ exit;
+}
+
+//
+// initialize JAXL object with initial config
+//
+require_once '../jaxl.php';
+$client = new JAXL(array(
+ 'jid' => $_GET['jid'],
+ 'pass' => $_GET['pass'],
+ 'bosh_url' => 'http://localhost:5280/http-bind',
+ 'log_level' => JAXL_DEBUG
+));
+
+$client->add_cb('on_auth_success', function() {
+ global $client;
+ _info("got on_auth_success cb, jid ".$client->full_jid->to_string());
+});
+
+//
+// finally start configured xmpp stream
+//
+$client->start();
+echo "done\n";
+
+?>
Index: externals/JAXL/examples/http_pre_bind.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/http_pre_bind.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// http pre bind php script
+$body = file_get_contents("php://input");
+$body = new SimpleXMLElement($body);
+$attrs = $body->attributes();
+
+if(!@$attrs['to'] && !@$attrs['rid'] && !@$attrs['wait'] && !@$attrs['hold']) {
+ echo "invalid input";
+ exit;
+}
+
+//
+// initialize JAXL object with initial config
+//
+require_once '../jaxl.php';
+
+$to = (string)$attrs['to'];
+$rid = (int)$attrs['rid'];
+$wait = (int)$attrs['wait'];
+$hold = (int)$attrs['hold'];
+list($host, $port) = JAXLUtil::get_dns_srv($to);
+
+$client = new JAXL(array(
+ 'domain' => $to,
+ 'host' => $host,
+ 'port' => $port,
+ 'bosh_url' => 'http://localhost:5280/http-bind',
+ 'bosh_rid' => $rid,
+ 'bosh_wait' => $wait,
+ 'bosh_hold' => $hold,
+ 'auth_type' => 'ANONYMOUS',
+ 'log_level' => JAXL_INFO
+));
+
+$client->add_cb('on_auth_success', function() {
+ global $client;
+ _info("got on_auth_success cb, jid ".$client->full_jid->to_string());
+ echo '<body xmlns="'.NS_HTTP_BIND.'" sid="'.$client->xeps['0206']->sid.'" rid="'.$client->xeps['0206']->rid.'" jid="'.$client->full_jid->to_string().'"/>';
+ exit;
+});
+
+$client->add_cb('on_auth_failure', function($reason) {
+ global $client;
+ _info("got on_auth_failure cb with reason $reason");
+ $client->send_end_stream();
+});
+
+//
+// finally start configured xmpp stream
+//
+$client->start();
+echo "done\n";
+
+?>
Index: externals/JAXL/examples/http_rest_server.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/http_rest_server.php
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// include and configure logger
+require_once 'jaxl.php';
+JAXLLogger::$level = JAXL_INFO;
+
+// print usage notice and parse addr/port parameters if passed
+_colorize("Usage: $argv[0] port (default: 9699)", JAXL_NOTICE);
+$port = ($argc == 2 ? $argv[1] : 9699);
+
+// initialize http server
+require_once JAXL_CWD.'/http/http_server.php';
+$http = new HTTPServer($port);
+
+// callback method for dispatch rule (see below)
+function index($request) {
+ $request->send_response(
+ 200, array('Content-Type'=>'text/html'),
+ '<html><head/><body><h1>Jaxl Http Server</h1><a href="/upload">upload a file</a></body></html>'
+ );
+ $request->close();
+}
+
+// callback method for dispatch rule (see below)
+function upload($request) {
+ if($request->method == 'GET') {
+ $request->ok(array(
+ 'Content-Type'=>'text/html'),
+ '<html><head/><body><h1>Jaxl Http Server</h1><form enctype="multipart/form-data" method="POST" action="http://127.0.0.1:9699/upload/"><input type="file" name="file"/><input type="submit" value="upload"/></form></body></html>'
+ );
+ }
+ else if($request->method == 'POST') {
+ if($request->body === null && $request->expect) {
+ $request->recv_body();
+ }
+ else {
+ // got upload body, save it
+ _info("file upload complete, got ".strlen($request->body)." bytes of data");
+ $upload_data = $request->multipart->form_data[0]['body'];
+ $request->ok($upload_data, array('Content-Type'=>$request->multipart->form_data[0]['headers']['Content-Type']));
+ }
+ }
+}
+
+// add dispatch rules with callback method as first argument
+$index = array('index', '^/$');
+$upload = array('upload', '^/upload', array('GET', 'POST'));
+
+// some REST CRUD style callback methods
+// Refer: http://jaxl.readthedocs.org/en/latest/users/http_extensions.html#dispatch-rules
+function create_event($request) {
+ _info("got event create request");
+ $request->close();
+}
+
+function read_event($request, $pk) {
+ _info("got event read request for $pk");
+ $request->close();
+}
+
+function update_event($request, $pk) {
+ _info("got event update request for $pk");
+ $request->close();
+}
+
+function delete_event($request, $pk) {
+ _info("got event delete request for $pk");
+ $request->close();
+}
+
+$event_create = array('create_event', '^/event/create/$', array('PUT'));
+$event_read = array('read_event', '^/event/(?P<pk>\d+)/$', array('GET', 'HEAD'));
+$event_update = array('update_event', '^/event/(?P<pk>\d+)/$', array('POST'));
+$event_delete = array('delete_event', '^/event/(?P<pk>\d+)/$', array('DELETE'));
+
+// prepare rule set
+$rules = array($index, $upload, $event_create, $event_read, $event_update, $event_delete);
+$http->dispatch($rules);
+
+// start http server
+$http->start();
Index: externals/JAXL/examples/muc_log_bot.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/muc_log_bot.php
@@ -0,0 +1,146 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+if($argc < 5) {
+ echo "Usage: $argv[0] host jid pass room@service.domain.tld nickname\n";
+ exit;
+}
+
+//
+// initialize JAXL object with initial config
+//
+require_once 'jaxl.php';
+$client = new JAXL(array(
+ // (required) credentials
+ 'jid' => $argv[2],
+ 'pass' => $argv[3],
+ 'host' => $argv[1],
+ 'log_level' => JAXL_INFO
+));
+
+$client->require_xep(array(
+ '0045', // MUC
+ '0203', // Delayed Delivery
+ '0199' // XMPP Ping
+));
+
+//
+// add necessary event callbacks here
+//
+
+$_room_full_jid = $argv[4]."/".$argv[5];
+$room_full_jid = new XMPPJid($_room_full_jid);
+
+$client->add_cb('on_auth_success', function() {
+ global $client, $room_full_jid;
+ _info("got on_auth_success cb, jid ".$client->full_jid->to_string());
+
+ // join muc room
+ $client->xeps['0045']->join_room($room_full_jid);
+});
+
+$client->add_cb('on_auth_failure', function($reason) {
+ global $client;
+ $client->send_end_stream();
+ _info("got on_auth_failure cb with reason $reason");
+});
+
+$client->add_cb('on_groupchat_message', function($stanza) {
+ global $client;
+
+ $from = new XMPPJid($stanza->from);
+ $delay = $stanza->exists('delay', NS_DELAYED_DELIVERY);
+
+ if($from->resource) {
+ echo "message stanza rcvd from ".$from->resource." saying... ".$stanza->body.($delay ? ", delay timestamp ".$delay->attrs['stamp'] : ", timestamp ".gmdate("Y-m-dTH:i:sZ")).PHP_EOL;
+ }
+ else {
+ $subject = $stanza->exists('subject');
+ if($subject) {
+ echo "room subject: ".$subject->text.($delay ? ", delay timestamp ".$delay->attrs['stamp'] : ", timestamp ".gmdate("Y-m-dTH:i:sZ")).PHP_EOL;
+ }
+ }
+});
+
+$client->add_cb('on_presence_stanza', function($stanza) {
+ global $client, $room_full_jid;
+
+ $from = new XMPPJid($stanza->from);
+
+ // self-stanza received, we now have complete room roster
+ if(strtolower($from->to_string()) == strtolower($room_full_jid->to_string())) {
+ if(($x = $stanza->exists('x', NS_MUC.'#user')) !== false) {
+ if(($status = $x->exists('status', null, array('code'=>'110'))) !== false) {
+ $item = $x->exists('item');
+ _info("xmlns #user exists with x ".$x->ns." status ".$status->attrs['code'].", affiliation:".$item->attrs['affiliation'].", role:".$item->attrs['role']);
+ }
+ else {
+ _info("xmlns #user have no x child element");
+ }
+ }
+ else {
+ _warning("=======> odd case 1");
+ }
+ }
+ // stanza from other users received
+ else if(strtolower($from->bare) == strtolower($room_full_jid->bare)) {
+ if(($x = $stanza->exists('x', NS_MUC.'#user')) !== false) {
+ $item = $x->exists('item');
+ echo "presence stanza of type ".($stanza->type ? $stanza->type : "available")." received from ".$from->resource.", affiliation:".$item->attrs['affiliation'].", role:".$item->attrs['role'].PHP_EOL;
+ }
+ else {
+ _warning("=======> odd case 2");
+ }
+ }
+ else {
+ _warning("=======> odd case 3");
+ }
+
+});
+
+$client->add_cb('on_disconnect', function() {
+ _info("got on_disconnect cb");
+});
+
+//
+// finally start configured xmpp stream
+//
+$client->start();
+echo "done\n";
+
+?>
Index: externals/JAXL/examples/multi_client.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/multi_client.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// enable multi client support
+// this will force 1st parameter of callbacks
+// as connected client instance
+define('JAXL_MULTI_CLIENT', true);
+
+// input multiple account credentials
+$accounts = array();
+$add_new = TRUE;
+while($add_new) {
+ $jid = readline('Enter Jabber Id: ');
+ $pass = readline('Enter Password: ');
+ $accounts[] = array($jid, $pass);
+ $next = readline('Add another account (y/n): ');
+ $add_new = $next == 'y' ? TRUE : FALSE;
+}
+
+// setup jaxl
+require_once 'jaxl.php';
+
+//
+// common callbacks
+//
+
+function on_auth_success($client) {
+ _info("got on_auth_success cb, jid ".$client->full_jid->to_string());
+
+ // fetch roster list
+ $client->get_roster();
+
+ // fetch vcard
+ $client->get_vcard();
+
+ // set status
+ $client->set_status("available!", "dnd", 10);
+}
+
+function on_auth_failure($client, $reason) {
+ _info("got on_auth_failure cb with reason $reason");
+ $client->send_end_stream();
+}
+
+function on_chat_message($client, $stanza) {
+ // echo back incoming chat message stanza
+ $stanza->to = $stanza->from;
+ $stanza->from = $client->full_jid->to_string();
+ $client->send($stanza);
+}
+
+function on_presence_stanza($client, $stanza) {
+ global $client;
+
+ $type = ($stanza->type ? $stanza->type : "available");
+ $show = ($stanza->show ? $stanza->show : "???");
+ _info($stanza->from." is now ".$type." ($show)");
+
+ if($type == "available") {
+ // fetch vcard
+ $client->get_vcard($stanza->from);
+ }
+}
+
+function on_disconnect($client) {
+ _info("got on_disconnect cb");
+}
+
+//
+// bootstrap all account instances
+//
+
+foreach($accounts as $account) {
+ $client = new JAXL(array(
+ 'jid' => $account[0],
+ 'pass' => $account[1],
+ 'log_level' => JAXL_DEBUG
+ ));
+
+ $client->add_cb('on_auth_success', 'on_auth_success');
+ $client->add_cb('on_auth_failure', 'on_auth_failure');
+ $client->add_cb('on_chat_message', 'on_chat_message');
+ $client->add_cb('on_presence_stanza', 'on_presence_stanza');
+ $client->add_cb('on_disconnect', 'on_disconnect');
+
+ $client->connect($client->get_socket_path());
+ $client->start_stream();
+}
+
+// start core loop
+JAXLLoop::run();
+echo "done\n";
+
+?>
Index: externals/JAXL/examples/pipes.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/pipes.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// include and configure logger
+require_once 'jaxl.php';
+JAXLLogger::$level = JAXL_INFO;
+
+// include jaxl pipes
+require_once JAXL_CWD.'/core/jaxl_pipe.php';
+
+// initialize
+$pipe_name = getmypid();
+$pipe = new JAXLPipe($pipe_name);
+
+// add read event callback
+$pipe->set_callback(function($data) {
+ global $pipe;
+ _info("read ".trim($data)." from pipe");
+});
+
+JAXLLoop::run();
+echo "done\n";
+
+?>
Index: externals/JAXL/examples/publisher.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/publisher.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+if($argc < 3) {
+ echo "Usage: $argv[0] jid pass\n";
+ exit;
+}
+
+//
+// initialize JAXL object with initial config
+//
+require_once 'jaxl.php';
+$client = new JAXL(array(
+ 'jid' => $argv[1],
+ 'pass' => $argv[2],
+ 'log_level' => JAXL_INFO
+));
+
+$client->require_xep(array(
+ '0060' // Publish-Subscribe
+));
+
+//
+// add necessary event callbacks here
+//
+
+$client->add_cb('on_auth_success', function() {
+ global $client;
+ _info("got on_auth_success cb, jid ".$client->full_jid->to_string());
+
+ // create node
+ //$client->xeps['0060']->create_node('pubsub.localhost', 'dummy_node');
+
+ // publish
+ $item = new JAXLXml('item', null, array('id'=>time()));
+ $item->c('entry', 'http://www.w3.org/2005/Atom');
+
+ $item->c('title')->t('Soliloquy')->up();
+ $item->c('summary')->t('To be, or not to be: that is the question')->up();
+ $item->c('link', null, array('rel'=>'alternate', 'type'=>'text/html', 'href'=>'http://denmark.lit/2003/12/13/atom03'))->up();
+ $item->c('id')->t('tag:denmark.lit,2003:entry-32397')->up();
+ $item->c('published')->t('2003-12-13T18:30:02Z')->up();
+ $item->c('updated')->t('2003-12-13T18:30:02Z')->up();
+
+ $client->xeps['0060']->publish_item('pubsub.localhost', 'dummy_node', $item);
+});
+
+$client->add_cb('on_auth_failure', function($reason) {
+ global $client;
+ $client->send_end_stream();
+ _info("got on_auth_failure cb with reason $reason");
+});
+
+$client->add_cb('on_disconnect', function() {
+ _info("got on_disconnect cb");
+});
+
+//
+// finally start configured xmpp stream
+//
+$client->start();
+echo "done\n";
+
+?>
Index: externals/JAXL/examples/register_user.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/register_user.php
@@ -0,0 +1,169 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+if($argc < 2) {
+ echo "Usage: $argv[0] domain\n";
+ exit;
+}
+
+//
+// initialize JAXL object with initial config
+//
+require_once 'jaxl.php';
+$client = new JAXL(array(
+ 'jid' => $argv[1],
+ 'log_level' => JAXL_DEBUG
+));
+
+$client->require_xep(array(
+ '0077' // InBand Registration
+));
+
+//
+// below are two states which become part of
+// our client's xmpp_stream lifecycle
+// consider as if these methods are directly
+// inside xmpp_stream state machine
+//
+// Note: $stanza = $args[0] is an instance of
+// JAXLXml in xmpp_stream state methods,
+// it is yet not ready for easy access
+// patterns available on XMPPStanza instances
+//
+
+$form = array();
+
+function wait_for_register_response($event, $args) {
+ global $client, $form;
+
+ if($event == 'stanza_cb') {
+ $stanza = $args[0];
+ if($stanza->name == 'iq') {
+ $form['type'] = $stanza->attrs['type'];
+ if($stanza->attrs['type'] == 'result') {
+ echo "registration successful".PHP_EOL."shutting down...".PHP_EOL;
+ $client->send_end_stream();
+ return "logged_out";
+ }
+ else if($stanza->attrs['type'] == 'error') {
+ $error = $stanza->exists('error');
+ echo "registration failed with error code: ".$error->attrs['code']." and type: ".$error->attrs['type'].PHP_EOL;
+ echo "error text: ".$error->exists('text')->text.PHP_EOL;
+ echo "shutting down...".PHP_EOL;
+ $client->send_end_stream();
+ return "logged_out";
+ }
+ }
+ }
+ else {
+ _notice("unhandled event $event rcvd");
+ }
+}
+
+function wait_for_register_form($event, $args) {
+ global $client, $form;
+
+ $stanza = $args[0];
+ $query = $stanza->exists('query', NS_INBAND_REGISTER);
+ if($query) {
+ $instructions = $query->exists('instructions');
+ if($instructions) {
+ echo $instructions->text.PHP_EOL;
+ }
+
+ foreach($query->childrens as $k=>$child) {
+ if($child->name != 'instructions') {
+ $form[$child->name] = readline($child->name.":");
+
+ }
+ }
+
+ $client->xeps['0077']->set_form($stanza->attrs['from'], $form);
+ return "wait_for_register_response";
+ }
+ else {
+ $client->end_stream();
+ return "logged_out";
+ }
+}
+
+//
+// add necessary event callbacks here
+//
+
+$client->add_cb('on_stream_features', function($stanza) {
+ global $client, $argv;
+ $client->xeps['0077']->get_form($argv[1]);
+ return "wait_for_register_form";
+});
+
+$client->add_cb('on_disconnect', function() {
+ global $form;
+ _info("registration " . ($form['type'] == 'result' ? 'succeeded' : 'failed'));
+});
+
+//
+// finally start configured xmpp stream
+//
+$client->start();
+
+//
+// if registration was successful
+// try to connect with newly registered account
+//
+if($form['type'] == 'result') {
+
+_info("connecting newly registered user account");
+$client = new JAXL(array(
+ 'jid' => $form['username'].'@'.$argv[1],
+ 'pass' => $form['password'],
+ 'log_level' => JAXL_DEBUG
+));
+
+$client->add_cb('on_auth_success', function() {
+ global $client;
+ $client->set_status('Available');
+});
+
+$client->start();
+
+}
+
+echo "done\n";
+
+?>
Index: externals/JAXL/examples/subscriber.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/subscriber.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+if($argc < 3) {
+ echo "Usage: $argv[0] jid pass\n";
+ exit;
+}
+
+//
+// initialize JAXL object with initial config
+//
+require_once 'jaxl.php';
+$client = new JAXL(array(
+ 'jid' => $argv[1],
+ 'pass' => $argv[2],
+ 'log_level' => JAXL_INFO
+));
+
+$client->require_xep(array(
+ '0060' // Publish-Subscribe
+));
+
+//
+// add necessary event callbacks here
+//
+
+$client->add_cb('on_auth_success', function() {
+ global $client;
+ _info("got on_auth_success cb, jid ".$client->full_jid->to_string());
+
+ // create node
+ //$client->xeps['0060']->create_node('pubsub.localhost', 'dummy_node');
+
+ // subscribe
+ $client->xeps['0060']->subscribe('pubsub.localhost', 'dummy_node');
+});
+
+$client->add_cb('on_auth_failure', function($reason) {
+ global $client;
+ $client->send_end_stream();
+ _info("got on_auth_failure cb with reason $reason");
+});
+
+$client->add_cb('on_headline_message', function($stanza) {
+ global $client;
+ if(($event = $stanza->exists('event', NS_PUBSUB.'#event'))) {
+ _info("got pubsub event");
+ }
+ else {
+ _warning("unknown headline message rcvd");
+ }
+});
+
+$client->add_cb('on_disconnect', function() {
+ _info("got on_disconnect cb");
+});
+
+//
+// finally start configured xmpp stream
+//
+$client->start();
+echo "done\n";
+
+?>
Index: externals/JAXL/examples/xfacebook_platform_client.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/xfacebook_platform_client.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+if($argc != 4) {
+ echo "Usage: $argv[0] fb_user_id_or_username fb_app_key fb_access_token\n";
+ exit;
+}
+
+//
+// initialize JAXL object with initial config
+//
+require_once 'jaxl.php';
+$client = new JAXL(array(
+ // (required) credentials
+ 'jid' => $argv[1].'@chat.facebook.com',
+ 'fb_app_key' => $argv[2],
+ 'fb_access_token' => $argv[3],
+
+ // force tls (facebook require this now)
+ 'force_tls' => true,
+ // (required) force facebook oauth
+ 'auth_type' => 'X-FACEBOOK-PLATFORM',
+
+ // (optional)
+ //'resource' => 'resource',
+
+ 'log_level' => JAXL_INFO
+));
+
+//
+// add necessary event callbacks here
+//
+
+$client->add_cb('on_auth_success', function() {
+ global $client;
+ _info("got on_auth_success cb, jid ".$client->full_jid->to_string());
+ $client->set_status("available!", "dnd", 10);
+});
+
+$client->add_cb('on_auth_failure', function($reason) {
+ global $client;
+ $client->send_end_stream();
+ _info("got on_auth_failure cb with reason $reason");
+});
+
+$client->add_cb('on_chat_message', function($stanza) {
+ global $client;
+
+ // echo back incoming message stanza
+ $stanza->to = $stanza->from;
+ $stanza->from = $client->full_jid->to_string();
+ $client->send($stanza);
+});
+
+$client->add_cb('on_disconnect', function() {
+ _info("got on_disconnect cb");
+});
+
+//
+// finally start configured xmpp stream
+//
+$client->start();
+echo "done\n";
+
+?>
Index: externals/JAXL/examples/xmpp_rest.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/xmpp_rest.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// View explanation for this example here:
+// https://groups.google.com/d/msg/jaxl/QaGjZP4A2gY/n6SYutrBVxsJ
+if($argc < 3) {
+ echo "Usage: $argv[0] jid pass\n";
+ exit;
+}
+
+// initialize xmpp client
+require_once 'jaxl.php';
+$xmpp = new JAXL(array(
+ 'jid' => $argv[1],
+ 'pass' => $argv[2],
+ 'log_level' => JAXL_INFO
+));
+
+// register callbacks on required xmpp events
+$xmpp->add_cb('on_auth_success', function() {
+ global $xmpp;
+ _info("got on_auth_success cb, jid ".$xmpp->full_jid->to_string());
+});
+
+// initialize http server
+require_once JAXL_CWD.'/http/http_server.php';
+$http = new HTTPServer();
+
+// add generic callback
+// you can also dispatch REST style callback
+// Refer: http://jaxl.readthedocs.org/en/latest/users/http_extensions.html#dispatch-rules
+$http->cb = function($request) {
+ // For demo purposes we simply return xmpp client full jid
+ global $xmpp;
+ $request->ok($xmpp->full_jid->to_string());
+};
+
+// This will start main JAXLLoop,
+// hence we don't need to call $http->start() explicitly
+$xmpp->start();
+
+?>
Index: externals/JAXL/examples/xoauth2_gtalk_client.php
===================================================================
--- /dev/null
+++ externals/JAXL/examples/xoauth2_gtalk_client.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+if($argc != 3) {
+ echo "Usage: $argv[0] jid access_token\n";
+ exit;
+}
+
+//
+// initialize JAXL object with initial config
+//
+require_once 'jaxl.php';
+$client = new JAXL(array(
+ // (required) credentials
+ 'jid' => $argv[1],
+ 'pass' => $argv[2],
+
+ // force tls
+ 'force_tls' => true,
+ // (required) perform X-OAUTH2
+ 'auth_type' => 'X-OAUTH2',
+
+ // (optional)
+ //'resource' => 'resource',
+
+ 'log_level' => JAXL_DEBUG
+));
+
+//
+// add necessary event callbacks here
+//
+
+$client->add_cb('on_auth_success', function() {
+ global $client;
+ _info("got on_auth_success cb, jid ".$client->full_jid->to_string());
+ $client->set_status("available!", "dnd", 10);
+});
+
+$client->add_cb('on_auth_failure', function($reason) {
+ global $client;
+ $client->send_end_stream();
+ _info("got on_auth_failure cb with reason $reason");
+});
+
+$client->add_cb('on_chat_message', function($stanza) {
+ global $client;
+
+ // echo back incoming message stanza
+ $stanza->to = $stanza->from;
+ $stanza->from = $client->full_jid->to_string();
+ $client->send($stanza);
+});
+
+$client->add_cb('on_disconnect', function() {
+ _info("got on_disconnect cb");
+});
+
+//
+// finally start configured xmpp stream
+//
+$client->start();
+echo "done\n";
+
+?>
Index: externals/JAXL/http/README.md
===================================================================
--- /dev/null
+++ externals/JAXL/http/README.md
@@ -0,0 +1,9 @@
+Jaxl HTTP Stack:
+----------------
+HTTP Stack implementation includes:
+
+* HTTPClient - Generic HTTP Client
+* HTTPServer - Generic HTTP Server
+* HTTPRequest - A HTTP Request Object
+* HTTPDispatcher - HTTP REST Url Dispatcher
+* HTTPMultiPart - HTTP MultiPart Body
\ No newline at end of file
Index: externals/JAXL/http/http_client.php
===================================================================
--- /dev/null
+++ externals/JAXL/http/http_client.php
@@ -0,0 +1,138 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/core/jaxl_socket_client.php';
+
+/**
+ * TODO: convert into a finite state machine
+ *
+ * @author abhinavsingh
+ *
+ */
+class HTTPClient {
+
+ private $url = null;
+ private $parts = array();
+
+ private $headers = array();
+ private $data = null;
+ public $method = null;
+
+ private $client = null;
+
+ public function __construct($url, $headers=array(), $data=null) {
+ $this->url = $url;
+ $this->headers = $headers;
+ $this->data = $data;
+
+ $this->client = new JAXLSocketClient();
+ $this->client->set_callback(array(&$this, 'on_response'));
+ }
+
+ public function start($method='GET') {
+ $this->method = $method;
+
+ $this->parts = parse_url($this->url);
+ $transport = $this->_transport();
+ $ip = $this->_ip();
+ $port = $this->_port();
+
+ $socket_path = $transport.'://'.$ip.':'.$port;
+ if($this->client->connect($socket_path)) {
+ _debug("connection to $this->url established");
+
+ // send request data
+ $this->send_request();
+
+ // start main loop
+ JAXLLoop::run();
+ }
+ else {
+ _debug("unable to open $this->url");
+ }
+ }
+
+ public function on_response($raw) {
+ _info("got http response");
+ }
+
+ protected function send_request() {
+ $this->client->send($this->_line()."\r\n");
+ $this->client->send($this->_ua()."\r\n");
+ $this->client->send($this->_host()."\r\n");
+ $this->client->send("\r\n");
+ }
+
+ //
+ // private methods on uri parts
+ //
+
+ private function _line() {
+ return $this->method.' '.$this->_uri().' HTTP/1.1';
+ }
+
+ private function _ua() {
+ return 'User-Agent: jaxl_http_client/3.x';
+ }
+
+ private function _host() {
+ return 'Host: '.$this->parts['host'].':'.$this->_port();
+ }
+
+ private function _transport() {
+ return ($this->parts['scheme'] == 'http' ? 'tcp' : 'ssl');
+ }
+
+ private function _ip() {
+ return gethostbyname($this->parts['host']);
+ }
+
+ private function _port() {
+ return @$this->parts['port'] ? $this->parts['port'] : 80;
+ }
+
+ private function _uri() {
+ $uri = $this->parts['path'];
+ if(@$this->parts['query']) $uri .= '?'.$this->parts['query'];
+ if(@$this->parts['fragment']) $uri .= '#'.$this->parts['fragment'];
+ return $uri;
+ }
+
+}
+
+?>
Index: externals/JAXL/http/http_dispatcher.php
===================================================================
--- /dev/null
+++ externals/JAXL/http/http_dispatcher.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+//
+// (optionally) set an array of url dispatch rules
+// each dispatch rule is defined by an array of size 4 like:
+// array($callback, $pattern, $methods, $extra), where
+// $callback the method which will be called if this rule matches
+// $pattern regular expression to match request path
+// $methods list of allowed methods for this rule
+// pass boolean true to allow all http methods
+// if omitted or an empty array() is passed (which actually doesnt make sense)
+// by default 'GET' will be the method allowed on this rule
+// $extra reserved for future (you can totally omit this as of now)
+//
+class HTTPDispatchRule {
+
+ // match callback
+ public $cb = null;
+
+ // regexp to match on request path
+ public $pattern = null;
+
+ // methods to match upon
+ // add atleast 1 method for this rule to work
+ public $methods = null;
+
+ // other matching rules
+ public $extra = array();
+
+ public function __construct($cb, $pattern, $methods=array('GET'), $extra=array()) {
+ $this->cb = $cb;
+ $this->pattern = $pattern;
+ $this->methods = $methods;
+ $this->extra = $extra;
+ }
+
+ public function match($path, $method) {
+ if(preg_match("/".str_replace("/", "\/", $this->pattern)."/", $path, $matches)) {
+ if(in_array($method, $this->methods)) {
+ return $matches;
+ }
+ }
+ return false;
+ }
+
+}
+
+class HTTPDispatcher {
+
+ protected $rules = array();
+
+ public function __construct() {
+ $this->rules = array();
+ }
+
+ public function add_rule($rule) {
+ $s = sizeof($rule);
+ if($s > 4) { _debug("invalid rule"); return; }
+
+ // fill up defaults
+ if($s == 3) { $rule[] = array(); }
+ else if($s == 2) { $rule[] = array('GET'); $rule[] = array(); }
+ else { _debug("invalid rule"); return; }
+
+ $this->rules[] = new HTTPDispatchRule($rule[0], $rule[1], $rule[2], $rule[3]);
+ }
+
+ public function dispatch($request) {
+ foreach($this->rules as $rule) {
+ //_debug("matching $request->path with pattern $rule->pattern");
+ if(($matches = $rule->match($request->path, $request->method)) !== false) {
+ _debug("matching rule found, dispatching");
+ $params = array($request);
+ // TODO: a bad way to restrict on 'pk', fix me for generalization
+ if(@isset($matches['pk'])) $params[] = $matches['pk'];
+ call_user_func_array($rule->cb, $params);
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
+
+?>
Index: externals/JAXL/http/http_multipart.php
===================================================================
--- /dev/null
+++ externals/JAXL/http/http_multipart.php
@@ -0,0 +1,176 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/core/jaxl_fsm.php';
+
+class HTTPMultiPart extends JAXLFsm {
+
+ public $boundary = null;
+ public $form_data = array();
+ public $index = -1;
+
+ public function handle_invalid_state($r) {
+ _error("got invalid event $r");
+ }
+
+ public function __construct($boundary) {
+ $this->boundary = $boundary;
+ parent::__construct('wait_for_boundary_start');
+ }
+
+ public function state() {
+ return $this->state;
+ }
+
+ public function wait_for_boundary_start($event, $data) {
+ if($event == 'process') {
+ if($data[0] == '--'.$this->boundary) {
+ $this->index += 1;
+ $this->form_data[$this->index] = array(
+ 'meta' => array(),
+ 'headers' => array(),
+ 'body' => ''
+ );
+ return array('wait_for_content_disposition', true);
+ }
+ else {
+ _warning("invalid boundary start $data[0] while expecting $this->boundary");
+ return array('wait_for_boundary_start', false);
+ }
+ }
+ else {
+ _warning("invalid $event rcvd");
+ return array('wait_for_boundary_start', false);
+ }
+ }
+
+ public function wait_for_content_disposition($event, $data) {
+ if($event == 'process') {
+ $disposition = explode(":", $data[0]);
+
+ if(strtolower(trim($disposition[0])) == 'content-disposition') {
+ $this->form_data[$this->index]['headers'][$disposition[0]] = trim($disposition[1]);
+ $meta = explode(";", $disposition[1]);
+ if(trim(array_shift($meta)) == 'form-data') {
+ foreach($meta as $k) {
+ list($k, $v) = explode("=", $k);
+ $this->form_data[$this->index]['meta'][$k] = $v;
+ }
+
+ return array('wait_for_content_type', true);
+ }
+ else {
+ _warning("first part of meta is not form-data");
+ return array('wait_for_content_disposition', false);
+ }
+ }
+ else {
+ _warning("not a valid content-disposition line");
+ return array('wait_for_content_disposition', false);
+ }
+ }
+ else {
+ _warning("invalid $event rcvd");
+ return array('wait_for_content_disposition', false);
+ }
+ }
+
+ public function wait_for_content_type($event, $data) {
+ if($event == 'process') {
+ $type = explode(":", $data[0]);
+ if(strtolower(trim($type[0])) == 'content-type') {
+ $this->form_data[$this->index]['headers'][$type[0]] = trim($type[1]);
+ $this->form_data[$this->index]['meta']['type'] = $type[1];
+ return array('wait_for_content_body', true);
+ }
+ else {
+ _debug("not a valid content-type line");
+ return array('wait_for_content_type', false);
+ }
+ }
+ else {
+ _warning("invalid $event rcvd");
+ return array('wait_for_content_type', false);
+ }
+ }
+
+ public function wait_for_content_body($event, $data) {
+ if($event == 'process') {
+ if($data[0] == '--'.$this->boundary) {
+ _debug("start of new multipart/form-data detected");
+ return array('wait_for_content_disposition', true);
+ }
+ else if($data[0] == '--'.$this->boundary.'--') {
+ _debug("end of multipart form data detected");
+ return array('wait_for_empty_line', true);
+ }
+ else {
+ $this->form_data[$this->index]['body'] .= $data[0];
+ return array('wait_for_content_body', true);
+ }
+ }
+ else {
+ _warning("invalid $event rcvd");
+ return array('wait_for_content_body', false);
+ }
+ }
+
+ public function wait_for_empty_line($event, $data) {
+ if($event == 'process') {
+ if($data[0] == '') {
+ return array('done', true);
+ }
+ else {
+ _warning("invalid empty line $data[0] received");
+ return array('wait_for_empty_line', false);
+ }
+ }
+ else {
+ _warning("got $event in done state with data $data[0]");
+ return array('wait_for_empty_line', false);
+ }
+ }
+
+ public function done($event, $data) {
+ _warning("got unhandled event $event with data $data[0]");
+ return array('done', false);
+ }
+
+}
+
+?>
Index: externals/JAXL/http/http_request.php
===================================================================
--- /dev/null
+++ externals/JAXL/http/http_request.php
@@ -0,0 +1,492 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/core/jaxl_fsm.php';
+require_once JAXL_CWD.'/http/http_multipart.php';
+
+//
+// These methods are available only once
+// $request FSM has reached 'headers_received' state
+//
+// following shortcuts are available
+// on received $request object:
+//
+// $request->{status_code_name}($headers, $body)
+// $request->{status_code_name}($body, $headers)
+//
+// $request->{status_code_name}($headers)
+// $request->{status_code_name}($body)
+//
+// following specific methods are also available:
+//
+// $request->send_line($code)
+// $request->send_header($key, $value)
+// $request->send_headers($headers)
+// $request->send_message($string)
+//
+// all the above methods can also be directly performed using:
+//
+// $request->send_response($code, $headers=array(), $body=null)
+//
+// Note: All the send_* methods do not manage connection close/keep-alive logic,
+// it is upto you to do that, by default connection will usually be dropped
+// on client disconnect if not handled by you.
+//
+class HTTPRequest extends JAXLFsm {
+
+ // peer identifier
+ public $sock = null;
+ public $ip = null;
+ public $port = null;
+
+ // request line
+ public $version = null;
+ public $method = null;
+ public $resource = null;
+ public $path = null;
+ public $query = array();
+
+ // headers and body
+ public $headers = array();
+ public $body = null;
+ public $recvd_body_len = 0;
+
+ // is true if 'Expect: 100-Continue'
+ // request header has been seen
+ public $expect = false;
+
+ // set if there is Content-Type: multipart/form-data; boundary=...
+ // header already seen
+ public $multipart = null;
+
+ // callback for send/read/close actions on accepted sock
+ private $_send_cb = null;
+ private $_read_cb = null;
+ private $_close_cb = null;
+
+ private $shortcuts = array(
+ 'ok' => 200, // 2xx
+ 'redirect' => 302, 'not_modified' => 304, // 3xx
+ 'not_found' => 404, 'bad_request' => 400, // 4xx
+ 'internal_error' => 500, // 5xx
+ 'recv_body' => true, 'close' => true // others
+ );
+
+ public function __construct($sock, $addr) {
+ $this->sock = $sock;
+
+ $addr = explode(":", $addr);
+ $this->ip = $addr[0];
+ if(sizeof($addr) == 2) {
+ $this->port = $addr[1];
+ }
+
+ parent::__construct("setup");
+ }
+
+ public function __destruct() {
+ _debug("http request going down in ".$this->state." state");
+ }
+
+ public function state() {
+ return $this->state;
+ }
+
+ //
+ // abstract method implementation
+ //
+
+ public function handle_invalid_state($r) {
+ _debug("handle invalid state called with");
+ var_dump($r);
+ }
+
+ //
+ // fsm States
+ //
+
+ public function setup($event, $args) {
+ switch($event) {
+ case 'set_sock_cb':
+ $this->_send_cb = $args[0];
+ $this->_read_cb = $args[1];
+ $this->_close_cb = $args[2];
+ return 'wait_for_request_line';
+ break;
+ default:
+ _warning("uncatched $event");
+ return 'setup';
+ }
+ }
+
+ public function wait_for_request_line($event, $args) {
+ switch($event) {
+ case 'line':
+ $this->_line($args[0], $args[1], $args[2]);
+ return 'wait_for_headers';
+ break;
+ default:
+ _warning("uncatched $event");
+ return 'wait_for_request_line';
+ }
+ }
+
+ public function wait_for_headers($event, $args) {
+ switch($event) {
+ case 'set_header':
+ $this->set_header($args[0], $args[1]);
+ return 'wait_for_headers';
+ break;
+ case 'empty_line':
+ return 'maybe_headers_received';
+ default:
+ _warning("uncatched $event");
+ return 'wait_for_headers';
+ }
+ }
+
+ public function maybe_headers_received($event, $args) {
+ switch($event) {
+ case 'set_header':
+ $this->set_header($args[0], $args[1]);
+ return 'wait_for_headers';
+ break;
+ case 'empty_line':
+ return 'headers_received';
+ break;
+ case 'body':
+ return $this->wait_for_body($event, $args);
+ break;
+ default:
+ _warning("uncatched $event");
+ return 'maybe_headers_received';
+ }
+ }
+
+ public function wait_for_body($event, $args) {
+ switch($event) {
+ case 'body':
+ $content_length = $this->headers['Content-Length'];
+ $rcvd = $args[0];
+ $rcvd_len = strlen($rcvd);
+ $this->recvd_body_len += $rcvd_len;
+
+ if($this->body === null) $this->body = $rcvd;
+ else $this->body .= $rcvd;
+
+ if($this->multipart) {
+ // boundary start, content_disposition, form data, boundary start, ....., boundary end
+ // these define various states of a multipart/form-data
+ $form_data = explode("\r\n", $rcvd);
+ foreach($form_data as $data) {
+ //_debug("passing $data to multipart fsm");
+ if(!$this->multipart->process($data)) {
+ _debug("multipart fsm returned false");
+ $this->_close();
+ return array('closed', false);
+ }
+ }
+ }
+
+ if($this->recvd_body_len < $content_length && $this->multipart->state() != 'done') {
+ _debug("rcvd body len: $this->recvd_body_len/$content_length");
+ return 'wait_for_body';
+ }
+ else {
+ _debug("all data received, switching state for dispatch");
+ return 'headers_received';
+ }
+ break;
+ case 'set_header':
+ $content_length = $this->headers['Content-Length'];
+ $body = implode(":", $args);
+ $rcvd_len = strlen($body);
+ $this->recvd_body_len += $rcvd_len;
+
+ if(!$this->multipart->process($body)) {
+ _debug("multipart fsm returned false");
+ $this->_close();
+ return array('closed', false);
+ }
+
+ if($this->recvd_body_len < $content_length) {
+ _debug("rcvd body len: $this->recvd_body_len/$content_length");
+ return 'wait_for_body';
+ }
+ else {
+ _debug("all data received, switching state for dispatch");
+ return 'headers_received';
+ }
+ break;
+ case 'empty_line':
+ $content_length = $this->headers['Content-Length'];
+
+ if(!$this->multipart->process('')) {
+ _debug("multipart fsm returned false");
+ $this->_close();
+ return array('closed', false);
+ }
+
+ if($this->recvd_body_len < $content_length) {
+ _debug("rcvd body len: $this->recvd_body_len/$content_length");
+ return 'wait_for_body';
+ }
+ else {
+ _debug("all data received, switching state for dispatch");
+ return 'headers_received';
+ }
+ break;
+ default:
+ _warning("uncatched $event");
+ return 'wait_for_body';
+ }
+ }
+
+ // headers and may be body received
+ public function headers_received($event, $args) {
+ switch($event) {
+ case 'empty_line':
+ return 'headers_received';
+ break;
+ default:
+ if(substr($event, 0, 5) == 'send_') {
+ $protected = '_'.$event;
+ if(method_exists($this, $protected)) {
+ call_user_func_array(array(&$this, $protected), $args);
+ return 'headers_received';
+ }
+ else {
+ _debug("non-existant method $event called");
+ return 'headers_received';
+ }
+ }
+ else if(@isset($this->shortcuts[$event])) {
+ return $this->handle_shortcut($event, $args);
+ }
+ else {
+ _warning("uncatched $event ".$args[0]);
+ return 'headers_received';
+ }
+ }
+ }
+
+ public function closed($event, $args) {
+ _warning("uncatched $event");
+ }
+
+ // sets input headers
+ // called internally for every header received
+ protected function set_header($k, $v) {
+ $k = trim($k); $v = ltrim($v);
+
+ // is expect header?
+ if(strtolower($k) == 'expect' && strtolower($v) == '100-continue') {
+ $this->expect = true;
+ }
+
+ // is multipart form data?
+ if(strtolower($k) == 'content-type') {
+ $ctype = explode(';', $v);
+ if(sizeof($ctype) == 2 && strtolower(trim($ctype[0])) == 'multipart/form-data') {
+ $boundary = explode('=', trim($ctype[1]));
+ if(strtolower(trim($boundary[0])) == 'boundary') {
+ _debug("multipart with boundary $boundary[1] detected");
+ $this->multipart = new HTTPMultiPart(ltrim($boundary[1]));
+ }
+ }
+ }
+
+ $this->headers[trim($k)] = trim($v);
+ }
+
+ // shortcut handler
+ protected function handle_shortcut($event, $args) {
+ _debug("executing shortcut '$event'");
+ switch($event) {
+ // http status code shortcuts
+ case 'ok':
+ case 'redirect':
+ case 'not_modified':
+ case 'bad_request':
+ case 'not_found':
+ case 'internal_error':
+ list($headers, $body) = $this->parse_shortcut_args($args);
+
+ $code = $this->shortcuts[$event];
+ $this->_send_response($code, $headers, $body);
+
+ $this->_close();
+ return 'closed';
+ break;
+ // others
+ case 'recv_body':
+ // send expect header if required
+ if($this->expect) {
+ $this->expect = false;
+ $this->_send_line(100);
+ }
+
+ // read data
+ $this->_read();
+
+ return 'wait_for_body';
+ break;
+ case 'close':
+ $this->_close();
+ return 'closed';
+ break;
+ }
+ }
+
+ private function parse_shortcut_args($args) {
+ if(sizeof($args) == 0) {
+ $body = null;
+ $headers = array();
+ }
+ if(sizeof($args) == 1) {
+ // http headers or body only received
+ if(is_array($args[0])) {
+ // http headers only
+ $headers = $args[0];
+ $body = null;
+ }
+ else {
+ // body only
+ $body = $args[0];
+ $headers = array();
+ }
+ }
+ else if(sizeof($args) == 2) {
+ // body and http headers both received
+ if(is_array($args[0])) {
+ // header first
+ $body = $args[1];
+ $headers = $args[0];
+ }
+ else {
+ // body first
+ $body = $args[0];
+ $headers = $args[1];
+ }
+ }
+
+ return array($headers, $body);
+ }
+
+ //
+ // send methods
+ // available only on 'headers_received' state
+ //
+
+ protected function _send_line($code) {
+ $raw = $this->version." ".$code." ".constant('HTTP_'.$code).HTTP_CRLF;
+ $this->_send($raw);
+ }
+
+ protected function _send_header($k, $v) {
+ $raw = $k.': '.$v.HTTP_CRLF;
+ $this->_send($raw);
+ }
+
+ protected function _send_headers($code, $headers) {
+ foreach($headers as $k=>$v)
+ $this->_send_header($k, $v);
+ }
+
+ protected function _send_body($body) {
+ $this->_send($body);
+ }
+
+ protected function _send_response($code, $headers=array(), $body=null) {
+ // send out response line
+ $this->_send_line($code);
+
+ // set content length of body exists and is not already set
+ if($body && !isset($headers['Content-Length']))
+ $headers['Content-Length'] = strlen($body);
+
+ // send out headers
+ $this->_send_headers($code, $headers);
+
+ // send body
+ // prefixed with an empty line
+ _debug("sending out HTTP_CRLF prefixed body");
+ if($body)
+ $this->_send_body(HTTP_CRLF.$body);
+ }
+
+ //
+ // internal methods
+ //
+
+ // initializes status line elements
+ private function _line($method, $resource, $version) {
+ $this->method = $method;
+ $this->resource = $resource;
+
+ $resource = explode("?", $resource);
+ $this->path = $resource[0];
+ if(sizeof($resource) == 2) {
+ $query = $resource[1];
+ $query = explode("&", $query);
+ foreach($query as $q) {
+ $q = explode("=", $q);
+ if(sizeof($q) == 1) $q[1] = "";
+ $this->query[$q[0]] = $q[1];
+ }
+ }
+
+ $this->version = $version;
+ }
+
+ private function _send($raw) {
+ call_user_func($this->_send_cb, $this->sock, $raw);
+ }
+
+ private function _read() {
+ call_user_func($this->_read_cb, $this->sock);
+ }
+
+ private function _close() {
+ call_user_func($this->_close_cb, $this->sock);
+ }
+
+
+}
+
+?>
Index: externals/JAXL/http/http_server.php
===================================================================
--- /dev/null
+++ externals/JAXL/http/http_server.php
@@ -0,0 +1,197 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/core/jaxl_logger.php';
+require_once JAXL_CWD.'/http/http_dispatcher.php';
+require_once JAXL_CWD.'/http/http_request.php';
+
+// carriage return and line feed
+define('HTTP_CRLF', "\r\n");
+
+// 1xx informational
+define('HTTP_100', "Continue");
+define('HTTP_101', "Switching Protocols");
+
+// 2xx success
+define('HTTP_200', "OK");
+
+// 3xx redirection
+define('HTTP_301', 'Moved Permanently');
+define('HTTP_304', 'Not Modified');
+
+// 4xx client error
+define('HTTP_400', 'Bad Request');
+define('HTTP_403', 'Forbidden');
+define('HTTP_404', 'Not Found');
+define('HTTP_405', 'Method Not Allowed');
+define('HTTP_499', 'Client Closed Request'); // Nginx
+
+// 5xx server error
+define('HTTP_500', 'Internal Server Error');
+define('HTTP_503', 'Service Unavailable');
+
+class HTTPServer {
+
+ private $server = null;
+ public $cb = null;
+
+ private $dispatcher = null;
+ private $requests = array();
+
+ public function __construct($port=9699, $address="127.0.0.1") {
+ $path = 'tcp://'.$address.':'.$port;
+
+ $this->server = new JAXLSocketServer(
+ $path,
+ array(&$this, 'on_accept'),
+ array(&$this, 'on_request')
+ );
+
+ $this->dispatcher = new HTTPDispatcher();
+ }
+
+ public function __destruct() {
+ $this->server = null;
+ }
+
+ public function dispatch($rules) {
+ foreach($rules as $rule) {
+ $this->dispatcher->add_rule($rule);
+ }
+ }
+
+ public function start($cb=null) {
+ $this->cb = $cb;
+ JAXLLoop::run();
+ }
+
+ public function on_accept($sock, $addr) {
+ _debug("on_accept for client#$sock, addr:$addr");
+
+ // initialize new request obj
+ $request = new HTTPRequest($sock, $addr);
+
+ // setup sock cb
+ $request->set_sock_cb(
+ array(&$this->server, 'send'),
+ array(&$this->server, 'read'),
+ array(&$this->server, 'close')
+ );
+
+ // cache request object
+ $this->requests[$sock] = &$request;
+
+ // reactive client for further read
+ $this->server->read($sock);
+ }
+
+ public function on_request($sock, $raw) {
+ _debug("on_request for client#$sock");
+ $request = $this->requests[$sock];
+
+ // 'wait_for_body' state is reached when ever
+ // application calls recv_body() method
+ // on received $request object
+ if($request->state() == 'wait_for_body') {
+ $request->body($raw);
+ }
+ else {
+ // break on crlf
+ $lines = explode(HTTP_CRLF, $raw);
+
+ // parse request line
+ if($request->state() == 'wait_for_request_line') {
+ list($method, $resource, $version) = explode(" ", $lines[0]);
+ $request->line($method, $resource, $version);
+ unset($lines[0]);
+ _info($request->ip." ".$request->method." ".$request->resource." ".$request->version);
+ }
+
+ // parse headers
+ foreach($lines as $line) {
+ $line_parts = explode(":", $line);
+
+ if(sizeof($line_parts) > 1) {
+ if(strlen($line_parts[0]) > 0) {
+ $k = $line_parts[0];
+ unset($line_parts[0]);
+ $v = implode(":", $line_parts);
+ $request->set_header($k, $v);
+ }
+ }
+ else if(strlen(trim($line_parts[0])) == 0) {
+ $request->empty_line();
+ }
+ // if exploded line array size is 1
+ // and thr is something in $line_parts[0]
+ // must be request body
+ else {
+ $request->body($line);
+ }
+ }
+ }
+
+ // if request has reached 'headers_received' state?
+ if($request->state() == 'headers_received') {
+ // dispatch to any matching rule found
+ _debug("delegating to dispatcher for further routing");
+ $dispatched = $this->dispatcher->dispatch($request);
+
+ // if no dispatch rule matched call generic callback
+ if(!$dispatched && $this->cb) {
+ _debug("no dispatch rule matched, sending to generic callback");
+ call_user_func($this->cb, $request);
+ }
+ // else if not dispatched and not generic callbacked
+ // send 404 not_found
+ else if(!$dispatched) {
+ // TODO: send 404 if no callback is registered for this request
+ _debug("dropping request since no matching dispatch rule or generic callback was specified");
+ $request->not_found('404 Not Found');
+ }
+ }
+ // if state is not 'headers_received'
+ // reactivate client socket for read event
+ else {
+ $this->server->read($sock);
+ }
+ }
+
+}
+
+?>
Index: externals/JAXL/jaxl.php
===================================================================
--- /dev/null
+++ externals/JAXL/jaxl.php
@@ -0,0 +1,809 @@
+<?php
+/**
+* Jaxl (Jabber XMPP Library)
+*
+* Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+*
+*/
+
+date_default_timezone_set("UTC");
+declare(ticks = 1);
+define('JAXL_CWD', dirname(__FILE__));
+
+require_once JAXL_CWD.'/core/jaxl_exception.php';
+require_once JAXL_CWD.'/core/jaxl_cli.php';
+require_once JAXL_CWD.'/core/jaxl_loop.php';
+require_once JAXL_CWD.'/xmpp/xmpp_stream.php';
+require_once JAXL_CWD.'/xmpp/xmpp_roster_item.php';
+require_once JAXL_CWD.'/core/jaxl_event.php';
+require_once JAXL_CWD.'/core/jaxl_logger.php';
+require_once JAXL_CWD.'/core/jaxl_socket_server.php';
+
+/**
+ * Jaxl class extends base XMPPStream class with following functionalities:
+ * 1) Adds an event based wrapper over xmpp stream lifecycle
+ * 2) Provides restart strategy and signal handling to ensure connectivity of xmpp stream
+ * 3) Roster management as specified in XMPP-IM
+ * 4) Management of XEP's inside xmpp stream lifecycle
+ * 5) Adds a logging facility
+ * 6) Adds a cron job facility in sync with connected xmpp stream timeline
+ *
+ * @author abhinavsingh
+ *
+ */
+class JAXL extends XMPPStream {
+
+ // lib meta info
+ const version = '3.0.1';
+ const name = 'JAXL :: Jabber XMPP Library';
+
+ // cached init config array
+ public $cfg = array();
+
+ // event callback engine for xmpp stream lifecycle
+ protected $ev = null;
+
+ // reference to various xep instance objects
+ public $xeps = array();
+
+ // local cache of roster list
+ public $roster = array();
+
+ // whether jaxl must also populate local roster cache with
+ // received presence information about the contacts
+ public $manage_roster = true;
+
+ // what to do with presence sub requests
+ // "none" | "accept" | "mutual"
+ public $manage_subscribe = "none";
+
+ // path variables
+ public $log_level = JAXL_INFO;
+ public $priv_dir;
+ public $tmp_dir;
+ public $log_dir;
+ public $pid_dir;
+ public $sock_dir;
+
+ // ipc utils
+ private $sock;
+ private $cli;
+
+ // env
+ public $local_ip;
+ public $pid;
+ public $mode;
+
+ // current status message
+ public $status;
+
+ // identity
+ public $features = array();
+ public $category = 'client';
+ public $type = 'bot';
+ public $lang = 'en';
+
+ // after cth failed attempt
+ // retry connect after k * $retry_interval seconds
+ // where k is a random number between 0 and 2^c - 1.
+ public $retry = true;
+ private $retry_interval = 1;
+ private $retry_attempt = 0;
+ private $retry_max_interval = 32; // 2^5 seconds (means 5 max tries)
+
+ public function __construct($config) {
+ $this->cfg = $config;
+
+ // setup logger
+ if(isset($this->cfg['log_path'])) JAXLLogger::$path = $this->cfg['log_path'];
+ //else JAXLLogger::$path = $this->log_dir."/jaxl.log";
+ if(isset($this->cfg['log_level'])) JAXLLogger::$level = $this->log_level = $this->cfg['log_level'];
+ else JAXLLogger::$level = $this->log_level;
+
+ // env
+ $strict = isset($this->cfg['strict']) ? $this->cfg['strict'] : TRUE;
+ if($strict) $this->add_exception_handlers();
+ $this->mode = PHP_SAPI;
+ $this->local_ip = gethostbyname(php_uname('n'));
+ $this->pid = getmypid();
+
+ // jid object
+ $jid = @$this->cfg['jid'] ? new XMPPJid($this->cfg['jid']) : null;
+
+ // handle signals
+ if(extension_loaded('pcntl')) {
+ pcntl_signal(SIGHUP, array($this, 'signal_handler'));
+ pcntl_signal(SIGINT, array($this, 'signal_handler'));
+ pcntl_signal(SIGTERM, array($this, 'signal_handler'));
+ }
+
+ // create .jaxl directory in JAXL_CWD
+ // for our /tmp, /run and /log folders
+ // overwrite these using jaxl config array
+ $this->priv_dir = @$this->cfg['priv_dir'] ? $this->cfg['priv_dir'] : JAXL_CWD."/.jaxl";
+ $this->tmp_dir = $this->priv_dir."/tmp";
+ $this->pid_dir = $this->priv_dir."/run";
+ $this->log_dir = $this->priv_dir."/log";
+ $this->sock_dir = $this->priv_dir."/sock";
+ if(!is_dir($this->priv_dir)) mkdir($this->priv_dir);
+ if(!is_dir($this->tmp_dir)) mkdir($this->tmp_dir);
+ if(!is_dir($this->pid_dir)) mkdir($this->pid_dir);
+ if(!is_dir($this->log_dir)) mkdir($this->log_dir);
+ if(!is_dir($this->sock_dir)) mkdir($this->sock_dir);
+
+ // touch pid file
+ if($this->mode == "cli") {
+ touch($this->get_pid_file_path());
+ _info("created pid file ".$this->get_pid_file_path());
+ }
+
+ // include mandatory xmpp xeps
+ // service discovery and entity caps
+ // are recommended for every xmpp entity
+ $this->require_xep(array('0030', '0115'));
+
+ // do dns lookup, update $cfg['host'] and $cfg['port'] if not already specified
+ $host = @$this->cfg['host'];
+ $port = @$this->cfg['port'];
+ if((!$host || !$port) && $jid) {
+ // this dns lookup is blocking
+ _info("dns srv lookup for ".$jid->domain);
+ list($host, $port) = JAXLUtil::get_dns_srv($jid->domain);
+ }
+ $this->cfg['host'] = @$this->cfg['host'] ? $this->cfg['host'] : $host;
+ $this->cfg['port'] = @$this->cfg['port'] ? $this->cfg['port'] : $port;
+
+ // choose appropriate transport
+ // if 'bosh_url' cfg is defined include 0206
+ if(@$this->cfg['bosh_url']) {
+ _debug("including bosh xep");
+ $this->require_xep('0206');
+ $transport = $this->xeps['0206'];
+ }
+ else {
+ //list($host, $port) = JAXLUtil::get_dns_srv($jid->domain);
+ $stream_context = @$this->cfg['stream_context'];
+ $transport = new JAXLSocketClient($stream_context);
+ }
+
+ // lifecycle events callback
+ $this->ev = new JAXLEvent(defined('JAXL_MULTI_CLIENT') ? array(&$this) : array());
+
+ // initialize xmpp stream with configured transport
+ parent::__construct(
+ $transport,
+ $jid,
+ @$this->cfg['pass'],
+ @$this->cfg['resource'] ? 'jaxl#'.$this->cfg['resource'] : 'jaxl#'.md5(time()),
+ @$this->cfg['force_tls']
+ );
+ }
+
+ public function __destruct() {
+ // delete pid file
+ _info("cleaning up pid and unix sock files");
+ @unlink($this->get_pid_file_path());
+ @unlink($this->get_sock_file_path());
+
+ parent::__destruct();
+ }
+
+ public function add_exception_handlers() {
+ _info("strict mode enabled, adding exception handlers. Set 'strict'=>TRUE inside JAXL config to disable this");
+ set_error_handler(array('JAXLException', 'error_handler'));
+ set_exception_handler(array('JAXLException', 'exception_handler'));
+ register_shutdown_function(array('JAXLException', 'shutdown_handler'));
+ }
+
+ public function get_pid_file_path() {
+ return $this->pid_dir."/jaxl_".$this->pid.".pid";
+ }
+
+ public function get_sock_file_path() {
+ return $this->sock_dir."/jaxl_".$this->pid.".sock";
+ }
+
+ public function require_xep($xeps) {
+ if(!is_array($xeps))
+ $xeps = array($xeps);
+
+ foreach($xeps as $xep) {
+ $filename = 'xep_'.$xep.'.php';
+ $classname = 'XEP_'.$xep;
+
+ // include xep
+ require_once JAXL_CWD.'/xep/'.$filename;
+ $this->xeps[$xep] = new $classname($this);
+
+ // add necessary requested callback on events
+ foreach($this->xeps[$xep]->init() as $ev=>$cb) {
+ $this->add_cb($ev, array($this->xeps[$xep], $cb));
+ }
+ }
+ }
+
+ public function add_cb($ev, $cb, $pri=1) {
+ return $this->ev->add($ev, $cb, $pri);
+ }
+
+ public function del_cb($ref) {
+ $this->ev->del($ref);
+ }
+
+ public function set_status($status, $show='chat', $priority=10) {
+ $this->send($this->get_pres_pkt(
+ array(),
+ $status,
+ $show,
+ $priority
+ ));
+ }
+
+ public function send_chat_msg($to, $body, $thread=null, $subject=null) {
+ $msg = new XMPPMsg(
+ array(
+ 'type'=>'chat',
+ 'to'=>$to,
+ 'from'=>$this->full_jid->to_string()
+ ),
+ $body,
+ $thread,
+ $subject
+ );
+ $this->send($msg);
+ }
+
+ public function get_vcard($jid=null, $cb=null) {
+ $attrs = array(
+ 'type'=>'get',
+ 'from'=>$this->full_jid->to_string()
+ );
+
+ if($jid) {
+ $jid = new XMPPJid($jid);
+ $attrs['to'] = $jid->node."@".$jid->domain;
+ }
+
+ $pkt = $this->get_iq_pkt(
+ $attrs,
+ new JAXLXml('vCard', 'vcard-temp')
+ );
+ if($cb) $this->add_cb('on_stanza_id_'.$pkt->id, $cb);
+ $this->send($pkt);
+ }
+
+ public function get_roster($cb=null) {
+ $pkt = $this->get_iq_pkt(
+ array(
+ 'type'=>'get',
+ 'from'=>$this->full_jid->to_string()
+ ),
+ new JAXLXml('query', 'jabber:iq:roster')
+ );
+ if($cb) $this->add_cb('on_stanza_id_'.$pkt->id, $cb);
+ $this->send($pkt);
+ }
+
+ public function subscribe($to) {
+ $this->send($this->get_pres_pkt(
+ array('to'=>$to, 'type'=>'subscribe')
+ ));
+ }
+
+ public function subscribed($to) {
+ $this->send($this->get_pres_pkt(
+ array('to'=>$to, 'type'=>'subscribed')
+ ));
+ }
+
+ public function unsubscribe($to) {
+ $this->send($this->get_pres_pkt(
+ array('to'=>$to, 'type'=>'unsubscribe')
+ ));
+ }
+
+ public function unsubscribed($to) {
+ $this->send($this->get_pres_pkt(
+ array('to'=>$to, 'type'=>'unsubscribed')
+ ));
+ }
+
+ public function get_socket_path() {
+ return ($this->cfg['port'] == 5223 ? "ssl" : "tcp")."://".$this->cfg['host'].":".$this->cfg['port'];
+ }
+
+ public function retry() {
+ $retry_after = pow(2, $this->retry_attempt) * $this->retry_interval;
+ $this->retry_attempt++;
+ _info("Will try to restart in ".$retry_after." seconds");
+
+ // TODO: use jaxl cron if sigalarms cannnot be used
+ sleep($retry_after);
+ $this->start();
+ }
+
+ public function start($opts=array()) {
+ // is bosh bot?
+ if(@$this->cfg['bosh_url']) {
+ $this->trans->session_start();
+
+ for(;;) {
+ // while any of the curl request is pending
+ // keep receiving response
+ while(sizeof($this->trans->chs) != 0) {
+ $this->trans->recv();
+ }
+
+ // if no request in queue, ping bosh end point
+ // and repeat recv
+ $this->trans->ping();
+ }
+
+ $this->trans->session_end();
+ return;
+ }
+
+ // is xmpp client or component?
+ // if on_connect event have no callbacks
+ // set default on_connect callback to $this->start_stream()
+ // i.e. xmpp client mode
+ if(!$this->ev->exists('on_connect'))
+ $this->add_cb('on_connect', array($this, 'start_stream'));
+
+ // connect to the destination host/port
+ if($this->connect($this->get_socket_path())) {
+ // reset in case we connected back after retries
+ $this->retry_attempt = 0;
+
+ // emit
+ $this->ev->emit('on_connect');
+
+ // parse opts
+ if(@$opts['--with-debug-shell']) $this->enable_debug_shell();
+ if(@$opts['--with-unix-sock']) $this->enable_unix_sock();
+
+ // run main loop
+ JAXLLoop::run();
+
+ // emit
+ $this->ev->emit('on_disconnect');
+ }
+ // if connection to the destination fails
+ else {
+ if($this->trans->errno == 61
+ || $this->trans->errno == 110
+ || $this->trans->errno == 111
+ ) {
+ _debug("unable to connect with errno ".$this->trans->errno." (".$this->trans->errstr.")");
+ $this->retry();
+ }
+ else {
+ $this->ev->emit('on_connect_error', array(
+ $this->trans->errno,
+ $this->trans->errstr
+ ));
+ }
+ }
+ }
+
+ //
+ // callback methods
+ //
+
+ // signals callback handler
+ // not for public api consumption
+ public function signal_handler($sig) {
+ $this->end_stream();
+ $this->disconnect();
+ $this->ev->emit('on_disconnect');
+
+ switch($sig) {
+ // terminal line hangup
+ case SIGHUP:
+ _debug("got sighup");
+ break;
+ // interrupt program
+ case SIGINT:
+ _debug("got sigint");
+ break;
+ // software termination signal
+ case SIGTERM:
+ _debug("got sigterm");
+ break;
+ }
+
+ exit;
+ }
+
+ // called internally for ipc
+ // not for public consumption
+ public function on_unix_sock_accept($_c, $addr) {
+ $this->sock->read($_c);
+ }
+
+ // this currently simply evals the incoming raw string
+ // know what you are doing while in production
+ public function on_unix_sock_request($_c, $_raw) {
+ _debug("evaling raw string rcvd over unix sock: ".$_raw);
+ $this->sock->send($_c, serialize(eval($_raw)));
+ $this->sock->read($_c);
+ }
+
+ public function enable_unix_sock() {
+ $this->sock = new JAXLSocketServer(
+ 'unix://'.$this->get_sock_file_path(),
+ array(&$this, 'on_unix_sock_accept'),
+ array(&$this, 'on_unix_sock_request')
+ );
+ }
+
+ // this simply eval the incoming raw data
+ // inside current jaxl environment
+ // security is all upto you, no checks made here
+ public function handle_debug_shell($_raw) {
+ print_r(eval($_raw));
+ echo PHP_EOL;
+ JAXLCli::prompt();
+ }
+
+ protected function enable_debug_shell() {
+ $this->cli = new JAXLCli(array(&$this, 'handle_debug_shell'));
+ JAXLCli::prompt();
+ }
+
+ //
+ // abstract method implementation
+ //
+
+ protected function send_fb_challenge_response($challenge) {
+ $this->send($this->get_fb_challenge_response_pkt($challenge));
+ }
+
+ // refer https://developers.facebook.com/docs/chat/#jabber
+ public function get_fb_challenge_response_pkt($challenge) {
+ $stanza = new JAXLXml('response', NS_SASL);
+
+ $challenge = base64_decode($challenge);
+ $challenge = urldecode($challenge);
+ parse_str($challenge, $challenge_arr);
+
+ $response = http_build_query(array(
+ 'method' => $challenge_arr['method'],
+ 'nonce' => $challenge_arr['nonce'],
+ 'access_token' => $this->cfg['fb_access_token'],
+ 'api_key' => $this->cfg['fb_app_key'],
+ 'call_id' => 0,
+ 'v' => '1.0'
+ ));
+
+ $stanza->t(base64_encode($response));
+ return $stanza;
+ }
+
+ public function wait_for_fb_sasl_response($event, $args) {
+ switch($event) {
+ case "stanza_cb":
+ $stanza = $args[0];
+
+ if($stanza->name == 'challenge' && $stanza->ns == NS_SASL) {
+ $challenge = $stanza->text;
+ $this->send_fb_challenge_response($challenge);
+ return "wait_for_sasl_response";
+ }
+ else {
+ _debug("got unhandled sasl response, should never happen here");
+ exit;
+ }
+ break;
+ default:
+ _debug("not catched $event, should never happen here");
+ exit;
+ break;
+ }
+ }
+
+ // someday this needs to go inside xmpp stream
+ public function wait_for_cram_md5_response($event, $args) {
+ switch($event) {
+ case "stanza_cb":
+ $stanza = $args[0];
+
+ if($stanza->name == 'challenge' && $stanza->ns == NS_SASL) {
+ $challenge = base64_decode($stanza->text);
+ $resp = new JAXLXml('response', NS_SASL);
+ $resp->t(base64_encode($this->jid->to_string().' '.hash_hmac('md5', $challenge, $this->pass)));
+ $this->send($resp);
+ return "wait_for_sasl_response";
+ }
+ else {
+ _debug("got unhandled sasl response, should never happen here");
+ exit;
+ }
+ break;
+ default:
+ _debug("not catched $event, should never happen here");
+ exit;
+ break;
+ }
+ }
+
+ // http://tools.ietf.org/html/rfc5802#section-5
+ public function get_scram_sha1_response($pass, $challenge) {
+ // it contains users iteration count i and the user salt
+ // also server will append it's own nonce to the one we specified
+ $decoded = $this->explode_data(base64_decode($challenge));
+
+ // r=,s=,i=
+ $nonce = $decoded['r'];
+ $salt = base64_decode($decoded['s']);
+ $iteration = intval($decoded['i']);
+
+ // SaltedPassword := Hi(Normalize(password), salt, i)
+ $salted = JAXLUtil::pbkdf2($this->pass, $salt, $iteration);
+ // ClientKey := HMAC(SaltedPassword, "Client Key")
+ $client_key = hash_hmac('sha1', $salted, "Client Key", true);
+ // StoredKey := H(ClientKey)
+ $stored_key = hash('sha1', $client_key, true);
+ // AuthMessage := client-first-message-bare + "," + server-first-message + "," + client-final-message-without-proof
+ $auth_message = '';
+ // ClientSignature := HMAC(StoredKey, AuthMessage)
+ $signature = hash_hmac('sha1', $stored_key, $auth_message, true);
+ // ClientProof := ClientKey XOR ClientSignature
+ $client_proof = $client_key ^ $signature;
+
+ $proof = 'c=biws,r='.$nonce.',p='.base64_encode($client_proof);
+ return base64_encode($proof);
+ }
+
+ public function wait_for_scram_sha1_response($event, $args) {
+ switch($event) {
+ case "stanza_cb":
+ $stanza = $args[0];
+
+ if($stanza->name == 'challenge' && $stanza->ns == NS_SASL) {
+ $challenge = $stanza->text;
+
+ $resp = new JAXLXml('response', NS_SASL);
+ $resp->t($this->get_scram_sha1_response($this->pass, $challenge));
+ $this->send($resp);
+
+ return "wait_for_sasl_response";
+ }
+ else {
+ _debug("got unhandled sasl response, should never happen here");
+ exit;
+ }
+ break;
+ default:
+ _debug("not catched $event, should never happen here");
+ exit;
+ break;
+ }
+ }
+
+ public function handle_auth_mechs($stanza, $mechanisms) {
+ if($this->ev->exists('on_stream_features')) {
+ return $this->ev->emit('on_stream_features', array($stanza));
+ }
+
+ // extract available mechanisms
+ $mechs = array();
+ if($mechanisms) foreach($mechanisms->childrens as $mechanism) $mechs[$mechanism->text] = true;
+
+ // check if preferred auth type exists in available mechanisms
+ $pref_auth = @$this->cfg['auth_type'] ? $this->cfg['auth_type'] : 'PLAIN';
+ $pref_auth_exists = isset($mechs[$pref_auth]) ? true : false;
+ _debug("pref_auth ".$pref_auth." ".($pref_auth_exists ? "exists" : "doesn't exists"));
+
+ // if pref auth exists, try it
+ if($pref_auth_exists) {
+ $mech = $pref_auth;
+ }
+ // if pref auth doesn't exists, choose one from available mechanisms
+ else {
+ foreach($mechs as $mech=>$any) {
+ // choose X-FACEBOOK-PLATFORM only if fb_access_token config value is available
+ if($mech == 'X-FACEBOOK-PLATFORM') {
+ if(@$this->cfg['fb_access_token']) {
+ break;
+ }
+ }
+ // else try first of the available methods
+ else {
+ break;
+ }
+ }
+ _error("preferred auth type not supported, trying $mech");
+ }
+
+ $this->send_auth_pkt($mech, @$this->jid ? $this->jid->to_string() : null, @$this->pass);
+
+ if($pref_auth == 'X-FACEBOOK-PLATFORM') {
+ return "wait_for_fb_sasl_response";
+ }
+ else if($pref_auth == 'CRAM-MD5') {
+ return "wait_for_cram_md5_response";
+ }
+ else if($pref_auth == 'SCRAM-SHA-1') {
+ return "wait_for_scram_sha1_response";
+ }
+ }
+
+ public function handle_auth_success() {
+ // if not a component
+ /*if(!@$this->xeps['0114']) {
+ $this->xeps['0030']->get_info($this->full_jid->domain, array(&$this, 'handle_domain_info'));
+ $this->xeps['0030']->get_items($this->full_jid->domain, array(&$this, 'handle_domain_items'));
+ }*/
+
+ $this->ev->emit('on_auth_success');
+ }
+
+ public function handle_auth_failure($reason) {
+ $this->ev->emit('on_auth_failure', array(
+ $reason
+ ));
+ }
+
+ public function handle_stream_start($stanza) {
+ $stanza = new XMPPStanza($stanza);
+
+ $this->ev->emit('on_stream_start', array($stanza));
+ return array(@$this->cfg['bosh_url'] ? 'wait_for_stream_features' : 'connected', 1);
+ }
+
+ public function handle_iq($stanza) {
+ $stanza = new XMPPStanza($stanza);
+
+ // emit callback registered on stanza id's
+ $emited = false;
+ if($stanza->id && $this->ev->exists('on_stanza_id_'.$stanza->id)) {
+ //_debug("on stanza id callbackd");
+ $emited = true;
+ $this->ev->emit('on_stanza_id_'.$stanza->id, array($stanza));
+ }
+
+ // catch roster list
+ if($stanza->type == 'result' && ($query = $stanza->exists('query', 'jabber:iq:roster'))) {
+ foreach($query->childrens as $child) {
+ if($child->name == 'item') {
+ $jid = $child->attrs['jid'];
+ $subscription = $child->attrs['subscription'];
+
+ $groups = array();
+ foreach($child->childrens as $group) {
+ if($group->name == 'group') {
+ $groups[] = $group->text;
+ }
+ }
+
+ $this->roster[$jid] = new XMPPRosterItem($jid, $subscription, $groups);
+ }
+ }
+
+ // emit this event if not emited above
+ if(!$emited)
+ $this->ev->emit('on_roster_update');
+ }
+
+ // if managing roster
+ // catch contact vcard results
+ if($this->manage_roster && $stanza->type == 'result' && ($query = $stanza->exists('vCard', 'vcard-temp'))) {
+ if(@$this->roster[$stanza->from])
+ $this->roster[$stanza->from]->vcard = $query;
+ }
+
+ // on_get_iq, on_result_iq, and other events are only
+ // emitted if on_stanza_id_{id} wasn't emitted above
+ // TODO: can we add more checks here before calling back
+ // e.g. checks on existence of an attribute, check on 1st level child ns and so on
+ if(!$emited)
+ $this->ev->emit('on_'.$stanza->type.'_iq', array($stanza));
+ }
+
+ public function handle_presence($stanza) {
+ $stanza = new XMPPStanza($stanza);
+
+ // if managing roster
+ // catch available/unavailable type stanza
+ if($this->manage_roster) {
+ $type = ($stanza->type ? $stanza->type : "available");
+ $jid = new XMPPJid($stanza->from);
+
+ if($type == 'available') {
+ $this->roster[$jid->bare]->resources[$jid->resource] = $stanza;
+ }
+ else if($type == 'unavailable') {
+ if(@$this->roster[$jid->bare] && @$this->roster[$jid->bare]->resources[$jid->resource])
+ unset($this->roster[$jid->bare]->resources[$jid->resource]);
+ }
+ }
+
+ // if managing subscription requests
+ // we need to automate stuff here
+ if($stanza->type == "subscribe" && $this->manage_subscribe != "none") {
+ $this->subscribed($stanza->from);
+ if($this->manage_subscribe == "mutual")
+ $this->subscribe($stanza->from);
+ }
+
+ $this->ev->emit('on_presence_stanza', array($stanza));
+ }
+
+ public function handle_message($stanza) {
+ $stanza = new XMPPStanza($stanza);
+ $stanza->type = (@$stanza->type ? $stanza->type : 'normal');
+ $this->ev->emit('on_'.$stanza->type.'_message', array($stanza));
+ }
+
+ // unhandled event and arguments bubbled up
+ // TODO: in a lot of cases this will be called, need more checks
+ public function handle_other($event, $args) {
+ $stanza = $args[0];
+ $stanza = new XMPPStanza($stanza);
+ $ev = 'on_'.$stanza->name.'_stanza';
+ if($this->ev->exists($ev)) {
+ return $this->ev->emit($ev, array($stanza));
+ }
+ else {
+ _warning("event '".$event."' catched in handle_other with stanza name ".$stanza->name);
+ }
+ }
+
+ public function handle_domain_info($stanza) {
+ $query = $stanza->exists('query', NS_DISCO_INFO);
+ foreach($query->childrens as $k=>$child) {
+ if($child->name == 'identity') {
+ //echo 'identity category:'.@$child->attrs['category'].', type:'.@$child->attrs['type'].', name:'.@$child->attrs['name'].PHP_EOL;
+ }
+ else if($child->name == 'x') {
+ //echo 'x ns:'.$child->ns.PHP_EOL;
+ }
+ else if($child->name == 'feature') {
+ //echo 'feature var:'.$child->attrs['var'].PHP_EOL;
+ }
+ }
+ }
+
+ public function handle_domain_items($stanza) {
+ $query = $stanza->exists('query', NS_DISCO_ITEMS);
+ foreach($query->childrens as $k=>$child) {
+ if($child->name == 'item') {
+ //echo 'item jid:'.@$child->attrs['jid'].', name:'.@$child->attrs['name'].', node:'.@$child->attrs['node'].PHP_EOL;
+ }
+ }
+ }
+
+}
+
+?>
Index: externals/JAXL/jaxlctl
===================================================================
--- /dev/null
+++ externals/JAXL/jaxlctl
@@ -0,0 +1,190 @@
+#!/usr/bin/env php
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+$params = $argv;
+$exe = array_shift($params);
+$command = array_shift($params);
+
+require_once 'jaxl.php';
+JAXLLogger::$level = JAXL_INFO;
+
+// TODO: an abstract JAXLCtlCommand class
+// with seperate class per command
+// a mechanism to register new commands
+class JAXLCtl {
+
+ protected $ipc = null;
+
+ protected $buffer = '';
+ protected $buffer_cb = null;
+ protected $cli = null;
+ public $dots = "....... ";
+
+ protected $symbols = array();
+
+ public function __construct($command, $params) {
+ global $exe;
+
+ if(method_exists(&$this, $command)) {
+ $r = call_user_func_array(array(&$this, $command), $params);
+ if(sizeof($r) == 2) {
+ list($buffer_cb, $quit_cb) = $r;
+ $this->buffer_cb = $buffer_cb;
+ $this->cli = new JAXLCli(array(&$this, 'on_terminal_input'), $quit_cb);
+ $this->run();
+ }
+ else {
+ _colorize("oops! internal command error", JAXL_ERROR);
+ exit;
+ }
+ }
+ else {
+ _colorize("error: invalid command '$command' received", JAXL_ERROR);
+ _colorize("type '$exe help' for list of available commands", JAXL_NOTICE);
+ exit;
+ }
+ }
+
+ public function run() {
+ JAXLCli::prompt();
+ JAXLLoop::run();
+ }
+
+ public function on_terminal_input($raw) {
+ $raw = trim($raw);
+ $last = substr($raw, -1, 1);
+
+ if($last == ";") {
+ // dispatch to buffer callback
+ call_user_func($this->buffer_cb, $this->buffer.$raw);
+ $this->buffer = '';
+ }
+ else if($last == '\\') {
+ $this->buffer .= substr($raw, 0, -1);
+ echo $this->dots;
+ }
+ else {
+ // buffer command
+ $this->buffer .= $raw."; ";
+ echo $this->dots;
+ }
+ }
+
+ public static function print_help() {
+ global $exe;
+ _colorize("Usage: $exe command [options...]\n", JAXL_INFO);
+ _colorize("Commands:", JAXL_NOTICE);
+ _colorize(" help This help text", JAXL_DEBUG);
+ _colorize(" debug Attach a debug console to a running JAXL daemon", JAXL_DEBUG);
+ _colorize(" shell Open up Jaxl shell emulator", JAXL_DEBUG);
+ echo "\n";
+ }
+
+ protected function help() {
+ JAXLCtl::print_help();
+ exit;
+ }
+
+ //
+ // shell command
+ //
+
+ protected function shell() {
+ return array(array(&$this, 'on_shell_input'), array(&$this, 'on_shell_quit'));
+ }
+
+ private function _eval($raw, $symbols) {
+ extract($symbols);
+
+ eval($raw);
+ $g = get_defined_vars();
+
+ unset($g['raw']);
+ unset($g['symbols']);
+ return $g;
+ }
+
+ public function on_shell_input($raw) {
+ $this->symbols = $this->_eval($raw, $this->symbols);
+ JAXLCli::prompt();
+ }
+
+ public function on_shell_quit() {
+ exit;
+ }
+
+ //
+ // debug command
+ //
+
+ protected function debug($sock_path) {
+ $this->ipc = new JAXLSocketClient();
+ $this->ipc->set_callback(array(&$this, 'on_debug_response'));
+ $this->ipc->connect('unix://'.$sock_path);
+ return array(array(&$this, 'on_debug_input'), array(&$this, 'on_debug_quit'));
+ }
+
+ public function on_debug_response($raw) {
+ $ret = unserialize($raw);
+ print_r($ret);
+ echo "\n";
+ JAXLCli::prompt();
+ }
+
+ public function on_debug_input($raw) {
+ $this->ipc->send($this->buffer.$raw);
+ }
+
+ public function on_debug_quit() {
+ $this->ipc->disconnect();
+ exit;
+ }
+
+}
+
+// we atleast need a command argument
+if($argc < 2) {
+ JAXLCtl::print_help();
+ exit;
+}
+
+$ctl = new JAXLCtl($command, $params);
+echo "done\n";
+
+?>
Index: externals/JAXL/tests/test_jaxl_event.php
===================================================================
--- /dev/null
+++ externals/JAXL/tests/test_jaxl_event.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// TODO: support for php unit and add more tests
+error_reporting(E_ALL);
+require_once "jaxl.php";
+
+/**
+ *
+ * @author abhinavsingh
+ *
+ */
+class JAXLEventTest extends PHPUnit_Framework_TestCase {
+
+ function test_jaxl_event() {
+ $ev = new JAXLEvent();
+
+ $ref1 = $ev->add('on_connect', 'some_func', 0);
+ $ref2 = $ev->add('on_connect', 'some_func1', 0);
+ $ref3 = $ev->add('on_connect', 'some_func2', 1);
+ $ref4 = $ev->add('on_connect', 'some_func3', 4);
+ $ref5 = $ev->add('on_disconnect', 'some_func', 1);
+ $ref6 = $ev->add('on_disconnect', 'some_func1', 1);
+
+ //$ev->emit('on_connect', null);
+
+ $ev->del($ref2);
+ $ev->del($ref1);
+ $ev->del($ref6);
+ $ev->del($ref5);
+ $ev->del($ref4);
+ $ev->del($ref3);
+
+ //print_r($ev->reg);
+ }
+
+}
Index: externals/JAXL/tests/test_jaxl_socket_client.php
===================================================================
--- /dev/null
+++ externals/JAXL/tests/test_jaxl_socket_client.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// TODO: support for php unit and add more tests
+error_reporting(E_ALL);
+require_once "jaxl.php";
+
+/**
+ *
+ * @author abhinavsingh
+ *
+ */
+class JAXLSocketClientTest extends PHPUnit_Framework_TestCase {
+
+ function test_jaxl_socket_client() {
+ $sock = new JAXLSocketClient("127.0.0.1", 5222);
+ $sock->connect();
+
+ $sock->send("<stream:stream>");
+ while($sock->fd) {
+ $sock->recv();
+ }
+ }
+
+}
Index: externals/JAXL/tests/test_jaxl_xml_stream.php
===================================================================
--- /dev/null
+++ externals/JAXL/tests/test_jaxl_xml_stream.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// TODO: support for php unit and add more tests
+error_reporting(E_ALL);
+require_once "jaxl.php";
+
+/**
+ *
+ * @author abhinavsingh
+ *
+ */
+class JAXLXmlStreamTest extends PHPUnit_Framework_TestCase {
+
+ function xml_start_cb($node) {
+ $this->assertEquals('stream', $node->name);
+ $this->assertEquals(NS_XMPP, $node->ns);
+ }
+
+ function xml_end_cb($node) {
+ $this->assertEquals('stream', $node->name);
+ }
+
+ function xml_stanza_cb($node) {
+ $this->assertEquals('features', $node->name);
+ $this->assertEquals(1, sizeof($node->childrens));
+ }
+
+ function test_xml_stream_callbacks() {
+ $xml = new JAXLXmlStream();
+ $xml->set_callback(array(&$this, "xml_start_cb"), array(&$this, "xml_end_cb"), array(&$this, "xml_stanza_cb"));
+ $xml->parse('<stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client">');
+ $xml->parse('<features>');
+ $xml->parse('<mechanisms>');
+ $xml->parse('</mechanisms>');
+ $xml->parse('</features>');
+ $xml->parse('</stream:stream>');
+ }
+}
Index: externals/JAXL/tests/test_xmpp_jid.php
===================================================================
--- /dev/null
+++ externals/JAXL/tests/test_xmpp_jid.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// TODO: support for php unit and add more tests
+error_reporting(E_ALL);
+require_once "jaxl.php";
+
+/**
+ *
+ * @author abhinavsingh
+ *
+ */
+class XMPPJidTest extends PHPUnit_Framework_TestCase {
+
+ function test_xmpp_jid_construct() {
+ $jid = new XMPPJid("1@domain.tld/res");
+ $this->assertEquals('1@domain.tld/res', $jid->to_string());
+
+ $jid = new XMPPJid("domain.tld/res");
+ $this->assertEquals('domain.tld/res', $jid->to_string());
+
+ $jid = new XMPPJid("component.domain.tld");
+ $this->assertEquals('component.domain.tld', $jid->to_string());
+
+ $jid = new XMPPJid("1@domain.tld");
+ $this->assertEquals('1@domain.tld', $jid->to_string());
+ }
+}
Index: externals/JAXL/tests/test_xmpp_msg.php
===================================================================
--- /dev/null
+++ externals/JAXL/tests/test_xmpp_msg.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// TODO: support for php unit and add more tests
+error_reporting(E_ALL);
+require_once "jaxl.php";
+
+/**
+ *
+ * @author abhinavsingh
+ *
+ */
+class XMPPMsgTest extends PHPUnit_Framework_TestCase {
+
+ function test_xmpp_msg() {
+ $msg = new XMPPMsg(array('to'=>'2@w.c', 'from'=>'-0@q.p/~', 'type'=>'chat'), 'hi', 'thread1');
+
+ echo $msg->to.PHP_EOL;
+ echo $msg->to_node.PHP_EOL;
+ echo $msg->from.PHP_EOL;
+ echo $msg->to_string().PHP_EOL;
+
+ $msg->to = '4@w.c/sp';
+ $msg->body = 'hello world';
+ $msg->subject = 'some subject';
+
+ echo $msg->to.PHP_EOL;
+ echo $msg->to_node.PHP_EOL;
+ echo $msg->from.PHP_EOL;
+ echo $msg->to_string().PHP_EOL;
+ }
+
+}
Index: externals/JAXL/tests/test_xmpp_stanza.php
===================================================================
--- /dev/null
+++ externals/JAXL/tests/test_xmpp_stanza.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// TODO: support for php unit and add more tests
+error_reporting(E_ALL);
+require_once "jaxl.php";
+
+/**
+ *
+ * @author abhinavsingh
+ *
+ */
+class XMPPStanzaTest extends PHPUnit_Framework_TestCase {
+
+ function test_xmpp_stanza_nested() {
+ $stanza = new JAXLXml('message', array('to'=>'1@a.z', 'from'=>'2@b.c'));
+ $stanza
+ ->c('body')->attrs(array('xml:lang'=>'en'))->t('hello')->up()
+ ->c('thread')->t('1234')->up()
+ ->c('nested')
+ ->c('nest')->t('nest1')->up()
+ ->c('nest')->t('nest2')->up()
+ ->c('nest')->t('nest3')->up()->up()
+ ->c('c')->attrs(array('hash'=>'84jsdmnskd'));
+
+ $this->assertEquals(
+ '<message to="1@a.z" from="2@b.c"><body xml:lang="en">hello</body><thread>1234</thread><nested><nest>nest1</nest><nest>nest2</nest><nest>nest3</nest></nested><c hash="84jsdmnskd"></c></message>',
+ $stanza->to_string()
+ );
+ }
+
+ function test_xmpp_stanza_from_jaxl_xml() {
+ // xml to stanza test
+ $xml = new JAXLXml('message', NS_JABBER_CLIENT, array('to'=>'2@3.com', 'from'=>'4@r.p/q'));
+ $stanza = new XMPPStanza($xml);
+ $stanza->c('body')->t('hello world');
+ echo $stanza->to."\n";
+ echo $stanza->to_string()."\n";
+ }
+
+}
Index: externals/JAXL/tests/test_xmpp_stream.php
===================================================================
--- /dev/null
+++ externals/JAXL/tests/test_xmpp_stream.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// TODO: support for php unit and add more tests
+error_reporting(E_ALL);
+require_once "jaxl.php";
+
+/**
+ *
+ * @author abhinavsingh
+ *
+ */
+class XMPPStreamTest extends PHPUnit_Framework_TestCase {
+
+ function test_xmpp_stream() {
+ $xmpp = new XMPPStream("test@localhost", "password");
+ $xmpp->connect();
+
+ $xmpp->start_stream();
+ while($xmpp->sock->fd) {
+ $xmpp->sock->recv();
+ }
+ }
+
+}
Index: externals/JAXL/tests/tests.php
===================================================================
--- /dev/null
+++ externals/JAXL/tests/tests.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+// TODO: support for php unit and add more tests
+error_reporting(E_ALL);
+require_once "jaxl.php";
+
+/**
+ *
+ * @author abhinavsingh
+ *
+ */
+class JAXLTest extends PHPUnit_Framework_TestCase {
+
+}
+
+?>
Index: externals/JAXL/xep/README.md
===================================================================
--- /dev/null
+++ externals/JAXL/xep/README.md
@@ -0,0 +1,14 @@
+Jaxl XMPP XEP's:
+----------------
+Following XMPP Extensions are available:
+
+* 0030 - Service Discovery
+* 0045 - Multi-User Chat
+* 0060 - Publish-Subscribe
+* 0077 - In-Band Registration
+* 0114 - Jabber Component
+* 0115 - Entity Capabilities
+* 0199 - XMPP Ping
+* 0203 - Delayed Delivery
+* 0206 - XMPP Over BOSH
+* 0249 - Direct MUC Invitation
\ No newline at end of file
Index: externals/JAXL/xep/xep_0030.php
===================================================================
--- /dev/null
+++ externals/JAXL/xep/xep_0030.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/xmpp/xmpp_xep.php';
+
+define('NS_DISCO_INFO', 'http://jabber.org/protocol/disco#info');
+define('NS_DISCO_ITEMS', 'http://jabber.org/protocol/disco#items');
+
+class XEP_0030 extends XMPPXep {
+
+ //
+ // abstract method
+ //
+
+ public function init() {
+ return array(
+
+ );
+ }
+
+ //
+ // api methods
+ //
+
+ public function get_info_pkt($entity_jid) {
+ return $this->jaxl->get_iq_pkt(
+ array('type'=>'get', 'from'=>$this->jaxl->full_jid->to_string(), 'to'=>$entity_jid),
+ new JAXLXml('query', NS_DISCO_INFO)
+ );
+ }
+
+ public function get_info($entity_jid, $callback=null) {
+ $pkt = $this->get_info_pkt($entity_jid);
+ if($callback) $this->jaxl->add_cb('on_stanza_id_'.$pkt->id, $callback);
+ $this->jaxl->send($pkt);
+ }
+
+ public function get_items_pkt($entity_jid) {
+ return $this->jaxl->get_iq_pkt(
+ array('type'=>'get', 'from'=>$this->jaxl->full_jid->to_string(), 'to'=>$entity_jid),
+ new JAXLXml('query', NS_DISCO_ITEMS)
+ );
+ }
+
+ public function get_items($entity_jid, $callback=null) {
+ $pkt = $this->get_items_pkt($entity_jid);
+ if($callback) $this->jaxl->add_cb('on_stanza_id_'.$pkt->id, $callback);
+ $this->jaxl->send($pkt);
+ }
+
+ //
+ // event callbacks
+ //
+
+}
+
+?>
Index: externals/JAXL/xep/xep_0045.php
===================================================================
--- /dev/null
+++ externals/JAXL/xep/xep_0045.php
@@ -0,0 +1,114 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/xmpp/xmpp_xep.php';
+
+define('NS_MUC', 'http://jabber.org/protocol/muc');
+
+class XEP_0045 extends XMPPXep {
+
+ //
+ // abstract method
+ //
+
+ public function init() {
+ return array();
+ }
+
+ public function send_groupchat($room_jid, $body, $thread=null, $subject=null) {
+ $msg = new XMPPMsg(
+ array(
+ 'type'=>'groupchat',
+ 'to'=>(($room_jid instanceof XMPPJid) ? $room_jid->to_string() : $room_jid),
+ 'from'=>$this->jaxl->full_jid->to_string()
+ ),
+ $body,
+ $thread,
+ $subject
+ );
+ $this->jaxl->send($msg);
+ }
+
+ //
+ // api methods (occupant use case)
+ //
+
+ // room_full_jid simply means room jid with nick name as resource
+ public function get_join_room_pkt($room_full_jid, $options) {
+ $pkt = $this->jaxl->get_pres_pkt(
+ array(
+ 'from'=>$this->jaxl->full_jid->to_string(),
+ 'to'=>(($room_full_jid instanceof XMPPJid) ? $room_full_jid->to_string() : $room_full_jid)
+ )
+ );
+ $x = $pkt->c('x', NS_MUC);
+ if (isset($options['no_history'])) {
+ $x->c('history')->attrs(array('maxstanzas' => 0, 'seconds' => 0));
+ }
+ return $x;
+ }
+
+ public function join_room($room_full_jid, $options = array()) {
+ $pkt = $this->get_join_room_pkt($room_full_jid, $options);
+ $this->jaxl->send($pkt);
+ }
+
+ public function get_leave_room_pkt($room_full_jid) {
+ return $this->jaxl->get_pres_pkt(
+ array('type'=>'unavailable', 'from'=>$this->jaxl->full_jid->to_string(), 'to'=>(($room_full_jid instanceof XMPPJid) ? $room_full_jid->to_string() : $room_full_jid))
+ );
+ }
+
+ public function leave_room($room_full_jid) {
+ $pkt = $this->get_leave_room_pkt($room_full_jid);
+ $this->jaxl->send($pkt);
+ }
+
+ //
+ // api methods (moderator use case)
+ //
+
+
+
+ //
+ // event callbacks
+ //
+
+}
+
+?>
Index: externals/JAXL/xep/xep_0060.php
===================================================================
--- /dev/null
+++ externals/JAXL/xep/xep_0060.php
@@ -0,0 +1,139 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/xmpp/xmpp_xep.php';
+
+define('NS_PUBSUB', 'http://jabber.org/protocol/pubsub');
+
+class XEP_0060 extends XMPPXep {
+
+ //
+ // abstract method
+ //
+
+ public function init() {
+ return array();
+ }
+
+ //
+ // api methods (entity use case)
+ //
+
+ //
+ // api methods (subscriber use case)
+ //
+
+ public function get_subscribe_pkt($service, $node, $jid=null) {
+ $child = new JAXLXml('pubsub', NS_PUBSUB);
+ $child->c('subscribe', null, array('node'=>$node, 'jid'=>($jid ? $jid : $this->jaxl->full_jid->to_string())));
+ return $this->get_iq_pkt($service, $child);
+ }
+
+ public function subscribe($service, $node, $jid=null) {
+ $this->jaxl->send($this->get_subscribe_pkt($service, $node, $jid));
+ }
+
+ public function unsubscribe() {
+
+ }
+
+ public function get_subscription_options() {
+
+ }
+
+ public function set_subscription_options() {
+
+ }
+
+ public function get_node_items() {
+
+ }
+
+ //
+ // api methods (publisher use case)
+ //
+
+ public function get_publish_item_pkt($service, $node, $item) {
+ $child = new JAXLXml('pubsub', NS_PUBSUB);
+ $child->c('publish', null, array('node'=>$node));
+ $child->cnode($item);
+ return $this->get_iq_pkt($service, $child);
+ }
+
+ public function publish_item($service, $node, $item) {
+ $this->jaxl->send($this->get_publish_item_pkt($service, $node, $item));
+ }
+
+ public function delete_item() {
+
+ }
+
+ //
+ // api methods (owner use case)
+ //
+
+ public function get_create_node_pkt($service, $node) {
+ $child = new JAXLXml('pubsub', NS_PUBSUB);
+ $child->c('create', null, array('node'=>$node));
+ return $this->get_iq_pkt($service, $child);
+ }
+
+ public function create_node($service, $node) {
+ $this->jaxl->send($this->get_create_node_pkt($service, $node));
+ }
+
+ //
+ // event callbacks
+ //
+
+
+ //
+ // local methods
+ //
+
+ // this always add attrs
+ protected function get_iq_pkt($service, $child, $type='set') {
+ return $this->jaxl->get_iq_pkt(
+ array('type'=>$type, 'from'=>$this->jaxl->full_jid->to_string(), 'to'=>$service),
+ $child
+ );
+ }
+
+}
+
+?>
Index: externals/JAXL/xep/xep_0077.php
===================================================================
--- /dev/null
+++ externals/JAXL/xep/xep_0077.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/xmpp/xmpp_xep.php';
+
+define('NS_FEATURE_REGISTER', 'http://jabber.org/features/iq-register');
+define('NS_INBAND_REGISTER', 'jabber:iq:register');
+
+class XEP_0077 extends XMPPXep {
+
+ //
+ // abstract method
+ //
+
+ public function init() {
+ return array(
+
+ );
+ }
+
+ //
+ // api methods
+ //
+
+ public function get_form_pkt($domain) {
+ return $this->jaxl->get_iq_pkt(
+ array('to'=>$domain, 'type'=>'get'),
+ new JAXLXml('query', NS_INBAND_REGISTER)
+ );
+ }
+
+ public function get_form($domain) {
+ $this->jaxl->send($this->get_form_pkt($domain));
+ }
+
+ public function set_form($domain, $form) {
+ $query = new JAXLXml('query', NS_INBAND_REGISTER);
+ foreach($form as $k=>$v) $query->c($k, null, array(), $v)->up();
+ $pkt = $this->jaxl->get_iq_pkt(
+ array('to'=>$domain, 'type'=>'set'),
+ $query
+ );
+ $this->jaxl->send($pkt);
+ }
+
+}
+
+?>
Index: externals/JAXL/xep/xep_0114.php
===================================================================
--- /dev/null
+++ externals/JAXL/xep/xep_0114.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/xmpp/xmpp_xep.php';
+
+define('NS_JABBER_COMPONENT_ACCEPT', 'jabber:component:accept');
+
+class XEP_0114 extends XMPPXep {
+
+ //
+ // abstract method
+ //
+
+ public function init() {
+ return array(
+ 'on_connect' => 'start_stream',
+ 'on_stream_start' => 'start_handshake',
+ 'on_handshake_stanza' => 'logged_in',
+ 'on_error_stanza' => 'logged_out'
+ );
+ }
+
+ //
+ // event callbacks
+ //
+
+ public function start_stream() {
+ $xml = '<stream:stream xmlns:stream="'.NS_XMPP.'" to="'.$this->jaxl->jid->to_string().'" xmlns="'.NS_JABBER_COMPONENT_ACCEPT.'">';
+ $this->jaxl->send_raw($xml);
+ }
+
+ public function start_handshake($stanza) {
+ _debug("starting component handshake");
+ $id = $stanza->id;
+ $hash = strtolower(sha1($id.$this->jaxl->pass));
+ $stanza = new JAXLXml('handshake', null, $hash);
+ $this->jaxl->send($stanza);
+ }
+
+ public function logged_in($stanza) {
+ _debug("component handshake complete");
+ $this->jaxl->handle_auth_success();
+ return array("logged_in", 1);
+ }
+
+ public function logged_out($stanza) {
+ if($stanza->name == "error" && $stanza->ns == NS_XMPP) {
+ $reason = $stanza->childrens[0]->name;
+ $this->jaxl->handle_auth_failure($reason);
+ $this->jaxl->send_end_stream();
+ return array("logged_out", 0);
+ }
+ else {
+ _debug("uncatched stanza received in logged_out");
+ }
+ }
+
+}
+
+?>
Index: externals/JAXL/xep/xep_0115.php
===================================================================
--- /dev/null
+++ externals/JAXL/xep/xep_0115.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/xmpp/xmpp_xep.php';
+
+define('NS_CAPS', 'http://jabber.org/protocol/caps');
+
+class XEP_0115 extends XMPPXep {
+
+ //
+ // abstract method
+ //
+
+ public function init() {
+ return array();
+ }
+
+ //
+ // api methods
+ //
+
+ public function get_caps_pkt($cat, $type, $lang, $name, $node, $features) {
+ asort($features);
+ $S = $cat.'/'.$type.'/'.$lang.'/'.$name.'<';
+ foreach($features as $feature) $S .= $feature.'<';
+ $ver = base64_encode(sha1($S, true));
+
+ $stanza = new JAXLXml('c', NS_CAPS, array('hash'=>'sha1', 'node'=>$node, 'ver'=>$ver));
+ return $stanza;
+ }
+
+ //
+ // event callbacks
+ //
+
+}
+
+?>
Index: externals/JAXL/xep/xep_0199.php
===================================================================
--- /dev/null
+++ externals/JAXL/xep/xep_0199.php
@@ -0,0 +1,60 @@
+<?php
+
+require_once JAXL_CWD.'/xmpp/xmpp_xep.php';
+
+define('NS_XMPP_PING', 'urn:xmpp:ping');
+
+class XEP_0199 extends XMPPXep {
+
+ //
+ // abstract method
+ //
+
+ public function init() {
+ return array(
+ 'on_auth_success' => 'on_auth_success',
+ 'on_get_iq' => 'on_xmpp_ping'
+ );
+ }
+
+ //
+ // api methods
+ //
+
+ public function get_ping_pkt() {
+ $attrs = array(
+ 'type'=>'get',
+ 'from'=>$this->jaxl->full_jid->to_string(),
+ 'to'=>$this->jaxl->full_jid->domain
+ );
+
+ return $this->jaxl->get_iq_pkt(
+ $attrs,
+ new JAXLXml('ping', NS_XMPP_PING)
+ );
+ }
+
+ public function ping() {
+ $this->jaxl->send($this->get_ping_pkt());
+ }
+
+ //
+ // event callbacks
+ //
+
+ public function on_auth_success() {
+ JAXLLoop::$clock->call_fun_periodic(30 * pow(10,6), array(&$this, 'ping'));
+ }
+
+ public function on_xmpp_ping($stanza) {
+ if($stanza->exists('ping', NS_XMPP_PING)) {
+ $stanza->type = "result";
+ $stanza->to = $stanza->from;
+ $stanza->from = $this->jaxl->full_jid->to_string();
+ $this->jaxl->send($stanza);
+ }
+ }
+
+}
+
+?>
Index: externals/JAXL/xep/xep_0203.php
===================================================================
--- /dev/null
+++ externals/JAXL/xep/xep_0203.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/xmpp/xmpp_xep.php';
+
+define('NS_DELAYED_DELIVERY', 'urn:xmpp:delay');
+
+class XEP_0203 extends XMPPXep {
+
+ //
+ // abstract method
+ //
+
+ public function init() {
+ return array();
+ }
+
+ //
+ // api methods
+ //
+
+ //
+ // event callbacks
+ //
+
+}
+
+?>
Index: externals/JAXL/xep/xep_0206.php
===================================================================
--- /dev/null
+++ externals/JAXL/xep/xep_0206.php
@@ -0,0 +1,236 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/xmpp/xmpp_xep.php';
+
+define('NS_HTTP_BIND', 'http://jabber.org/protocol/httpbind');
+define('NS_BOSH', 'urn:xmpp:xbosh');
+
+class XEP_0206 extends XMPPXep {
+
+ private $mch = null;
+ public $chs = array();
+ private $recv_cb = null;
+
+ public $rid = null;
+ public $sid = null;
+ private $hold = 1;
+ private $wait = 30;
+
+ private $restarted = false;
+
+ public $headers = array(
+ 'Accept-Encoding: gzip, deflate',
+ 'Content-Type: text/xml; charset=utf-8'
+ );
+
+ //
+ // abstract method
+ //
+
+ public function init() {
+ $this->mch = curl_multi_init();
+
+ return array(
+
+ );
+ }
+
+ //
+ // event callbacks
+ //
+
+ public function send($body) {
+ if(is_object($body)) {
+ $body = $body->to_string();
+ }
+ else {
+ if(substr($body, 0, 15) == '<stream:stream ') {
+ $this->restarted = true;
+
+ $body = new JAXLXml('body', NS_HTTP_BIND, array(
+ 'sid' => $this->sid,
+ 'rid' => ++$this->rid,
+ 'to' => @$this->jaxl->jid ? $this->jaxl->jid->domain : $this->jaxl->cfg['domain'],
+ 'xmpp:restart' => 'true',
+ 'xmlns:xmpp' => NS_BOSH
+ ));
+
+ $body = $body->to_string();
+ }
+ else if(substr($body, 0, 16) == '</stream:stream>') {
+ $body = new JAXLXml('body', NS_HTTP_BIND, array(
+ 'sid' => $this->sid,
+ 'rid' => ++$this->rid,
+ 'type' => 'terminate'
+ ));
+
+ $body = $body->to_string();
+ }
+ else {
+ $body = $this->wrap($body);
+ }
+ }
+ _debug("posting to ".$this->jaxl->cfg['bosh_url']." body ".$body);
+
+ $this->chs[$this->rid] = curl_init($this->jaxl->cfg['bosh_url']);
+ curl_setopt($this->chs[$this->rid], CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($this->chs[$this->rid], CURLOPT_ENCODING, 'gzip,deflate');
+ curl_setopt($this->chs[$this->rid], CURLOPT_HTTPHEADER, $this->headers);
+ curl_setopt($this->chs[$this->rid], CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($this->chs[$this->rid], CURLOPT_VERBOSE, false);
+ curl_setopt($this->chs[$this->rid], CURLOPT_POST, 1);
+ curl_setopt($this->chs[$this->rid], CURLOPT_POSTFIELDS, $body);
+
+ curl_multi_add_handle($this->mch, $this->chs[$this->rid]);
+ }
+
+ public function recv() {
+ if($this->restarted) {
+ $this->restarted = false;
+
+ // fool xmpp_stream state machine with stream start packet
+ // and make transition to wait_for_stream_features state
+ if($this->recv_cb) call_user_func($this->recv_cb, $this->jaxl->get_start_stream(new XMPPJid("bosh.jaxl")));
+ }
+
+ _debug("recving for $this->rid");
+ do {
+ $ret = curl_multi_exec($this->mch, $running);
+ $changed = curl_multi_select($this->mch, 0.1);
+
+ if($changed == 0 && $running == 0) {
+ $ch = @$this->chs[$this->rid];
+ if($ch) {
+ $data = curl_multi_getcontent($ch);
+
+ curl_multi_remove_handle($this->mch, $ch);
+ unset($this->chs[$this->rid]);
+ _debug("recvd for $this->rid ".$data);
+
+ list($body, $stanza) = $this->unwrap($data);
+ $body = new SimpleXMLElement($body);
+ $attrs = $body->attributes();
+
+ if(@$attrs['type'] == 'terminate') {
+ // fool me again
+ if($this->recv_cb) call_user_func($this->recv_cb, $this->jaxl->get_end_stream());
+ }
+ else {
+ if(!$this->sid) {
+ $this->sid = $attrs['sid'];
+ }
+
+ if($this->recv_cb) call_user_func($this->recv_cb, $stanza);
+ }
+ }
+ else {
+ _error("no ch found");
+ exit;
+ }
+ }
+ } while($running);
+ }
+
+ public function set_callback($recv_cb) {
+ $this->recv_cb = $recv_cb;
+ }
+
+ public function wrap($stanza) {
+ return '<body sid="'.$this->sid.'" rid="'.++$this->rid.'" xmlns="'.NS_HTTP_BIND.'">'.$stanza.'</body>';
+ }
+
+ public function unwrap($body) {
+ // a dirty way but it works efficiently
+ if(substr($body, -2, 2) == "/>") preg_match_all('/<body (.*?)\/>/smi', $body, $m);
+ else preg_match_all('/<body (.*?)>(.*)<\/body>/smi', $body, $m);
+
+ if(isset($m[1][0])) $envelop = "<body ".$m[1][0]."/>";
+ else $envelop = "<body/>";
+
+ if(isset($m[2][0])) $payload = $m[2][0];
+ else $payload = '';
+
+ return array($envelop, $payload);
+ }
+
+ public function session_start() {
+ $this->rid = @$this->jaxl->cfg['bosh_rid'] ? $this->jaxl->cfg['bosh_rid'] : rand(1000, 10000);
+ $this->hold = @$this->jaxl->cfg['bosh_hold'] ? $this->jaxl->cfg['bosh_hold'] : $this->hold;
+ $this->wait = @$this->jaxl->cfg['bosh_wait'] ? $this->jaxl->cfg['bosh_wait'] : $this->wait;
+
+ // fool xmpp_stream state machine with stream start packet
+ // and make transition to wait_for_stream_features state
+ if($this->recv_cb)
+ call_user_func($this->recv_cb, $this->jaxl->get_start_stream(new XMPPJid("bosh.jaxl")));
+
+ $attrs = array(
+ 'content' => 'text/xml; charset=utf-8',
+ 'to' => @$this->jaxl->jid ? $this->jaxl->jid->domain : $this->jaxl->cfg['domain'],
+ 'route' => 'xmpp:'.$this->jaxl->cfg['host'].':'.$this->jaxl->cfg['port'],
+ 'secure' => 'true',
+ 'xml:lang' => 'en',
+ 'xmpp:version' => '1.0',
+ 'xmlns:xmpp' => NS_BOSH,
+ 'hold' => $this->hold,
+ 'wait' => $this->wait,
+ 'rid' => $this->rid,
+ 'ver' => '1.10'
+ );
+
+ if(@$this->jaxl->cfg['jid']) $attrs['from'] = @$this->jaxl->cfg['jid'];
+ $body = new JAXLXml('body', NS_HTTP_BIND, $attrs);
+ $this->send($body);
+ }
+
+ public function ping() {
+ $body = new JAXLXml('body', NS_HTTP_BIND, array('sid' => $this->sid, 'rid' => ++$this->rid));
+ $this->send($body);
+ }
+
+ public function session_end() {
+ $this->disconnect();
+ }
+
+ public function disconnect() {
+ _debug("disconnecting");
+ }
+
+}
+
+?>
Index: externals/JAXL/xep/xep_0249.php
===================================================================
--- /dev/null
+++ externals/JAXL/xep/xep_0249.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/xmpp/xmpp_xep.php';
+
+define('NS_DIRECT_MUC_INVITATION', 'jabber:x:conference');
+
+class XEP_0249 extends XMPPXep {
+
+ //
+ // abstract method
+ //
+
+ public function init() {
+ return array();
+ }
+
+ //
+ // api methods
+ //
+
+ public function get_invite_pkt($to_bare_jid, $room_jid, $password=null, $reason=null, $thread=null, $continue=null) {
+ $xattrs = array('jid'=>$room_jid);
+ if($password) $xattrs['password'] = $password;
+ if($reason) $xattrs['reason'] = $reason;
+ if($thread) $xattrs['thread'] = $thread;
+ if($continue) $xattrs['continue'] = $continue;
+
+ return $this->jaxl->get_msg_pkt(
+ array('from'=>$this->jaxl->full_jid->to_string(), 'to'=>$to_bare_jid),
+ null, null, null,
+ new JAXLXml('x', NS_DIRECT_MUC_INVITATION, $xattrs)
+ );
+ }
+
+ public function invite($to_bare_jid, $room_jid, $password=null, $reason=null, $thread=null, $continue=null) {
+ $this->jaxl->send($this->get_invite_pkt($to_bare_jid, $room_jid, $password, $reason, $thread, $continue));
+ }
+
+ //
+ // event callbacks
+ //
+
+}
+
+?>
Index: externals/JAXL/xmpp/README.md
===================================================================
--- /dev/null
+++ externals/JAXL/xmpp/README.md
@@ -0,0 +1,12 @@
+Jaxl XMPP Stack:
+----------------
+XMPP Stack implementation includes:
+
+* XMPPStream - RFC 6120 and RFC 6121
+* XMPPXep - Abstract XMPP Extension class
+* XMPPStanza - Generic Stanza object
+* XMPPPres - Generic Presence object
+* XMPPMsg - Generic Message object
+* XMPPIq - Generic IQ object
+* XMPPJid - JabberId object
+* XMPPRosterItem - A XMPP Roster Item representation
\ No newline at end of file
Index: externals/JAXL/xmpp/xmpp_iq.php
===================================================================
--- /dev/null
+++ externals/JAXL/xmpp/xmpp_iq.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/xmpp/xmpp_stanza.php';
+
+class XMPPIq extends XMPPStanza {
+
+ public function __construct($attrs) {
+ parent::__construct('iq', $attrs);
+ }
+
+}
+
+?>
Index: externals/JAXL/xmpp/xmpp_jid.php
===================================================================
--- /dev/null
+++ externals/JAXL/xmpp/xmpp_jid.php
@@ -0,0 +1,83 @@
+<?php
+/**
+* Jaxl (Jabber XMPP Library)
+*
+* Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+*
+*/
+
+/**
+ *
+ * Xmpp Jid
+ *
+ * @author abhinavsingh
+ *
+ */
+class XMPPJid {
+
+ public $node = null;
+ public $domain = null;
+ public $resource = null;
+ public $bare = null;
+
+ public function __construct($str) {
+ $tmp = explode("@", $str);
+ if(sizeof($tmp) == 2) {
+ $this->node = $tmp[0];
+ $tmp = explode("/", $tmp[1]);
+ if(sizeof($tmp) == 2) {
+ $this->domain = $tmp[0];
+ $this->resource = $tmp[1];
+ }
+ else {
+ $this->domain = $tmp[0];
+ }
+ }
+ else if(sizeof($tmp) == 1) {
+ $this->domain = $tmp[0];
+ }
+
+ $this->bare = $this->node ? $this->node."@".$this->domain : $this->domain;
+ }
+
+ public function to_string() {
+ $str = "";
+ if($this->node) $str .= $this->node.'@'.$this->domain;
+ else if($this->domain) $str .= $this->domain;
+ if($this->resource) $str .= '/'.$this->resource;
+ return $str;
+ }
+
+}
+
+?>
Index: externals/JAXL/xmpp/xmpp_msg.php
===================================================================
--- /dev/null
+++ externals/JAXL/xmpp/xmpp_msg.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/xmpp/xmpp_stanza.php';
+
+class XMPPMsg extends XMPPStanza {
+
+ public function __construct($attrs, $body=null, $thread=null, $subject=null) {
+ parent::__construct('message', $attrs);
+
+ if($body) $this->c('body')->t($body)->up();
+ if($thread) $this->c('thread')->t($thread)->up();
+ if($subject) $this->c('subject')->t($subject)->up();
+ }
+
+}
+
+?>
Index: externals/JAXL/xmpp/xmpp_nss.php
===================================================================
--- /dev/null
+++ externals/JAXL/xmpp/xmpp_nss.php
@@ -0,0 +1,62 @@
+<?php
+/**
+* Jaxl (Jabber XMPP Library)
+*
+* Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+*
+*/
+
+// XML
+define('NS_XML_pfx', "xml");
+define('NS_XML', 'http://www.w3.org/XML/1998/namespace');
+
+// XMPP Core (RFC 3920)
+define('NS_XMPP_pfx', "stream");
+define('NS_XMPP', 'http://etherx.jabber.org/streams');
+define('NS_STREAM_ERRORS', 'urn:ietf:params:xml:ns:xmpp-streams');
+define('NS_TLS', 'urn:ietf:params:xml:ns:xmpp-tls');
+define('NS_SASL', 'urn:ietf:params:xml:ns:xmpp-sasl');
+define('NS_BIND', 'urn:ietf:params:xml:ns:xmpp-bind');
+define('NS_STANZA_ERRORS', 'urn:ietf:params:xml:ns:xmpp-stanzas');
+
+// XMPP-IM (RFC 3921)
+define('NS_JABBER_CLIENT', 'jabber:client');
+define('NS_JABBER_SERVER', 'jabber:server');
+define('NS_SESSION', 'urn:ietf:params:xml:ns:xmpp-session');
+define('NS_ROSTER', 'jabber:iq:roster');
+
+// Stream Compression (XEP-0138)
+define('NS_COMPRESSION_FEATURE', 'http://jabber.org/features/compress');
+define('NS_COMPRESSION_PROTOCOL', 'http://jabber.org/protocol/compress');
+
+?>
Index: externals/JAXL/xmpp/xmpp_pres.php
===================================================================
--- /dev/null
+++ externals/JAXL/xmpp/xmpp_pres.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/xmpp/xmpp_stanza.php';
+
+class XMPPPres extends XMPPStanza {
+
+ public function __construct($attrs, $status=null, $show=null, $priority=null) {
+ parent::__construct('presence', $attrs);
+
+ if($status) $this->c('status')->t($status)->up();
+ if($show) $this->c('show')->t($show)->up();
+ if($priority) $this->c('priority')->t($priority)->up();
+ }
+
+}
+
+?>
Index: externals/JAXL/xmpp/xmpp_roster_item.php
===================================================================
--- /dev/null
+++ externals/JAXL/xmpp/xmpp_roster_item.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+/**
+ *
+ * @author abhinavsingh
+ */
+class XMPPRosterItem {
+
+ public $jid = null;
+ public $subscription = null;
+ public $groups = array();
+ public $resources = array();
+ public $vcard = null;
+
+ public function __construct($jid, $subscription, $groups) {
+ $this->jid = $jid;
+ $this->subscription = $subscription;
+ $this->groups = $groups;
+ }
+
+}
+
+?>
Index: externals/JAXL/xmpp/xmpp_stanza.php
===================================================================
--- /dev/null
+++ externals/JAXL/xmpp/xmpp_stanza.php
@@ -0,0 +1,176 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+require_once JAXL_CWD.'/xmpp/xmpp_nss.php';
+require_once JAXL_CWD.'/xmpp/xmpp_jid.php';
+require_once JAXL_CWD.'/core/jaxl_xml.php';
+
+/**
+ * Generic xmpp stanza object which provide convinient access pattern over xml objects
+ * Also to be able to convert an existing xml object into stanza object (to get access patterns going)
+ * this class doesn't extend xml, but infact works on a reference of xml object
+ * If not provided during constructor, new xml object is created and saved as reference
+ *
+ * @author abhinavsingh
+ *
+ */
+class XMPPStanza {
+
+ private $xml;
+
+ public function __construct($name, $attrs=array(), $ns=NS_JABBER_CLIENT) {
+ if($name instanceof JAXLXml) $this->xml = $name;
+ else $this->xml = new JAXLXml($name, $ns, $attrs);
+ }
+
+ public function __call($method, $args) {
+ return call_user_func_array(array($this->xml, $method), $args);
+ }
+
+ public function __get($prop) {
+ switch($prop) {
+ // access to jaxl xml properties
+ case 'name':
+ case 'ns':
+ case 'text':
+ case 'attrs':
+ case 'childrens':
+ return $this->xml->$prop;
+ break;
+
+ // access to common xml attributes
+ case 'to':
+ case 'from':
+ case 'id':
+ case 'type':
+ return @$this->xml->attrs[$prop] ? $this->xml->attrs[$prop] : null;
+ break;
+
+ // access to parts of common xml attributes
+ case 'to_node':
+ case 'to_domain':
+ case 'to_resource':
+ case 'from_node':
+ case 'from_domain':
+ case 'from_resource':
+ list($attr, $key) = explode('_', $prop);
+ $val = @$this->xml->attrs[$attr] ? $this->xml->attrs[$attr] : null;
+ if(!$val) return null;
+
+ $val = new XMPPJid($val);
+ return $val->$key;
+ break;
+
+ // access to first child element text
+ case 'status':
+ case 'show':
+ case 'priority':
+ case 'body':
+ case 'thread':
+ case 'subject':
+ $val = $this->xml->exists($prop);
+ if(!$val) return null;
+ return $val->text;
+ break;
+
+ default:
+ return null;
+ break;
+ }
+ }
+
+ public function __set($prop, $val) {
+ switch($prop) {
+ // access to jaxl xml properties
+ case 'name':
+ case 'ns':
+ case 'text':
+ case 'attrs':
+ case 'childrens':
+ return $this->xml->$prop = $val;
+ break;
+
+ // access to common xml attributes
+ case 'to':
+ case 'from':
+ case 'id':
+ case 'type':
+ $this->xml->attrs[$prop] = $val;
+ return true;
+ break;
+
+ // access to parts of common xml attributes
+ case 'to_node':
+ case 'to_domain':
+ case 'to_resource':
+ case 'from_node':
+ case 'from_domain':
+ case 'from_resource':
+ list($attr, $key) = explode('_', $prop);
+ $val1 = @$this->xml->attrs[$attr];
+ if(!$val1) $val1 = '';
+
+ $val1 = new XMPPJid($val1);
+ $val1->$key = $val;
+
+ $this->xml->attrs[$attr] = $val1->to_string();
+ return true;
+ break;
+
+ // access to first child element text
+ case 'status':
+ case 'show':
+ case 'priority':
+ case 'body':
+ case 'thread':
+ case 'subject':
+ $val1 = $this->xml->exists($prop);
+ if(!$val1) $this->xml->c($prop)->t($val)->up();
+ else $this->xml->update($prop, $val1->ns, $val1->attrs, $val);
+ return true;
+ break;
+
+ default:
+ return null;
+ break;
+ }
+ }
+
+}
+
+?>
Index: externals/JAXL/xmpp/xmpp_stream.php
===================================================================
--- /dev/null
+++ externals/JAXL/xmpp/xmpp_stream.php
@@ -0,0 +1,671 @@
+<?php
+/**
+* Jaxl (Jabber XMPP Library)
+*
+* Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+*
+*/
+
+require_once JAXL_CWD.'/core/jaxl_fsm.php';
+require_once JAXL_CWD.'/core/jaxl_xml.php';
+require_once JAXL_CWD.'/core/jaxl_xml_stream.php';
+require_once JAXL_CWD.'/core/jaxl_util.php';
+require_once JAXL_CWD.'/core/jaxl_socket_client.php';
+
+require_once JAXL_CWD.'/xmpp/xmpp_nss.php';
+require_once JAXL_CWD.'/xmpp/xmpp_jid.php';
+require_once JAXL_CWD.'/xmpp/xmpp_msg.php';
+require_once JAXL_CWD.'/xmpp/xmpp_pres.php';
+require_once JAXL_CWD.'/xmpp/xmpp_iq.php';
+
+/**
+ *
+ * Enter description here ...
+ * @author abhinavsingh
+ *
+ */
+abstract class XMPPStream extends JAXLFsm {
+
+ // jid with binding resource value
+ public $full_jid = null;
+
+ // input parameters
+ public $jid = null;
+ public $pass = null;
+ public $resource = null;
+ public $force_tls = false;
+
+ // underlying socket/bosh and xml stream ref
+ protected $trans = null;
+ protected $xml = null;
+
+ // stanza id
+ protected $last_id = 0;
+
+ //
+ // abstract methods
+ //
+
+ abstract public function handle_stream_start($stanza);
+ abstract public function handle_auth_mechs($stanza, $mechs);
+ abstract public function handle_auth_success();
+ abstract public function handle_auth_failure($reason);
+ abstract public function handle_iq($stanza);
+ abstract public function handle_presence($stanza);
+ abstract public function handle_message($stanza);
+ abstract public function handle_other($event, $args);
+
+ //
+ // public api
+ //
+
+ public function __construct($transport, $jid, $pass=null, $resource=null, $force_tls=false) {
+ $this->jid = $jid;
+ $this->pass = $pass;
+ $this->resource = $resource ? $resource : md5(time());
+ $this->force_tls = $force_tls;
+
+ $this->trans = $transport;
+ $this->xml = new JAXLXmlStream();
+
+ $this->trans->set_callback(array(&$this->xml, "parse"));
+ $this->xml->set_callback(array(&$this, "start_cb"), array(&$this, "end_cb"), array(&$this, "stanza_cb"));
+
+ parent::__construct("setup");
+ }
+
+ public function __destruct() {
+ //_debug("cleaning up xmpp stream...");
+ }
+
+ public function handle_invalid_state($r) {
+ _error("got invalid return value from state handler '".$this->state."', sending end stream...");
+ $this->send_end_stream();
+ $this->state = "logged_out";
+ _notice("state handler '".$this->state."' returned ".serialize($r).", kindly report this to developers");
+ }
+
+ public function send($stanza) {
+ $this->trans->send($stanza->to_string());
+ }
+
+ public function send_raw($data) {
+ $this->trans->send($data);
+ }
+
+ //
+ // pkt creation utilities
+ //
+
+ public function get_start_stream($jid) {
+ $xml = '<stream:stream xmlns:stream="'.NS_XMPP.'" version="1.0" ';
+ //if(isset($jid->bare)) $xml .= 'from="'.$jid->bare.'" ';
+ if(isset($jid->domain)) $xml .= 'to="'.$jid->domain.'" ';
+ $xml .= 'xmlns="'.NS_JABBER_CLIENT.'" xml:lang="en" xmlns:xml="'.NS_XML.'">';
+ return $xml;
+ }
+
+ public function get_end_stream() {
+ return '</stream:stream>';
+ }
+
+ public function get_starttls_pkt() {
+ $stanza = new JAXLXml('starttls', NS_TLS);
+ return $stanza;
+ }
+
+ public function get_compress_pkt($method) {
+ $stanza = new JAXLXml('compress', NS_COMPRESSION_PROTOCOL);
+ $stanza->c('method')->t($method);
+ return $stanza;
+ }
+
+ // someday this all needs to go inside jaxl_sasl_auth
+ public function get_auth_pkt($mechanism, $user, $pass) {
+ $stanza = new JAXLXml('auth', NS_SASL, array('mechanism'=>$mechanism));
+
+ switch($mechanism) {
+ case 'PLAIN':
+ case 'X-OAUTH2':
+ $stanza->t(base64_encode("\x00".$user."\x00".$pass));
+ break;
+ case 'DIGEST-MD5':
+ break;
+ case 'CRAM-MD5':
+ break;
+ case 'SCRAM-SHA-1':
+ // client first message always starts with n, y or p for GS2 extensibility
+ $stanza->t(base64_encode("n,,n=".$user.",r=".JAXLUtil::get_nonce(false)));
+ break;
+ case 'ANONYMOUS':
+ break;
+ case 'EXTERNAL':
+ // If no password, then we are probably doing certificate auth, so follow RFC 6120 form and pass '='.
+ if(strlen($pass) == 0)
+ $stanza->t('=');
+ break;
+ default:
+ break;
+ }
+
+ return $stanza;
+ }
+
+ public function get_challenge_response_pkt($challenge) {
+ $stanza = new JAXLXml('response', NS_SASL);
+ $decoded = $this->explode_data(base64_decode($challenge));
+
+ if(!isset($decoded['rspauth'])) {
+ _debug("calculating response to challenge");
+ $stanza->t($this->get_challenge_response($decoded));
+ }
+
+ return $stanza;
+ }
+
+ public function get_challenge_response($decoded) {
+ $response = array();
+ $nc = '00000001';
+
+ if(!isset($decoded['digest-uri']))
+ $decoded['digest-uri'] = 'xmpp/'.$this->jid->domain;
+
+ $decoded['cnonce'] = base64_encode(JAXLUtil::get_nonce());
+
+ if(isset($decoded['qop']) && $decoded['qop'] != 'auth' && strpos($decoded['qop'], 'auth') !== false)
+ $decoded['qop'] = 'auth';
+
+ $data = array_merge($decoded, array('nc'=>$nc));
+
+ $response = array(
+ 'username'=> $this->jid->node,
+ 'response' => $this->encrypt_password($data, $this->jid->node, $this->pass),
+ 'charset' => 'utf-8',
+ 'nc' => $nc,
+ 'qop' => 'auth'
+ );
+
+ foreach(array('nonce', 'digest-uri', 'realm', 'cnonce') as $key)
+ if(isset($decoded[$key]))
+ $response[$key] = $decoded[$key];
+
+ return base64_encode($this->implode_data($response));
+ }
+
+ public function get_bind_pkt($resource) {
+ $stanza = new JAXLXml('bind', NS_BIND);
+ $stanza->c('resource')->t($resource);
+ return $this->get_iq_pkt(array(
+ 'type' => 'set'
+ ), $stanza);
+ }
+
+ public function get_session_pkt() {
+ $stanza = new JAXLXml('session', NS_SESSION);
+ return $this->get_iq_pkt(array(
+ 'type' => 'set'
+ ), $stanza);
+ }
+
+ public function get_msg_pkt($attrs, $body=null, $thread=null, $subject=null, $payload=null) {
+ $msg = new XMPPMsg($attrs, $body, $thread, $subject);
+ if(!$msg->id) $msg->id = $this->get_id();
+ if($payload) $msg->cnode($payload);
+ return $msg;
+ }
+
+ public function get_pres_pkt($attrs, $status=null, $show=null, $priority=null, $payload=null) {
+ $pres = new XMPPPres($attrs, $status, $show, $priority);
+ if(!$pres->id) $pres->id = $this->get_id();
+ if($payload) $pres->cnode($payload);
+ return $pres;
+ }
+
+ public function get_iq_pkt($attrs, $payload) {
+ $iq = new XMPPIq($attrs);
+ if(!$iq->id) $iq->id = $this->get_id();
+ if($payload) $iq->cnode($payload);
+ return $iq;
+ }
+
+ public function get_id() {
+ ++$this->last_id;
+ return dechex($this->last_id);
+ }
+
+ public function explode_data($data) {
+ $data = explode(',', $data);
+ $pairs = array();
+ $key = false;
+
+ foreach($data as $pair) {
+ $dd = strpos($pair, '=');
+ if($dd) {
+ $key = trim(substr($pair, 0, $dd));
+ $pairs[$key] = trim(trim(substr($pair, $dd + 1)), '"');
+ }
+ else if(strpos(strrev(trim($pair)), '"') === 0 && $key) {
+ $pairs[$key] .= ',' . trim(trim($pair), '"');
+ continue;
+ }
+ }
+
+ return $pairs;
+ }
+
+ public function implode_data($data) {
+ $return = array();
+ foreach($data as $key => $value) $return[] = $key . '="' . $value . '"';
+ return implode(',', $return);
+ }
+
+ public function encrypt_password($data, $user, $pass) {
+ foreach(array('realm', 'cnonce', 'digest-uri') as $key)
+ if(!isset($data[$key]))
+ $data[$key] = '';
+
+ $pack = md5($user.':'.$data['realm'].':'.$pass);
+
+ if(isset($data['authzid']))
+ $a1 = pack('H32',$pack).sprintf(':%s:%s:%s',$data['nonce'],$data['cnonce'],$data['authzid']);
+ else
+ $a1 = pack('H32',$pack).sprintf(':%s:%s',$data['nonce'],$data['cnonce']);
+
+ $a2 = 'AUTHENTICATE:'.$data['digest-uri'];
+ return md5(sprintf('%s:%s:%s:%s:%s:%s', md5($a1), $data['nonce'], $data['nc'], $data['cnonce'], $data['qop'], md5($a2)));
+ }
+
+ //
+ // socket senders
+ //
+
+ protected function send_start_stream($jid) {
+ $this->send_raw($this->get_start_stream($jid));
+ }
+
+ public function send_end_stream() {
+ $this->send_raw($this->get_end_stream());
+ }
+
+ protected function send_auth_pkt($type, $user, $pass) {
+ $this->send($this->get_auth_pkt($type, $user, $pass));
+ }
+
+ protected function send_starttls_pkt() {
+ $this->send($this->get_starttls_pkt());
+ }
+
+ protected function send_compress_pkt($method) {
+ $this->send($this->get_compress_pkt($method));
+ }
+
+ protected function send_challenge_response($challenge) {
+ $this->send($this->get_challenge_response_pkt($challenge));
+ }
+
+ protected function send_bind_pkt($resource) {
+ $this->send($this->get_bind_pkt($resource));
+ }
+
+ protected function send_session_pkt() {
+ $this->send($this->get_session_pkt());
+ }
+
+ private function do_connect($args) {
+ $socket_path = @$args[0];
+ if($this->trans->connect($socket_path)) {
+ return array("connected", 1);
+ }
+ else {
+ return array("disconnected", 0);
+ }
+ }
+
+ //
+ // fsm States
+ //
+
+ public function setup($event, $args) {
+ switch($event) {
+ case "connect":
+ return $this->do_connect($args);
+ break;
+ // someone else already started the stream
+ // even before "connect" was called must be bosh
+ case "start_cb":
+ $stanza = $args[0];
+ return $this->handle_stream_start($stanza);
+ break;
+ default:
+ _debug("uncatched $event");
+ //print_r($args);
+ return $this->handle_other($event, $args);
+ //return array("setup", 0);
+ break;
+ }
+ }
+
+ public function connected($event, $args) {
+ switch($event) {
+ case "start_stream":
+ $this->send_start_stream($this->jid);
+ return array("wait_for_stream_start", 1);
+ break;
+ // someone else already started the stream before us
+ // even before "start_stream" was called
+ // must be component
+ case "start_cb":
+ $stanza = $args[0];
+ return $this->handle_stream_start($stanza);
+ break;
+ default:
+ _debug("uncatched $event");
+ return $this->handle_other($event, $args);
+ //return array("connected", 0);
+ break;
+ }
+ }
+
+ public function disconnected($event, $args) {
+ switch($event) {
+ case "connect":
+ return $this->do_connect($args);
+ break;
+ case "end_stream":
+ $this->send_end_stream();
+ return "logged_out";
+ break;
+ default:
+ _debug("uncatched $event");
+ return $this->handle_other($event, $args);
+ //return array("disconnected", 0);
+ break;
+ }
+ }
+
+ public function wait_for_stream_start($event, $args) {
+ switch($event) {
+ case "start_cb":
+ // TODO: save stream id and other meta info
+ //_debug("stream started");
+ return "wait_for_stream_features";
+ break;
+ default:
+ _debug("uncatched $event");
+ return $this->handle_other($event, $args);
+ //return array("wait_for_stream_start", 0);
+ break;
+ }
+ }
+
+ // XEP-0170: Recommended Order of Stream Feature Negotiation
+ public function wait_for_stream_features($event, $args) {
+ switch($event) {
+ case "stanza_cb":
+ $stanza = $args[0];
+
+ // get starttls requirements
+ $starttls = $stanza->exists('starttls', NS_TLS);
+ $required = $starttls ? ($this->force_tls ? true : ($starttls->exists('required') ? true : false)) : false;
+
+ if($starttls && $required) {
+ $this->send_starttls_pkt();
+ return "wait_for_tls_result";
+ }
+
+ // handle auth mech
+ $mechs = $stanza->exists('mechanisms', NS_SASL);
+ if($mechs) {
+ $new_state = $this->handle_auth_mechs($stanza, $mechs);
+ return $new_state ? $new_state : "wait_for_sasl_response";
+ }
+
+ // post auth
+ $bind = $stanza->exists('bind', NS_BIND) ? true : false;
+ $sess = $stanza->exists('session', NS_SESSION) ? true : false;
+ $comp = $stanza->exists('compression', NS_COMPRESSION_FEATURE) ? true : false;
+
+ if($bind) {
+ $this->send_bind_pkt($this->resource);
+ return "wait_for_bind_response";
+ }
+ /*// compression not supported due to bug in php stream filters
+ else if($comp) {
+ $this->send_compress_pkt("zlib");
+ return "wait_for_compression_result";
+ }*/
+ else {
+ _debug("no catch");
+ }
+
+ break;
+ default:
+ _debug("uncatched $event");
+ return $this->handle_other($event, $args);
+ //return array("wait_for_stream_features", 0);
+ break;
+ }
+ }
+
+ public function wait_for_tls_result($event, $args) {
+ switch($event) {
+ case "stanza_cb":
+ $stanza = $args[0];
+
+ if($stanza->name == 'proceed' && $stanza->ns == NS_TLS) {
+ if($this->trans->crypt()) {
+ $this->xml->reset_parser();
+ $this->send_start_stream($this->jid);
+ return "wait_for_stream_start";
+ }
+ else {
+ $this->handle_auth_failure("tls-negotiation-failed");
+ return "logged_out";
+ }
+ }
+ else {
+ // FIXME: here
+ }
+
+ break;
+ default:
+ _debug("uncatched $event");
+ return $this->handle_other($event, $args);
+ //return array("wait_for_tls_result", 0);
+ break;
+ }
+ }
+
+ public function wait_for_compression_result($event, $args) {
+ switch($event) {
+ case "stanza_cb":
+ $stanza = $args[0];
+
+ if($stanza->name == 'compressed' && $stanza->ns == NS_COMPRESSION_PROTOCOL) {
+ $this->xml->reset_parser();
+ $this->trans->compress();
+ $this->send_start_stream($this->jid);
+ return "wait_for_stream_start";
+ }
+
+ break;
+ default:
+ _debug("uncatched $event");
+ return $this->handle_other($event, $args);
+ //return array("wait_for_compression_result", 0);
+ break;
+ }
+ }
+
+ public function wait_for_sasl_response($event, $args) {
+ switch($event) {
+ case "stanza_cb":
+ $stanza = $args[0];
+
+ if($stanza->name == 'failure' && $stanza->ns == NS_SASL) {
+ $reason = $stanza->childrens[0]->name;
+ //_debug("sasl failed with reason ".$reason."");
+ $this->handle_auth_failure($reason);
+ return "logged_out";
+ }
+ else if($stanza->name == 'challenge' && $stanza->ns == NS_SASL) {
+ $challenge = $stanza->text;
+ $this->send_challenge_response($challenge);
+ return "wait_for_sasl_response";
+ }
+ else if($stanza->name == 'success' && $stanza->ns == NS_SASL) {
+ $this->xml->reset_parser();
+ $this->send_start_stream(@$this->jid);
+ return "wait_for_stream_start";
+ }
+ else {
+ _debug("got unhandled sasl response");
+ }
+
+ return "wait_for_sasl_response";
+ break;
+ default:
+ _debug("uncatched $event");
+ return $this->handle_other($event, $args);
+ //return array("wait_for_sasl_response", 0);
+ break;
+ }
+ }
+
+ public function wait_for_bind_response($event, $args) {
+ switch($event) {
+ case "stanza_cb":
+ $stanza = $args[0];
+
+ // TODO: chk on id
+ if($stanza->name == 'iq' && $stanza->attrs['type'] == 'result'
+ && ($jid = $stanza->exists('bind', NS_BIND)->exists('jid'))) {
+ $this->full_jid = new XMPPJid($jid->text);
+ $this->send_session_pkt();
+ return "wait_for_session_response";
+ }
+ else {
+ // FIXME:
+ }
+ break;
+ default:
+ _debug("uncatched $event");
+ return $this->handle_other($event, $args);
+ //return array("wait_for_bind_response", 0);
+ break;
+ }
+ }
+
+ public function wait_for_session_response($event, $args) {
+ switch($event) {
+ case "stanza_cb":
+ $this->handle_auth_success();
+ return "logged_in";
+ break;
+ default:
+ _debug("uncatched $event");
+ return $this->handle_other($event, $args);
+ //return array("wait_for_session_response", 0);
+ break;
+ }
+ }
+
+ public function logged_in($event, $args) {
+ switch($event) {
+ case "stanza_cb":
+ $stanza = $args[0];
+
+ // call abstract
+ if($stanza->name == 'message') {
+ $this->handle_message($stanza);
+ }
+ else if($stanza->name == 'presence') {
+ $this->handle_presence($stanza);
+ }
+ else if($stanza->name == 'iq') {
+ $this->handle_iq($stanza);
+ }
+ else {
+ $this->handle_other($event, $args);
+ }
+
+ return "logged_in";
+ break;
+ case "end_cb":
+ $this->send_end_stream();
+ return "logged_out";
+ break;
+ case "end_stream":
+ $this->send_end_stream();
+ return "logged_out";
+ break;
+ case "disconnect":
+ $this->trans->disconnect();
+ return "disconnected";
+ break;
+ default:
+ _debug("uncatched $event");
+ return $this->handle_other($event, $args);
+ //return array("logged_in", 0);
+ break;
+ }
+ }
+
+ public function logged_out($event, $args) {
+ switch($event) {
+ case "end_cb":
+ $this->trans->disconnect();
+ return "disconnected";
+ break;
+ case "end_stream":
+ return "disconnected";
+ break;
+ case "disconnect":
+ $this->trans->disconnect();
+ return "disconnected";
+ break;
+ case "connect":
+ return $this->do_connect($args);
+ break;
+ default:
+ // exit for any other event in logged_out state
+ _debug("uncatched $event");
+ return $this->handle_other($event, $args);
+ //return array("logged_out", 0);
+ break;
+ }
+ }
+
+}
+
+?>
Index: externals/JAXL/xmpp/xmpp_xep.php
===================================================================
--- /dev/null
+++ externals/JAXL/xmpp/xmpp_xep.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Jaxl (Jabber XMPP Library)
+ *
+ * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.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.
+ *
+ */
+
+/**
+ *
+ * @author abhinavsingh
+ *
+ */
+abstract class XMPPXep {
+
+ // init() method defines various callbacks
+ // required by this xep extension
+ abstract public function init();
+ //abstract public $description;
+ //abstract public $dependencies;
+
+ // reference to jaxl instance
+ // which required me
+ protected $jaxl = null;
+
+ public function __construct($jaxl) {
+ $this->jaxl = $jaxl;
+ }
+
+ public function __destruct() {
+
+ }
+
+}
+
+?>
Index: src/__phutil_library_map__.php
===================================================================
--- src/__phutil_library_map__.php
+++ src/__phutil_library_map__.php
@@ -1039,6 +1039,7 @@
'PhabricatorInlineCommentInterface' => 'infrastructure/diff/interface/PhabricatorInlineCommentInterface.php',
'PhabricatorInlineCommentPreviewController' => 'infrastructure/diff/PhabricatorInlineCommentPreviewController.php',
'PhabricatorInlineSummaryView' => 'infrastructure/diff/view/PhabricatorInlineSummaryView.php',
+ 'PhabricatorJabberProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorJabberProtocolAdapter.php',
'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/PhabricatorJavelinLinter.php',
'PhabricatorJumpNavHandler' => 'applications/search/engine/PhabricatorJumpNavHandler.php',
'PhabricatorKeyValueDatabaseCache' => 'applications/cache/PhabricatorKeyValueDatabaseCache.php',
@@ -2774,6 +2775,7 @@
'PhabricatorInlineCommentInterface' => 'PhabricatorMarkupInterface',
'PhabricatorInlineCommentPreviewController' => 'PhabricatorController',
'PhabricatorInlineSummaryView' => 'AphrontView',
+ 'PhabricatorJabberProtocolAdapter' => 'PhabricatorBaseProtocolAdapter',
'PhabricatorJavelinLinter' => 'ArcanistLinter',
'PhabricatorKeyValueDatabaseCache' => 'PhutilKeyValueCache',
'PhabricatorLDAPConfigOptions' => 'PhabricatorApplicationConfigOptions',
Index: src/infrastructure/daemon/bot/adapter/PhabricatorJabberProtocolAdapter.php
===================================================================
--- /dev/null
+++ src/infrastructure/daemon/bot/adapter/PhabricatorJabberProtocolAdapter.php
@@ -0,0 +1,94 @@
+<?php
+
+require_once dirname(phutil_get_library_root('phabricator')).'/externals/JAXL/jaxl.php';
+
+final class PhabricatorJabberProtocolAdapter
+ extends PhabricatorBaseProtocolAdapter {
+
+ public function getServiceType() {
+ return 'Jabber';
+ }
+
+ public function getServiceName() {
+ return $this->getConfig('server');
+ }
+
+ // Hash map of command translations
+ public static $commandTranslations = array(
+ 'PRIVMSG' => 'MESSAGE');
+
+ public function connect() {
+ $server = $this->getConfig('server');
+ $port = $this->getConfig('port', 5222);
+ $pass = $this->getConfig('pass');
+ $user = $this->getConfig('user');
+
+ $this->muc_host = $this->getConfig('muc_domain', $server);
+ $this->nick = $this->getConfig('nick', $user);
+
+ $this->messages = array();
+
+ $this->conn = new JAXL(array('jid' => "$user@$server", 'pass' => $pass, 'port' => $port, 'priv_dir' => '/tmp/.jaxl'));
+ $this->conn->require_xep(array('0045', '0199')); // 0045 is xep for MUC and 0199 is for ping
+
+ $this->conn->add_cb('on_auth_success', array($this, 'onAuthSuccess'));
+ $this->conn->add_cb('on_groupchat_message', array($this, 'onGroupMessage'));
+ $this->conn->connect($this->conn->get_socket_path());
+ $this->conn->start_stream();
+ JAXLLoop::$clock = new JAXLClock();
+ }
+
+ public function onAuthSuccess() {
+ $this->conn->set_status('');
+
+ foreach ($this->getConfig('join') as $room) {
+ $this->conn->xeps['0045']->join_room($room.'@'.$this->muc_host.'/'.$this->nick, array('no_history' => true));
+ }
+ }
+
+ public function onGroupMessage($stanza) {
+ if (!$stanza->exists('body')) {
+ return;
+ }
+
+ $senderJid = new XMPPJid($stanza->from);
+
+ $sender = id(new PhabricatorBotUser())->setName($senderJid->resource);
+ $target = id(new PhabricatorBotChannel())->setName($senderJid->node.'@'.$senderJid->domain);
+
+ $this->messages[] = id(new PhabricatorBotMessage())
+ ->setCommand("MESSAGE")
+ ->setSender($sender)
+ ->setTarget($target)
+ ->setBody($stanza->body);
+ }
+
+ public function getNextMessages($poll_frequency) {
+ JAXLLoop::$secs = $poll_frequency;
+ JAXLLoop::$usecs = 0;
+
+ JAXLLoop::select();
+
+ $messages = $this->messages;
+ $this->messages = array();
+
+ return $messages;
+ }
+
+ public function writeMessage(PhabricatorBotMessage $message) {
+ switch ($message->getCommand()) {
+ case 'MESSAGE':
+ case 'PASTE':
+ $name = $message->getTarget()->getName();
+ $body = $message->getBody();
+ $this->conn->xeps['0045']->send_groupchat($name, $body);
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public function __destruct() {
+ $this->conn->disconnect();
+ }
+}

File Metadata

Mime Type
text/plain
Expires
Mon, May 13, 3:29 PM (2 w, 5 d ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/3x/4x/sbwcin7idm2pvs7c
Default Alt Text
D5873.diff (331 KB)

Event Timeline