Sources for file plugins/class/pavid.php in version 4.0 Beta 1



Click on a comment to hide it. Click here to show all comments.

/**
 * Project:     Xnyo 4: Bubbles
 * File:        plugins/class/pavid.php
 *
 * Version:     4.0-dev
 * SVN Id:      $Id: pavid.php 5 2007-05-18 03:49:07Z bok $
 * SVN URL:     $HeadURL:
http://svn.syd.wholesalebroadband.com.au/xnyo/trunk/plugins/class/pavid.php $
 * Authors:     Robert Amos <bok[at]odynia.org>
 *
 * Copyright (c) 2001-2007 Robert Amos <bok[at]odynia.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/

/**
 * Pavid is our XML-RPC stuff
**/

class XnyoPavid implements XnyoClassPlugin
{
    
// Plugin Information
    
public $_plugin_info = array
    (
        
'name' => 'Pavid: Xnyo\'s XML-RPC server',
        '
description' => 'Server side software that listens for incoming XML-RPC requests, and acts
appropriately
',
        '
action' => XNYO_PLUGIN_ACTION_RETURN
    );
    
    /**
     * Information Storage
    **/
    private $request;
    private $response;
    private $xnyo;
    private $types;
    private $return = array();
    private $errors;

    /**
     * Constructor
    **/
    public function __construct ()
    {
        $this->xnyo = $GLOBALS['
xnyo_parent'];
    }

    /**
     * Handle bubble extras
    **/
    public function handleBubbleRequest ()
    {
        // is this a GET request?
        if ($_SERVER['
REQUEST_METHOD'] == 'GET')
        {
            global $bubbles;

            // sure is, lets get the details we'
re looking for.
            
$file explode(DIRSEPXnyoInput::filename(substr($_SERVER['REQUEST_URI'],
strlen($_SERVER['SCRIPT_NAME'])+1)));

            
// the bubble should be the first item
            
$bubble XnyoInput::safetext($file[0]);
            if (empty(
$bubble) || !$bubbles->isBubble($bubble))
                exit;

            
// let the XML error handlers take care of it if its not a valid request
            
if (count($file) == || count($file) == 4)
            {
                if (
count($file) == 4)
                {
                    
$f $file[3];
                    
$id XnyoInput::int($file[2]);
                } else
                {
                    
$f $file[2];
                    
$id 0;
                }

                
// the type should therefore be the second item.
                
switch (strtolower(XnyoInput::safetext($file[1])))
                {
                    case 
'script':
                    case 
'scripts':
                        if (!
$bubbles->isScript($bubble$f))
                            exit;
                        
header('Content-Type: text/plain');
                        echo 
$bubbles->fetchScript($bubble$f$id);
                        exit;
                    case 
'style':
                    case 
'stylesheets':
                    case 
'css':
                        if (!
$bubbles->isStylesheet($bubble$f))
                            exit;
                        
header('Content-Type: text/css');
                        echo 
$bubbles->fetchStylesheet($bubble$f$id);
                        exit;
                }
                exit;
            } elseif (
count($file) == 2)
            {
                
// ok, getting bubble html?
                
if (substr($file[1], -5) != '.html')
                    exit;

                
// the template name should be there then
                
$tpl substr($file[1], 0, -5).'.tpl';

                if (!
$bubbles->isHTML($bubble$tpl))
                    exit;

                echo 
$bubbles->fetchHTML($bubble$tpl);
                exit;
            }
        }
    }

    
/**
     * Parse the incoming Pavid Request
    **/
    
public function parse ($xml=null)
    {
        if (
is_null($xml))
        {
            
// is the incoming request XML?
            
$this->xnyo->fserver('CONTENT_TYPE''header');
            if (empty(
$_SERVER['CONTENT_TYPE']) || $_SERVER['CONTENT_TYPE'] != 'text/xml')
                return 
$this->error('Incoming Content Type (%s) is not text/xml'$_SERVER['CONTENT_TYPE']);

            
// have anything?
            
$this->xnyo->fserver('CONTENT_LENGTH''int');
            if (
$_SERVER['CONTENT_LENGTH'] <= 0)
                return 
$this->error('Incoming XML request body is empty.');

            
$fp fopen('php://input''r');
            
$xml '';
            while (!
feof($fp))
                
$xml .= fgets($fp);
            
fclose($fp);
        }

        
// make sure we have some XML
        
if (empty($xml))
            return 
$this->error('Supplied or resultant XML request is empty.');

        
// so we have our XML now, can we parse it?
        
$this->request simplexml_load_string($xml);

        
// did it parse ok?
        
if ($this->request === false)
            return 
$this->error('Supplied or resultant request is not valid XML.');

    }

    
/**
     * Process
     *
     * Process a parse'd Pavid request
    **/
    
public function process ()
    {
        if (empty(
$this->request))
        {
            return 
$this->error('No Pavid Request available to process.');
        }

        if (!
is_array($this->types))
            
$this->types $this->xnyo->storage->filter->get_valid_types();

        
/**
         * We expect a request to be in the format:
         *
         *     <?xml version="1.0"?>
         *     <pavid_request>
         *        <call>
         *            <method>plugin::method</method>
         *            <arguments>
         *                <arg type="<input method>">
         *                    Some stuff
         *                </arg>
         *                ...
         *            </arguments>
         *        </call>
         *        ...
         *    </pavid_request>
        **/

        // if there are no calls..
        
if (empty($this->request->call))
            return 
$this->error('No method calls available to be made.');

        
// loop over the call(s)
        
foreach ($this->request->call as $num => $call)
        {
            
// see if the call has no method
            
if (empty($call->method))
                
$this->add_error('No method found in call %s'$num);

            
// check our method
            
$m explode('::', (string)$call->method);
            
$c count($m);
            if (!
$c || $c || $c 3)
                
$this->add_error('Invalid method in call %s'$num);

            
// XnyoInput::safetext() all arguments
            
$m XnyoInput::_array($m'safetext');

            
// bubble
            
$type XNYO_PLUGIN_CLASS;
            if (
$c == && $m[0] == 'bubble')
            {
                
$type XNYO_PLUGIN_BUBBLE;
                
array_shift($m);
                
$c 2;
            }

            
// plugin
            
if ($c == 2)
            {
                
// check to make sure this is a valid plugin
                
try
                {
                    if (!
$this->xnyo->storage->plugins->is_loaded($m[0], $type))
                        
$o $this->xnyo->load($m[0], $type);
                } catch (
XnyoError $e)
                {
                    
$this->add_error('Provided method call %s is not valid.', (string)$call->method);
                    
$this->xnyo->storage->error->raise($e);
                    continue;
                }

                
// check to make sure the method exists
                
if (!is_object($o) || !method_exists($o$m[1]))
                {
                    
$this->add_error('Provided method call %s is not valid.', (string)$call->method);
                    continue;
                }

                
// check the methods signature
                
if (!is_array($o->{$m[1]}))
                {
                    
$this->add_error('Method %s does not have a Pavid Signature and cannot be called via Pavid.',
(string)
$call->method);
                    continue;
                }

                
// check the methods on the method signature
                
                
foreach ($o->{$m[1]} as $type)
                    if (!
in_array($type$this->types))
                    {
                        
$this->add_error('Type %s for method %s is not valid.'$type, (string)$call->method);
                        continue 
2;
                    }

                
// loop over each argument, filtering them
                
$i 0;
                
$args = array();
                if (!empty(
$call->arguments))
                    foreach (
$call->arguments->arg as $arg)
                    {
                        if (!isset(
$o->{$m[1]}[$i]) || empty ($o->{$m[1]}[$i]))
                        {
                            
$this->add_error('Too many arguments supplied for %s', (string)$call->method);
                            continue 
2;
                        }
                        
$t $o->{$m[1]}[$i];
                        
$args[] = XnyoInput::$t((string)$arg);
                        
$i++;
                    }

                try
                {
                    
// all our arguments are now parsed! call the requested method
                    
$r call_user_func_array(array($o$m[1]), $args);
                    if (
is_object($r) && $r instanceof PavidEvent)
                        
$this->return[$r->event()] = $r->args();
                    else
                        
$this->return['response::'.(string)$call->method] = $this->handleBoolean($r);
                } catch (
PavidError $e) {}
            }
        }
    }
    
    private function 
handleBoolean ($b)
    {
        if (
$b === true)
            return 
'true';
        elseif (
$b === false)
            return 
'false';
        else
            return 
$b;
    }
    
    
/**
     * Return our response(s) as xml
    **/
    
public function respond ($output=true)
    {
        
// merge any session-based requests with this one.
        
if (isset($_SESSION['_xnyo_pavid_responses']) && is_array($_SESSION['_xnyo_pavid_responses']))
            
$this->return += $_SESSION['_xnyo_pavid_responses'];

        
// here we go then!
        
$xml '<?xml version="1.0"?><pavid_response>';

        
// any errors?
        
if (!empty($this->errors))
        {
            
$xml .= '<errors>';
            foreach (
$this->errors as $e)
                
$xml .= '<error>' $e '</error>';
            
$xml .= '</errors>';
        }

        
// any responses?
        
if (!empty($this->return))
            foreach (
$this->return as $k => $v)
            {
                
$xml .= '<call><event>'.$k.'</event><arguments>';
                foreach ((array)
$v as $x)
                    
$xml .= '<arg><![CDATA['.$x.']]></arg>';
                
$xml .= '</arguments></call>';
            }

        
$xml .= '</pavid_response>';

        
// output it
        
if ($output)
        {
            
header('Content-Type: text/xml');
            echo 
$xml;
            exit;
        }

        
// return it
        
return $xml;
    }

    
/**
     * Error
    **/
    
public function error ()
    {
        
$args func_get_args();
        
$this->errors[] = call_user_func_array('sprintf'$args);
        
$this->xnyo->storage->error->raise(new XnyoError(call_user_func_array('sprintf'$args)));
        
$this->respond();
        
    }
    public function 
add_error ()
    {
        
$args func_get_args();
        
$this->errors[] = call_user_func_array('sprintf'$args);
        
$this->xnyo->storage->error->raise(new XnyoError(call_user_func_array('sprintf'$args)));
    }
}

/**
 * Pavid Event Object
**/
class PavidEvent implements XnyoClassPlugin
{
    
// Plugin Information
    
public $_plugin_info = array
    (
        
'name' => 'Pavid Response Object',
        
'description' => 'Return a new instance of this object to invoke an event in the bubble system',
        
'action' => XNYO_PLUGIN_ACTION_NONE
    
);

    
/**
     * Storage
    **/
    
protected $event;
    protected 
$args;

    
/**
     * Constructor
    **/
    
public function __construct ($event$args)
    {
        
$this->event $event;
        
$this->args = (array)$args;
    }

    
/**
     * Get the Event
    **/
    
public function event ()
    {
        return 
$this->event;
    }

    
/**
     * Get the supplied arguments
    **/
    
public function args ()
    {
        return 
$this->args;
    }
}

class 
PavidError extends Exception
{
    
/**
     * Constructor
    **/
    
public function __construct ()
    {
        global 
$xnyo_parent;
        
$args func_get_args();
        
call_user_func_array(array($xnyo_parent->storage->plugins->get_plugin_reference('pavid',
XNYO_PLUGIN_CLASS), 'add_error'), $args);
    }
}

Website is Copyright © Odynia.org 2000-2005 - Xnyo is released under a BSD license.