text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Log
 * @subpackage Writer
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Mail.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** Zend_Log_Writer_Abstract */
require_once 'Zend/Log/Writer/Abstract.php';

/** Zend_Log_Exception */
require_once 'Zend/Log/Exception.php';

/** Zend_Log_Formatter_Simple*/
require_once 'Zend/Log/Formatter/Simple.php';

/**
 * Class used for writing log messages to email via Zend_Mail.
 *
 * Allows for emailing log messages at and above a certain level via a
 * Zend_Mail object.  Note that this class only sends the email upon
 * completion, so any log entries accumulated are sent in a single email.
 *
 * @category   Zend
 * @package    Zend_Log
 * @subpackage Writer
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Mail.php 23775 2011-03-01 17:25:24Z ralph $
 */
class Zend_Log_Writer_Mail extends Zend_Log_Writer_Abstract
{
    /**
     * Array of formatted events to include in message body.
     *
     * @var array
     */
    protected $_eventsToMail = array();

    /**
     * Array of formatted lines for use in an HTML email body; these events
     * are formatted with an optional formatter if the caller is using
     * Zend_Layout.
     *
     * @var array
     */
    protected $_layoutEventsToMail = array();

    /**
     * Zend_Mail instance to use
     *
     * @var Zend_Mail
     */
    protected $_mail;

    /**
     * Zend_Layout instance to use; optional.
     *
     * @var Zend_Layout
     */
    protected $_layout;

    /**
     * Optional formatter for use when rendering with Zend_Layout.
     *
     * @var Zend_Log_Formatter_Interface
     */
    protected $_layoutFormatter;

    /**
     * Array keeping track of the number of entries per priority level.
     *
     * @var array
     */
    protected $_numEntriesPerPriority = array();

    /**
     * Subject prepend text.
     *
     * Can only be used of the Zend_Mail object has not already had its
     * subject line set.  Using this will cause the subject to have the entry
     * counts per-priority level appended to it.
     *
     * @var string|null
     */
    protected $_subjectPrependText;

    /**
     * MethodMap for Zend_Mail's headers
     *
     * @var array
     */
    protected static $_methodMapHeaders = array(
        'from' => 'setFrom',
        'to' => 'addTo',
        'cc' => 'addCc',
        'bcc' => 'addBcc',
    );

    /**
     * Class constructor.
     *
     * Constructs the mail writer; requires a Zend_Mail instance, and takes an
     * optional Zend_Layout instance.  If Zend_Layout is being used,
     * $this->_layout->events will be set for use in the layout template.
     *
     * @param  Zend_Mail $mail Mail instance
     * @param  Zend_Layout $layout Layout instance; optional
     * @return void
     */
    public function __construct(Zend_Mail $mail, Zend_Layout $layout = null)
    {
        $this->_mail = $mail;
        if (null !== $layout) {
            $this->setLayout($layout);
        }
        $this->_formatter = new Zend_Log_Formatter_Simple();
    }

    /**
     * Create a new instance of Zend_Log_Writer_Mail
     *
     * @param  array|Zend_Config $config
     * @return Zend_Log_Writer_Mail
     */
    static public function factory($config)
    {
        $config = self::_parseConfig($config);
        $mail = self::_constructMailFromConfig($config);
        $writer = new self($mail);

        if (isset($config['layout']) || isset($config['layoutOptions'])) {
            $writer->setLayout($config);
        }
        if (isset($config['layoutFormatter'])) {
            $layoutFormatter = new $config['layoutFormatter'];
            $writer->setLayoutFormatter($layoutFormatter);
        }
        if (isset($config['subjectPrependText'])) {
            $writer->setSubjectPrependText($config['subjectPrependText']);
        }

        return $writer;
    }

    /**
     * Set the layout
     *
     * @param Zend_Layout|array $layout
     * @return Zend_Log_Writer_Mail
     * @throws Zend_Log_Exception
     */
    public function setLayout($layout)
    {
        if (is_array($layout)) {
            $layout = $this->_constructLayoutFromConfig($layout);
        }

        if (!$layout instanceof Zend_Layout) {
            require_once 'Zend/Log/Exception.php';
            throw new Zend_Log_Exception('Mail must be an instance of Zend_Layout or an array');
        }
        $this->_layout = $layout;

        return $this;
    }

    /**
     * Construct a Zend_Mail instance based on a configuration array
     *
     * @param array $config
     * @return Zend_Mail
     * @throws Zend_Log_Exception
     */
    protected static function _constructMailFromConfig(array $config)
    {
        $mailClass = 'Zend_Mail';
        if (isset($config['mail'])) {
            $mailClass = $config['mail'];
        }

        if (!array_key_exists('charset', $config)) {
            $config['charset'] = null;
        }
        $mail = new $mailClass($config['charset']);
        if (!$mail instanceof Zend_Mail) {
            throw new Zend_Log_Exception($mail . 'must extend Zend_Mail');
        }

        if (isset($config['subject'])) {
            $mail->setSubject($config['subject']);
        }

        $headerAddresses = array_intersect_key($config, self::$_methodMapHeaders);
        if (count($headerAddresses)) {
            foreach ($headerAddresses as $header => $address) {
                $method = self::$_methodMapHeaders[$header];
                if (is_array($address) && isset($address['name'])
                    && !is_numeric($address['name'])
                ) {
                    $params = array(
                        $address['email'],
                        $address['name']
                    );
                } else if (is_array($address) && isset($address['email'])) {
                    $params = array($address['email']);
                } else {
                    $params = array($address);
                }
                call_user_func_array(array($mail, $method), $params);
            }
        }

        return $mail;
    }

    /**
     * Construct a Zend_Layout instance based on a configuration array
     *
     * @param array $config
     * @return Zend_Layout
     * @throws Zend_Log_Exception
     */
    protected function _constructLayoutFromConfig(array $config)
    {
        $config = array_merge(array(
            'layout' => 'Zend_Layout',
            'layoutOptions' => null
        ), $config);

        $layoutClass = $config['layout'];
        $layout = new $layoutClass($config['layoutOptions']);
        if (!$layout instanceof Zend_Layout) {
            throw new Zend_Log_Exception($layout . 'must extend Zend_Layout');
        }

        return $layout;
    }

    /**
     * Places event line into array of lines to be used as message body.
     *
     * Handles the formatting of both plaintext entries, as well as those
     * rendered with Zend_Layout.
     *
     * @param  array $event Event data
     * @return void
     */
    protected function _write($event)
    {
        // Track the number of entries per priority level.
        if (!isset($this->_numEntriesPerPriority[$event['priorityName']])) {
            $this->_numEntriesPerPriority[$event['priorityName']] = 1;
        } else {
            $this->_numEntriesPerPriority[$event['priorityName']]++;
        }

        $formattedEvent = $this->_formatter->format($event);

        // All plaintext events are to use the standard formatter.
        $this->_eventsToMail[] = $formattedEvent;

        // If we have a Zend_Layout instance, use a specific formatter for the
        // layout if one exists.  Otherwise, just use the event with its
        // default format.
        if ($this->_layout) {
            if ($this->_layoutFormatter) {
                $this->_layoutEventsToMail[] =
                    $this->_layoutFormatter->format($event);
            } else {
                $this->_layoutEventsToMail[] = $formattedEvent;
            }
        }
    }

    /**
     * Gets instance of Zend_Log_Formatter_Instance used for formatting a
     * message using Zend_Layout, if applicable.
     *
     * @return Zend_Log_Formatter_Interface|null The formatter, or null.
     */
    public function getLayoutFormatter()
    {
        return $this->_layoutFormatter;
    }

    /**
     * Sets a specific formatter for use with Zend_Layout events.
     *
     * Allows use of a second formatter on lines that will be rendered with
     * Zend_Layout.  In the event that Zend_Layout is not being used, this
     * formatter cannot be set, so an exception will be thrown.
     *
     * @param  Zend_Log_Formatter_Interface $formatter
     * @return Zend_Log_Writer_Mail
     * @throws Zend_Log_Exception
     */
    public function setLayoutFormatter(Zend_Log_Formatter_Interface $formatter)
    {
        if (!$this->_layout) {
            throw new Zend_Log_Exception(
                'cannot set formatter for layout; ' .
                    'a Zend_Layout instance is not in use');
        }

        $this->_layoutFormatter = $formatter;
        return $this;
    }

    /**
     * Allows caller to have the mail subject dynamically set to contain the
     * entry counts per-priority level.
     *
     * Sets the text for use in the subject, with entry counts per-priority
     * level appended to the end.  Since a Zend_Mail subject can only be set
     * once, this method cannot be used if the Zend_Mail object already has a
     * subject set.
     *
     * @param  string $subject Subject prepend text.
     * @return Zend_Log_Writer_Mail
     * @throws Zend_Log_Exception
     */
    public function setSubjectPrependText($subject)
    {
        if ($this->_mail->getSubject()) {
            throw new Zend_Log_Exception(
                'subject already set on mail; ' .
                    'cannot set subject prepend text');
        }

        $this->_subjectPrependText = (string) $subject;
        return $this;
    }

    /**
     * Sends mail to recipient(s) if log entries are present.  Note that both
     * plaintext and HTML portions of email are handled here.
     *
     * @return void
     */
    public function shutdown()
    {
        // If there are events to mail, use them as message body.  Otherwise,
        // there is no mail to be sent.
        if (empty($this->_eventsToMail)) {
            return;
        }

        if ($this->_subjectPrependText !== null) {
            // Tack on the summary of entries per-priority to the subject
            // line and set it on the Zend_Mail object.
            $numEntries = $this->_getFormattedNumEntriesPerPriority();
            $this->_mail->setSubject(
                "{$this->_subjectPrependText} ({$numEntries})");
        }

        // Always provide events to mail as plaintext.
        $this->_mail->setBodyText(implode('', $this->_eventsToMail));

        // If a Zend_Layout instance is being used, set its "events"
        // value to the lines formatted for use with the layout.
        if ($this->_layout) {
            // Set the required "messages" value for the layout.  Here we
            // are assuming that the layout is for use with HTML.
            $this->_layout->events =
                implode('', $this->_layoutEventsToMail);

            // If an exception occurs during rendering, convert it to a notice
            // so we can avoid an exception thrown without a stack frame.
            try {
                $this->_mail->setBodyHtml($this->_layout->render());
            } catch (Exception $e) {
                trigger_error(
                    "exception occurred when rendering layout; " .
                        "unable to set html body for message; " .
                        "message = {$e->getMessage()}; " .
                        "code = {$e->getCode()}; " .
                        "exception class = " . get_class($e),
                    E_USER_NOTICE);
            }
        }

        // Finally, send the mail.  If an exception occurs, convert it into a
        // warning-level message so we can avoid an exception thrown without a
        // stack frame.
        try {
            $this->_mail->send();
        } catch (Exception $e) {
            trigger_error(
                "unable to send log entries via email; " .
                    "message = {$e->getMessage()}; " .
                    "code = {$e->getCode()}; " .
                        "exception class = " . get_class($e),
                E_USER_WARNING);
        }
    }

    /**
     * Gets a string of number of entries per-priority level that occurred, or
     * an emptry string if none occurred.
     *
     * @return string
     */
    protected function _getFormattedNumEntriesPerPriority()
    {
        $strings = array();

        foreach ($this->_numEntriesPerPriority as $priority => $numEntries) {
            $strings[] = "{$priority}={$numEntries}";
        }

        return implode(', ', $strings);
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Log
 * @subpackage Writer
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Db.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** Zend_Log_Writer_Abstract */
require_once 'Zend/Log/Writer/Abstract.php';

/**
 * @category   Zend
 * @package    Zend_Log
 * @subpackage Writer
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Db.php 23775 2011-03-01 17:25:24Z ralph $
 */
class Zend_Log_Writer_Db extends Zend_Log_Writer_Abstract
{
    /**
     * Database adapter instance
     *
     * @var Zend_Db_Adapter
     */
    private $_db;

    /**
     * Name of the log table in the database
     *
     * @var string
     */
    private $_table;

    /**
     * Relates database columns names to log data field keys.
     *
     * @var null|array
     */
    private $_columnMap;

    /**
     * Class constructor
     *
     * @param Zend_Db_Adapter $db   Database adapter instance
     * @param string $table         Log table in database
     * @param array $columnMap
     * @return void
     */
    public function __construct($db, $table, $columnMap = null)
    {
        $this->_db    = $db;
        $this->_table = $table;
        $this->_columnMap = $columnMap;
    }

    /**
     * Create a new instance of Zend_Log_Writer_Db
     *
     * @param  array|Zend_Config $config
     * @return Zend_Log_Writer_Db
     */
    static public function factory($config)
    {
        $config = self::_parseConfig($config);
        $config = array_merge(array(
            'db'        => null,
            'table'     => null,
            'columnMap' => null,
        ), $config);

        if (isset($config['columnmap'])) {
            $config['columnMap'] = $config['columnmap'];
        }

        return new self(
            $config['db'],
            $config['table'],
            $config['columnMap']
        );
    }

    /**
     * Formatting is not possible on this writer
     *
     * @return void
     * @throws Zend_Log_Exception
     */
    public function setFormatter(Zend_Log_Formatter_Interface $formatter)
    {
        require_once 'Zend/Log/Exception.php';
        throw new Zend_Log_Exception(get_class($this) . ' does not support formatting');
    }

    /**
     * Remove reference to database adapter
     *
     * @return void
     */
    public function shutdown()
    {
        $this->_db = null;
    }

    /**
     * Write a message to the log.
     *
     * @param  array  $event  event data
     * @return void
     * @throws Zend_Log_Exception
     */
    protected function _write($event)
    {
        if ($this->_db === null) {
            require_once 'Zend/Log/Exception.php';
            throw new Zend_Log_Exception('Database adapter is null');
        }

        if ($this->_columnMap === null) {
            $dataToInsert = $event;
        } else {
            $dataToInsert = array();
            foreach ($this->_columnMap as $columnName => $fieldKey) {
                $dataToInsert[$columnName] = $event[$fieldKey];
            }
        }

        $this->_db->insert($this->_table, $dataToInsert);
    }
}

repo_name: michael-romer/zf-boilerplate

repo_language: PHP

mime_type: text/html


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Log
 * @subpackage Writer
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: ZendMonitor.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** Zend_Log_Writer_Abstract */
require_once 'Zend/Log/Writer/Abstract.php';

/**
 * @category   Zend
 * @package    Zend_Log
 * @subpackage Writer
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: ZendMonitor.php 23775 2011-03-01 17:25:24Z ralph $
 */
class Zend_Log_Writer_ZendMonitor extends Zend_Log_Writer_Abstract
{
    /**
     * Is Zend Monitor enabled?
     *
     * @var boolean
     */
    protected $_isEnabled = true;

    /**
     * Is this for a Zend Server intance?
     *
     * @var boolean
     */
    protected $_isZendServer = false;

    /**
     * @return void
     */
    public function __construct()
    {
        if (!function_exists('monitor_custom_event')) {
            $this->_isEnabled = false;
        }
        if (function_exists('zend_monitor_custom_event')) {
            $this->_isZendServer = true;
        }
    }

    /**
     * Create a new instance of Zend_Log_Writer_ZendMonitor
     *
     * @param  array|Zend_Config $config
     * @return Zend_Log_Writer_ZendMonitor
     */
    static public function factory($config)
    {
        return new self();
    }

    /**
     * Is logging to this writer enabled?
     *
     * If the Zend Monitor extension is not enabled, this log writer will
     * fail silently. You can query this method to determine if the log
     * writer is enabled.
     *
     * @return boolean
     */
    public function isEnabled()
    {
        return $this->_isEnabled;
    }

    /**
     * Log a message to this writer.
     *
     * @param  array $event log data event
     * @return void
     */
    public function write($event)
    {
        if (!$this->isEnabled()) {
            return;
        }

        parent::write($event);
    }

    /**
     * Write a message to the log.
     *
     * @param  array  $event log data event
     * @return void
     */
    protected function _write($event)
    {
        $priority = $event['priority'];
        $message  = $event['message'];
        unset($event['priority'], $event['message']);

        if (!empty($event)) {
            if ($this->_isZendServer) {
                // On Zend Server; third argument should be the event
                zend_monitor_custom_event($priority, $message, $event);
            } else {
                // On Zend Platform; third argument is severity -- either
                // 0 or 1 -- and fourth is optional (event)
                // Severity is either 0 (normal) or 1 (severe); classifying
                // notice, info, and debug as "normal", and all others as
                // "severe"
                monitor_custom_event($priority, $message, ($priority > 4) ? 0 : 1, $event);
            }
        } else {
            monitor_custom_event($priority, $message);
        }
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Log
 * @subpackage Writer
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Abstract.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** Zend_Log_Filter_Priority */
require_once 'Zend/Log/Filter/Priority.php';

/**
 * @category   Zend
 * @package    Zend_Log
 * @subpackage Writer
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Abstract.php 23775 2011-03-01 17:25:24Z ralph $
 */
abstract class Zend_Log_Writer_Abstract implements Zend_Log_FactoryInterface
{
    /**
     * @var array of Zend_Log_Filter_Interface
     */
    protected $_filters = array();

    /**
     * Formats the log message before writing.
     *
     * @var Zend_Log_Formatter_Interface
     */
    protected $_formatter;

    /**
     * Add a filter specific to this writer.
     *
     * @param  Zend_Log_Filter_Interface  $filter
     * @return Zend_Log_Writer_Abstract
     */
    public function addFilter($filter)
    {
        if (is_int($filter)) {
            $filter = new Zend_Log_Filter_Priority($filter);
        }

        if (!$filter instanceof Zend_Log_Filter_Interface) {
            /** @see Zend_Log_Exception */
            require_once 'Zend/Log/Exception.php';
            throw new Zend_Log_Exception('Invalid filter provided');
        }

        $this->_filters[] = $filter;
        return $this;
    }

    /**
     * Log a message to this writer.
     *
     * @param  array $event log data event
     * @return void
     */
    public function write($event)
    {
        foreach ($this->_filters as $filter) {
            if (! $filter->accept($event)) {
                return;
            }
        }

        // exception occurs on error
        $this->_write($event);
    }

    /**
     * Set a new formatter for this writer
     *
     * @param  Zend_Log_Formatter_Interface $formatter
     * @return Zend_Log_Writer_Abstract
     */
    public function setFormatter(Zend_Log_Formatter_Interface $formatter)
    {
        $this->_formatter = $formatter;
        return $this;
    }

    /**
     * Perform shutdown activites such as closing open resources
     *
     * @return void
     */
    public function shutdown()
    {}

    /**
     * Write a message to the log.
     *
     * @param  array  $event  log data event
     * @return void
     */
    abstract protected function _write($event);

    /**
     * Validate and optionally convert the config to array
     *
     * @param  array|Zend_Config $config Zend_Config or Array
     * @return array
     * @throws Zend_Log_Exception
     */
    static protected function _parseConfig($config)
    {
        if ($config instanceof Zend_Config) {
            $config = $config->toArray();
        }

        if (!is_array($config)) {
            require_once 'Zend/Log/Exception.php';
            throw new Zend_Log_Exception(
                'Configuration must be an array or instance of Zend_Config'
            );
        }

        return $config;
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Log
 * @subpackage Writer
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Mock.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** Zend_Log_Writer_Abstract */
require_once 'Zend/Log/Writer/Abstract.php';

/**
 * @category   Zend
 * @package    Zend_Log
 * @subpackage Writer
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Mock.php 23775 2011-03-01 17:25:24Z ralph $
 */
class Zend_Log_Writer_Mock extends Zend_Log_Writer_Abstract
{
    /**
     * array of log events
     *
     * @var array
     */
    public $events = array();

    /**
     * shutdown called?
     *
     * @var boolean
     */
    public $shutdown = false;

    /**
     * Write a message to the log.
     *
     * @param  array  $event  event data
     * @return void
     */
    public function _write($event)
    {
        $this->events[] = $event;
    }

    /**
     * Record shutdown
     *
     * @return void
     */
    public function shutdown()
    {
        $this->shutdown = true;
    }

    /**
     * Create a new instance of Zend_Log_Writer_Mock
     *
     * @param  array|Zend_Config $config
     * @return Zend_Log_Writer_Mock
     */
    static public function factory($config)
    {
        return new self();
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Controller
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */

/**
 * Zend_XmlRpc_Value
 */
require_once 'Zend/XmlRpc/Value.php';

/**
 * Zend_XmlRpc_Fault
 */
require_once 'Zend/XmlRpc/Fault.php';

/**
 * XmlRpc Request object
 *
 * Encapsulates an XmlRpc request, holding the method call and all parameters.
 * Provides accessors for these, as well as the ability to load from XML and to
 * create the XML request string.
 *
 * Additionally, if errors occur setting the method or parsing XML, a fault is
 * generated and stored in {@link $_fault}; developers may check for it using
 * {@link isFault()} and {@link getFault()}.
 *
 * @category Zend
 * @package  Zend_XmlRpc
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version $Id: Request.php 23775 2011-03-01 17:25:24Z ralph $
 */
class Zend_XmlRpc_Request
{
    /**
     * Request character encoding
     * @var string
     */
    protected $_encoding = 'UTF-8';

    /**
     * Method to call
     * @var string
     */
    protected $_method;

    /**
     * XML request
     * @var string
     */
    protected $_xml;

    /**
     * Method parameters
     * @var array
     */
    protected $_params = array();

    /**
     * Fault object, if any
     * @var Zend_XmlRpc_Fault
     */
    protected $_fault = null;

    /**
     * XML-RPC type for each param
     * @var array
     */
    protected $_types = array();

    /**
     * XML-RPC request params
     * @var array
     */
    protected $_xmlRpcParams = array();

    /**
     * Create a new XML-RPC request
     *
     * @param string $method (optional)
     * @param array $params  (optional)
     */
    public function __construct($method = null, $params = null)
    {
        if ($method !== null) {
            $this->setMethod($method);
        }

        if ($params !== null) {
            $this->setParams($params);
        }
    }

    /**
     * Set encoding to use in request
     *
     * @param string $encoding
     * @return Zend_XmlRpc_Request
     */
    public function setEncoding($encoding)
    {
        $this->_encoding = $encoding;
        Zend_XmlRpc_Value::setEncoding($encoding);
        return $this;
    }

    /**
     * Retrieve current request encoding
     *
     * @return string
     */
    public function getEncoding()
    {
        return $this->_encoding;
    }

    /**
     * Set method to call
     *
     * @param string $method
     * @return boolean Returns true on success, false if method name is invalid
     */
    public function setMethod($method)
    {
        if (!is_string($method) || !preg_match('/^[a-z0-9_.:\/]+$/i', $method)) {
            $this->_fault = new Zend_XmlRpc_Fault(634, 'Invalid method name ("' . $method . '")');
            $this->_fault->setEncoding($this->getEncoding());
            return false;
        }

        $this->_method = $method;
        return true;
    }

    /**
     * Retrieve call method
     *
     * @return string
     */
    public function getMethod()
    {
        return $this->_method;
    }

    /**
     * Add a parameter to the parameter stack
     *
     * Adds a parameter to the parameter stack, associating it with the type
     * $type if provided
     *
     * @param mixed $value
     * @param string $type Optional; type hinting
     * @return void
     */
    public function addParam($value, $type = null)
    {
        $this->_params[] = $value;
        if (null === $type) {
            // Detect type if not provided explicitly
            if ($value instanceof Zend_XmlRpc_Value) {
                $type = $value->getType();
            } else {
                $xmlRpcValue = Zend_XmlRpc_Value::getXmlRpcValue($value);
                $type        = $xmlRpcValue->getType();
            }
        }
        $this->_types[]  = $type;
        $this->_xmlRpcParams[] = array('value' => $value, 'type' => $type);
    }

    /**
     * Set the parameters array
     *
     * If called with a single, array value, that array is used to set the
     * parameters stack. If called with multiple values or a single non-array
     * value, the arguments are used to set the parameters stack.
     *
     * Best is to call with array of the format, in order to allow type hinting
     * when creating the XMLRPC values for each parameter:
     * <code>
     * $array = array(
     *     array(
     *         'value' => $value,
     *         'type'  => $type
     *     )[, ... ]
     * );
     * </code>
     *
     * @access public
     * @return void
     */
    public function setParams()
    {
        $argc = func_num_args();
        $argv = func_get_args();
        if (0 == $argc) {
            return;
        }

        if ((1 == $argc) && is_array($argv[0])) {
            $params     = array();
            $types      = array();
            $wellFormed = true;
            foreach ($argv[0] as $arg) {
                if (!is_array($arg) || !isset($arg['value'])) {
                    $wellFormed = false;
                    break;
                }
                $params[] = $arg['value'];

                if (!isset($arg['type'])) {
                    $xmlRpcValue = Zend_XmlRpc_Value::getXmlRpcValue($arg['value']);
                    $arg['type'] = $xmlRpcValue->getType();
                }
                $types[] = $arg['type'];
            }
            if ($wellFormed) {
                $this->_xmlRpcParams = $argv[0];
                $this->_params = $params;
                $this->_types  = $types;
            } else {
                $this->_params = $argv[0];
                $this->_types  = array();
                $xmlRpcParams  = array();
                foreach ($argv[0] as $arg) {
                    if ($arg instanceof Zend_XmlRpc_Value) {
                        $type = $arg->getType();
                    } else {
                        $xmlRpcValue = Zend_XmlRpc_Value::getXmlRpcValue($arg);
                        $type        = $xmlRpcValue->getType();
                    }
                    $xmlRpcParams[] = array('value' => $arg, 'type' => $type);
                    $this->_types[] = $type;
                }
                $this->_xmlRpcParams = $xmlRpcParams;
            }
            return;
        }

        $this->_params = $argv;
        $this->_types  = array();
        $xmlRpcParams  = array();
        foreach ($argv as $arg) {
            if ($arg instanceof Zend_XmlRpc_Value) {
                $type = $arg->getType();
            } else {
                $xmlRpcValue = Zend_XmlRpc_Value::getXmlRpcValue($arg);
                $type        = $xmlRpcValue->getType();
            }
            $xmlRpcParams[] = array('value' => $arg, 'type' => $type);
            $this->_types[] = $type;
        }
        $this->_xmlRpcParams = $xmlRpcParams;
    }

    /**
     * Retrieve the array of parameters
     *
     * @return array
     */
    public function getParams()
    {
        return $this->_params;
    }

    /**
     * Return parameter types
     *
     * @return array
     */
    public function getTypes()
    {
        return $this->_types;
    }

    /**
     * Load XML and parse into request components
     *
     * @param string $request
     * @return boolean True on success, false if an error occurred.
     */
    public function loadXml($request)
    {
        if (!is_string($request)) {
            $this->_fault = new Zend_XmlRpc_Fault(635);
            $this->_fault->setEncoding($this->getEncoding());
            return false;
        }

        try {
            $xml = new SimpleXMLElement($request);
        } catch (Exception $e) {
            // Not valid XML
            $this->_fault = new Zend_XmlRpc_Fault(631);
            $this->_fault->setEncoding($this->getEncoding());
            return false;
        }

        // Check for method name
        if (empty($xml->methodName)) {
            // Missing method name
            $this->_fault = new Zend_XmlRpc_Fault(632);
            $this->_fault->setEncoding($this->getEncoding());
            return false;
        }

        $this->_method = (string) $xml->methodName;

        // Check for parameters
        if (!empty($xml->params)) {
            $types = array();
            $argv  = array();
            foreach ($xml->params->children() as $param) {
                if (!isset($param->value)) {
                    $this->_fault = new Zend_XmlRpc_Fault(633);
                    $this->_fault->setEncoding($this->getEncoding());
                    return false;
                }

                try {
                    $param   = Zend_XmlRpc_Value::getXmlRpcValue($param->value, Zend_XmlRpc_Value::XML_STRING);
                    $types[] = $param->getType();
                    $argv[]  = $param->getValue();
                } catch (Exception $e) {
                    $this->_fault = new Zend_XmlRpc_Fault(636);
                    $this->_fault->setEncoding($this->getEncoding());
                    return false;
                }
            }

            $this->_types  = $types;
            $this->_params = $argv;
        }

        $this->_xml = $request;

        return true;
    }

    /**
     * Does the current request contain errors and should it return a fault
     * response?
     *
     * @return boolean
     */
    public function isFault()
    {
        return $this->_fault instanceof Zend_XmlRpc_Fault;
    }

    /**
     * Retrieve the fault response, if any
     *
     * @return null|Zend_XmlRpc_Fault
     */
    public function getFault()
    {
        return $this->_fault;
    }

    /**
     * Retrieve method parameters as XMLRPC values
     *
     * @return array
     */
    protected function _getXmlRpcParams()
    {
        $params = array();
        if (is_array($this->_xmlRpcParams)) {
            foreach ($this->_xmlRpcParams as $param) {
                $value = $param['value'];
                $type  = isset($param['type']) ? $param['type'] : Zend_XmlRpc_Value::AUTO_DETECT_TYPE;

                if (!$value instanceof Zend_XmlRpc_Value) {
                    $value = Zend_XmlRpc_Value::getXmlRpcValue($value, $type);
                }
                $params[] = $value;
            }
        }

        return $params;
    }

    /**
     * Create XML request
     *
     * @return string
     */
    public function saveXml()
    {
        $args   = $this->_getXmlRpcParams();
        $method = $this->getMethod();

        $generator = Zend_XmlRpc_Value::getGenerator();
        $generator->openElement('methodCall')
                  ->openElement('methodName', $method)
                  ->closeElement('methodName');

        if (is_array($args) && count($args)) {
            $generator->openElement('params');

            foreach ($args as $arg) {
                $generator->openElement('param');
                $arg->generateXml();
                $generator->closeElement('param');
            }
            $generator->closeElement('params');
        }
        $generator->closeElement('methodCall');

        return $generator->flush();
    }

    /**
     * Return XML request
     *
     * @return string
     */
    public function __toString()
    {
        return $this->saveXML();
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_XmlRpc
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Exception.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * Zend_Exception
 */
require_once 'Zend/Exception.php';

/**
 * @category   Zend
 * @package    Zend_XmlRpc
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_XmlRpc_Exception extends Zend_Exception
{}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_XmlRpc
 * @subpackage Client
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Client.php 24159 2011-06-28 12:30:56Z adamlundrigan $
 */

/**
 * For handling the HTTP connection to the XML-RPC service
 * @see Zend_Http_Client
 */
require_once 'Zend/Http/Client.php';

/**
 * Enables object chaining for calling namespaced XML-RPC methods.
 * @see Zend_XmlRpc_Client_ServerProxy
 */
require_once 'Zend/XmlRpc/Client/ServerProxy.php';

/**
 * Introspects remote servers using the XML-RPC de facto system.* methods
 * @see Zend_XmlRpc_Client_ServerIntrospection
 */
require_once 'Zend/XmlRpc/Client/ServerIntrospection.php';

/**
 * Represent a native XML-RPC value, used both in sending parameters
 * to methods and as the parameters retrieve from method calls
 * @see Zend_XmlRpc_Value
 */
require_once 'Zend/XmlRpc/Value.php';

/**
 * XML-RPC Request
 * @see Zend_XmlRpc_Request
 */
require_once 'Zend/XmlRpc/Request.php';

/**
 * XML-RPC Response
 * @see Zend_XmlRpc_Response
 */
require_once 'Zend/XmlRpc/Response.php';

/**
 * XML-RPC Fault
 * @see Zend_XmlRpc_Fault
 */
require_once 'Zend/XmlRpc/Fault.php';

/**
 * An XML-RPC client implementation
 *
 * @category   Zend
 * @package    Zend_XmlRpc
 * @subpackage Client
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_XmlRpc_Client
{
    /**
     * Full address of the XML-RPC service
     * @var string
     * @example http://time.xmlrpc.com/RPC2
     */
    protected $_serverAddress;

    /**
     * HTTP Client to use for requests
     * @var Zend_Http_Client
     */
    protected $_httpClient = null;

    /**
     * Introspection object
     * @var Zend_Http_Client_Introspector
     */
    protected $_introspector = null;

    /**
     * Request of the last method call
     * @var Zend_XmlRpc_Request
     */
    protected $_lastRequest = null;

    /**
     * Response received from the last method call
     * @var Zend_XmlRpc_Response
     */
    protected $_lastResponse = null;

    /**
     * Proxy object for more convenient method calls
     * @var array of Zend_XmlRpc_Client_ServerProxy
     */
    protected $_proxyCache = array();

    /**
     * Flag for skipping system lookup
     * @var bool
     */
    protected $_skipSystemLookup = false;

    /**
     * Create a new XML-RPC client to a remote server
     *
     * @param  string $server      Full address of the XML-RPC service
     *                             (e.g. http://time.xmlrpc.com/RPC2)
     * @param  Zend_Http_Client $httpClient HTTP Client to use for requests
     * @return void
     */
    public function __construct($server, Zend_Http_Client $httpClient = null)
    {
        if ($httpClient === null) {
            $this->_httpClient = new Zend_Http_Client();
        } else {
            $this->_httpClient = $httpClient;
        }

        $this->_introspector  = new Zend_XmlRpc_Client_ServerIntrospection($this);
        $this->_serverAddress = $server;
    }

    /**
     * Sets the HTTP client object to use for connecting the XML-RPC server.
     *
     * @param  Zend_Http_Client $httpClient
     * @return Zend_Http_Client
     */
    public function setHttpClient(Zend_Http_Client $httpClient)
    {
        return $this->_httpClient = $httpClient;
    }

    /**
     * Gets the HTTP client object.
     *
     * @return Zend_Http_Client
     */
    public function getHttpClient()
    {
        return $this->_httpClient;
    }

    /**
     * Sets the object used to introspect remote servers
     *
     * @param  Zend_XmlRpc_Client_ServerIntrospection
     * @return Zend_XmlRpc_Client_ServerIntrospection
     */
    public function setIntrospector(Zend_XmlRpc_Client_ServerIntrospection $introspector)
    {
        return $this->_introspector = $introspector;
    }

    /**
     * Gets the introspection object.
     *
     * @return Zend_XmlRpc_Client_ServerIntrospection
     */
    public function getIntrospector()
    {
        return $this->_introspector;
    }

   /**
     * The request of the last method call
     *
     * @return Zend_XmlRpc_Request
     */
    public function getLastRequest()
    {
        return $this->_lastRequest;
    }

    /**
     * The response received from the last method call
     *
     * @return Zend_XmlRpc_Response
     */
    public function getLastResponse()
    {
        return $this->_lastResponse;
    }

    /**
     * Returns a proxy object for more convenient method calls
     *
     * @param string $namespace  Namespace to proxy or empty string for none
     * @return Zend_XmlRpc_Client_ServerProxy
     */
    public function getProxy($namespace = '')
    {
        if (empty($this->_proxyCache[$namespace])) {
            $proxy = new Zend_XmlRpc_Client_ServerProxy($this, $namespace);
            $this->_proxyCache[$namespace] = $proxy;
        }
        return $this->_proxyCache[$namespace];
    }

    /**
     * Set skip system lookup flag
     *
     * @param  bool $flag
     * @return Zend_XmlRpc_Client
     */
    public function setSkipSystemLookup($flag = true)
    {
        $this->_skipSystemLookup = (bool) $flag;
        return $this;
    }

    /**
     * Skip system lookup when determining if parameter should be array or struct?
     *
     * @return bool
     */
    public function skipSystemLookup()
    {
        return $this->_skipSystemLookup;
    }

    /**
     * Perform an XML-RPC request and return a response.
     *
     * @param Zend_XmlRpc_Request $request
     * @param null|Zend_XmlRpc_Response $response
     * @return void
     * @throws Zend_XmlRpc_Client_HttpException
     */
    public function doRequest($request, $response = null)
    {
        $this->_lastRequest = $request;

        iconv_set_encoding('input_encoding', 'UTF-8');
        iconv_set_encoding('output_encoding', 'UTF-8');
        iconv_set_encoding('internal_encoding', 'UTF-8');

        $http = $this->getHttpClient();
        if($http->getUri() === null) {
            $http->setUri($this->_serverAddress);
        }

        $http->setHeaders(array(
            'Content-Type: text/xml; charset=utf-8',
            'Accept: text/xml',
        ));

        if ($http->getHeader('user-agent') === null) {
            $http->setHeaders(array('User-Agent: Zend_XmlRpc_Client'));
        }

        $xml = $this->_lastRequest->__toString();
        $http->setRawData($xml);
        $httpResponse = $http->request(Zend_Http_Client::POST);

        if (! $httpResponse->isSuccessful()) {
            /**
             * Exception thrown when an HTTP error occurs
             * @see Zend_XmlRpc_Client_HttpException
             */
            require_once 'Zend/XmlRpc/Client/HttpException.php';
            throw new Zend_XmlRpc_Client_HttpException(
                                    $httpResponse->getMessage(),
                                    $httpResponse->getStatus());
        }

        if ($response === null) {
            $response = new Zend_XmlRpc_Response();
        }
        $this->_lastResponse = $response;
        $this->_lastResponse->loadXml(trim($httpResponse->getBody()));
    }

    /**
     * Send an XML-RPC request to the service (for a specific method)
     *
     * @param  string $method Name of the method we want to call
     * @param  array $params Array of parameters for the method
     * @return mixed
     * @throws Zend_XmlRpc_Client_FaultException
     */
    public function call($method, $params=array())
    {
        if (!$this->skipSystemLookup() && ('system.' != substr($method, 0, 7))) {
            // Ensure empty array/struct params are cast correctly
            // If system.* methods are not available, bypass. (ZF-2978)
            $success = true;
            try {
                $signatures = $this->getIntrospector()->getMethodSignature($method);
            } catch (Zend_XmlRpc_Exception $e) {
                $success = false;
            }
            if ($success) {
                $validTypes = array(
                    Zend_XmlRpc_Value::XMLRPC_TYPE_ARRAY,
                    Zend_XmlRpc_Value::XMLRPC_TYPE_BASE64,
                    Zend_XmlRpc_Value::XMLRPC_TYPE_BOOLEAN,
                    Zend_XmlRpc_Value::XMLRPC_TYPE_DATETIME,
                    Zend_XmlRpc_Value::XMLRPC_TYPE_DOUBLE,
                    Zend_XmlRpc_Value::XMLRPC_TYPE_I4,
                    Zend_XmlRpc_Value::XMLRPC_TYPE_INTEGER,
                    Zend_XmlRpc_Value::XMLRPC_TYPE_NIL,
                    Zend_XmlRpc_Value::XMLRPC_TYPE_STRING,
                    Zend_XmlRpc_Value::XMLRPC_TYPE_STRUCT,
                );

                if (!is_array($params)) {
                    $params = array($params);
                }

                foreach ($params as $key => $param)
                {
                    if ($param instanceof Zend_XmlRpc_Value) {
                        continue;
                    }

                    if (count($signatures) > 1) {
                        $type = Zend_XmlRpc_Value::getXmlRpcTypeByValue($param);
                        foreach ($signatures as $signature) {
                            if (!is_array($signature)) {
                                continue;
                            }
                            if (isset($signature['parameters'][$key])) {
                                if ($signature['parameters'][$key] == $type) {
                                    break;
                                }
                            }
                        }
                    } elseif (isset($signatures[0]['parameters'][$key])) {
                        $type = $signatures[0]['parameters'][$key];
                    } else {
                        $type = null;
                    }

                    if (empty($type) || !in_array($type, $validTypes)) {
                        $type = Zend_XmlRpc_Value::AUTO_DETECT_TYPE;
                    }

                    $params[$key] = Zend_XmlRpc_Value::getXmlRpcValue($param, $type);
                }
            }
        }

        $request = $this->_createRequest($method, $params);

        $this->doRequest($request);

        if ($this->_lastResponse->isFault()) {
            $fault = $this->_lastResponse->getFault();
            /**
             * Exception thrown when an XML-RPC fault is returned
             * @see Zend_XmlRpc_Client_FaultException
             */
            require_once 'Zend/XmlRpc/Client/FaultException.php';
            throw new Zend_XmlRpc_Client_FaultException($fault->getMessage(),
                                                        $fault->getCode());
        }

        return $this->_lastResponse->getReturnValue();
    }

    /**
     * Create request object
     *
     * @return Zend_XmlRpc_Request
     */
    protected function _createRequest($method, $params)
    {
        return new Zend_XmlRpc_Request($method, $params);
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @package    Zend_XmlRpc
 * @subpackage Server
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Fault.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * Zend_XmlRpc_Value
 */
require_once 'Zend/XmlRpc/Value.php';

/**
 * XMLRPC Faults
 *
 * Container for XMLRPC faults, containing both a code and a message;
 * additionally, has methods for determining if an XML response is an XMLRPC
 * fault, as well as generating the XML for an XMLRPC fault response.
 *
 * To allow method chaining, you may only use the {@link getInstance()} factory
 * to instantiate a Zend_XmlRpc_Server_Fault.
 *
 * @category   Zend
 * @package    Zend_XmlRpc
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_XmlRpc_Fault
{
    /**
     * Fault code
     * @var int
     */
    protected $_code;

    /**
     * Fault character encoding
     * @var string
     */
    protected $_encoding = 'UTF-8';

    /**
     * Fault message
     * @var string
     */
    protected $_message;

    /**
     * Internal fault codes => messages
     * @var array
     */
    protected $_internal = array(
        404 => 'Unknown Error',

        // 610 - 619 reflection errors
        610 => 'Invalid method class',
        611 => 'Unable to attach function or callback; not callable',
        612 => 'Unable to load array; not an array',
        613 => 'One or more method records are corrupt or otherwise unusable',

        // 620 - 629 dispatch errors
        620 => 'Method does not exist',
        621 => 'Error instantiating class to invoke method',
        622 => 'Method missing implementation',
        623 => 'Calling parameters do not match signature',

        // 630 - 639 request errors
        630 => 'Unable to read request',
        631 => 'Failed to parse request',
        632 => 'Invalid request, no method passed; request must contain a \'methodName\' tag',
        633 => 'Param must contain a value',
        634 => 'Invalid method name',
        635 => 'Invalid XML provided to request',
        636 => 'Error creating xmlrpc value',

        // 640 - 649 system.* errors
        640 => 'Method does not exist',

        // 650 - 659 response errors
        650 => 'Invalid XML provided for response',
        651 => 'Failed to parse response',
        652 => 'Invalid response',
        653 => 'Invalid XMLRPC value in response',
    );

    /**
     * Constructor
     *
     * @return Zend_XmlRpc_Fault
     */
    public function __construct($code = 404, $message = '')
    {
        $this->setCode($code);
        $code = $this->getCode();

        if (empty($message) && isset($this->_internal[$code])) {
            $message = $this->_internal[$code];
        } elseif (empty($message)) {
            $message = 'Unknown error';
        }
        $this->setMessage($message);
    }

    /**
     * Set the fault code
     *
     * @param int $code
     * @return Zend_XmlRpc_Fault
     */
    public function setCode($code)
    {
        $this->_code = (int) $code;
        return $this;
    }

    /**
     * Return fault code
     *
     * @return int
     */
    public function getCode()
    {
        return $this->_code;
    }

    /**
     * Retrieve fault message
     *
     * @param string
     * @return Zend_XmlRpc_Fault
     */
    public function setMessage($message)
    {
        $this->_message = (string) $message;
        return $this;
    }

    /**
     * Retrieve fault message
     *
     * @return string
     */
    public function getMessage()
    {
        return $this->_message;
    }

    /**
     * Set encoding to use in fault response
     *
     * @param string $encoding
     * @return Zend_XmlRpc_Fault
     */
    public function setEncoding($encoding)
    {
        $this->_encoding = $encoding;
        Zend_XmlRpc_Value::setEncoding($encoding);
        return $this;
    }

    /**
     * Retrieve current fault encoding
     *
     * @return string
     */
    public function getEncoding()
    {
        return $this->_encoding;
    }

    /**
     * Load an XMLRPC fault from XML
     *
     * @param string $fault
     * @return boolean Returns true if successfully loaded fault response, false
     * if response was not a fault response
     * @throws Zend_XmlRpc_Exception if no or faulty XML provided, or if fault
     * response does not contain either code or message
     */
    public function loadXml($fault)
    {
        if (!is_string($fault)) {
            require_once 'Zend/XmlRpc/Exception.php';
            throw new Zend_XmlRpc_Exception('Invalid XML provided to fault');
        }

        try {
            $xml = @new SimpleXMLElement($fault);
        } catch (Exception $e) {
            // Not valid XML
            require_once 'Zend/XmlRpc/Exception.php';
            throw new Zend_XmlRpc_Exception('Failed to parse XML fault: ' .  $e->getMessage(), 500, $e);
        }

        // Check for fault
        if (!$xml->fault) {
            // Not a fault
            return false;
        }

        if (!$xml->fault->value->struct) {
            // not a proper fault
            require_once 'Zend/XmlRpc/Exception.php';
            throw new Zend_XmlRpc_Exception('Invalid fault structure', 500);
        }

        $structXml = $xml->fault->value->asXML();
        $struct    = Zend_XmlRpc_Value::getXmlRpcValue($structXml, Zend_XmlRpc_Value::XML_STRING);
        $struct    = $struct->getValue();

        if (isset($struct['faultCode'])) {
            $code = $struct['faultCode'];
        }
        if (isset($struct['faultString'])) {
            $message = $struct['faultString'];
        }

        if (empty($code) && empty($message)) {
            require_once 'Zend/XmlRpc/Exception.php';
            throw new Zend_XmlRpc_Exception('Fault code and string required');
        }

        if (empty($code)) {
            $code = '404';
        }

        if (empty($message)) {
            if (isset($this->_internal[$code])) {
                $message = $this->_internal[$code];
            } else {
                $message = 'Unknown Error';
            }
        }

        $this->setCode($code);
        $this->setMessage($message);

        return true;
    }

    /**
     * Determine if an XML response is an XMLRPC fault
     *
     * @param string $xml
     * @return boolean
     */
    public static function isFault($xml)
    {
        $fault = new self();
        require_once 'Zend/XmlRpc/Exception.php';
        try {
            $isFault = $fault->loadXml($xml);
        } catch (Zend_XmlRpc_Exception $e) {
            $isFault = false;
        }

        return $isFault;
    }

    /**
     * Serialize fault to XML
     *
     * @return string
     */
    public function saveXml()
    {
        // Create fault value
        $faultStruct = array(
            'faultCode'   => $this->getCode(),
            'faultString' => $this->getMessage()
        );
        $value = Zend_XmlRpc_Value::getXmlRpcValue($faultStruct);

        $generator = Zend_XmlRpc_Value::getGenerator();
        $generator->openElement('methodResponse')
                  ->openElement('fault');
        $value->generateXml();
        $generator->closeElement('fault')
                  ->closeElement('methodResponse');

        return $generator->flush();
    }

    /**
     * Return XML fault response
     *
     * @return string
     */
    public function __toString()
    {
        return $this->saveXML();
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_XmlRpc
 * @subpackage Server
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Server.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * Extends Zend_Server_Abstract
 */
require_once 'Zend/Server/Abstract.php';

/**
 * XMLRPC Request
 */
require_once 'Zend/XmlRpc/Request.php';

/**
 * XMLRPC Response
 */
require_once 'Zend/XmlRpc/Response.php';

/**
 * XMLRPC HTTP Response
 */
require_once 'Zend/XmlRpc/Response/Http.php';

/**
 * XMLRPC server fault class
 */
require_once 'Zend/XmlRpc/Server/Fault.php';

/**
 * XMLRPC server system methods class
 */
require_once 'Zend/XmlRpc/Server/System.php';

/**
 * Convert PHP to and from xmlrpc native types
 */
require_once 'Zend/XmlRpc/Value.php';

/**
 * Reflection API for function/method introspection
 */
require_once 'Zend/Server/Reflection.php';

/**
 * Zend_Server_Reflection_Function_Abstract
 */
require_once 'Zend/Server/Reflection/Function/Abstract.php';

/**
 * Specifically grab the Zend_Server_Reflection_Method for manually setting up
 * system.* methods and handling callbacks in {@link loadFunctions()}.
 */
require_once 'Zend/Server/Reflection/Method.php';

/**
 * An XML-RPC server implementation
 *
 * Example:
 * <code>
 * require_once 'Zend/XmlRpc/Server.php';
 * require_once 'Zend/XmlRpc/Server/Cache.php';
 * require_once 'Zend/XmlRpc/Server/Fault.php';
 * require_once 'My/Exception.php';
 * require_once 'My/Fault/Observer.php';
 *
 * // Instantiate server
 * $server = new Zend_XmlRpc_Server();
 *
 * // Allow some exceptions to report as fault responses:
 * Zend_XmlRpc_Server_Fault::attachFaultException('My_Exception');
 * Zend_XmlRpc_Server_Fault::attachObserver('My_Fault_Observer');
 *
 * // Get or build dispatch table:
 * if (!Zend_XmlRpc_Server_Cache::get($filename, $server)) {
 *     require_once 'Some/Service/Class.php';
 *     require_once 'Another/Service/Class.php';
 *
 *     // Attach Some_Service_Class in 'some' namespace
 *     $server->setClass('Some_Service_Class', 'some');
 *
 *     // Attach Another_Service_Class in 'another' namespace
 *     $server->setClass('Another_Service_Class', 'another');
 *
 *     // Create dispatch table cache file
 *     Zend_XmlRpc_Server_Cache::save($filename, $server);
 * }
 *
 * $response = $server->handle();
 * echo $response;
 * </code>
 *
 * @category   Zend
 * @package    Zend_XmlRpc
 * @subpackage Server
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_XmlRpc_Server extends Zend_Server_Abstract
{
    /**
     * Character encoding
     * @var string
     */
    protected $_encoding = 'UTF-8';

    /**
     * Request processed
     * @var null|Zend_XmlRpc_Request
     */
    protected $_request = null;

    /**
     * Class to use for responses; defaults to {@link Zend_XmlRpc_Response_Http}
     * @var string
     */
    protected $_responseClass = 'Zend_XmlRpc_Response_Http';

    /**
     * Dispatch table of name => method pairs
     * @var Zend_Server_Definition
     */
    protected $_table;

    /**
     * PHP types => XML-RPC types
     * @var array
     */
    protected $_typeMap = array(
        'i4'                         => 'i4',
        'int'                        => 'int',
        'integer'                    => 'int',
        'Zend_Crypt_Math_BigInteger' => 'i8',
        'i8'                         => 'i8',
        'ex:i8'                      => 'i8',
        'double'                     => 'double',
        'float'                      => 'double',
        'real'                       => 'double',
        'boolean'                    => 'boolean',
        'bool'                       => 'boolean',
        'true'                       => 'boolean',
        'false'                      => 'boolean',
        'string'                     => 'string',
        'str'                        => 'string',
        'base64'                     => 'base64',
        'dateTime.iso8601'           => 'dateTime.iso8601',
        'date'                       => 'dateTime.iso8601',
        'time'                       => 'dateTime.iso8601',
        'time'                       => 'dateTime.iso8601',
        'Zend_Date'                  => 'dateTime.iso8601',
        'DateTime'                   => 'dateTime.iso8601',
        'array'                      => 'array',
        'struct'                     => 'struct',
        'null'                       => 'nil',
        'nil'                        => 'nil',
        'ex:nil'                     => 'nil',
        'void'                       => 'void',
        'mixed'                      => 'struct',
    );

    /**
     * Send arguments to all methods or just constructor?
     *
     * @var bool
     */
    protected $_sendArgumentsToAllMethods = true;

    /**
     * Constructor
     *
     * Creates system.* methods.
     *
     * @return void
     */
    public function __construct()
    {
        $this->_table = new Zend_Server_Definition();
        $this->_registerSystemMethods();
    }

    /**
     * Proxy calls to system object
     *
     * @param  string $method
     * @param  array $params
     * @return mixed
     * @throws Zend_XmlRpc_Server_Exception
     */
    public function __call($method, $params)
    {
        $system = $this->getSystem();
        if (!method_exists($system, $method)) {
            require_once 'Zend/XmlRpc/Server/Exception.php';
            throw new Zend_XmlRpc_Server_Exception('Unknown instance method called on server: ' . $method);
        }
        return call_user_func_array(array($system, $method), $params);
    }

    /**
     * Attach a callback as an XMLRPC method
     *
     * Attaches a callback as an XMLRPC method, prefixing the XMLRPC method name
     * with $namespace, if provided. Reflection is done on the callback's
     * docblock to create the methodHelp for the XMLRPC method.
     *
     * Additional arguments to pass to the function at dispatch may be passed;
     * any arguments following the namespace will be aggregated and passed at
     * dispatch time.
     *
     * @param string|array $function Valid callback
     * @param string $namespace Optional namespace prefix
     * @return void
     * @throws Zend_XmlRpc_Server_Exception
     */
    public function addFunction($function, $namespace = '')
    {
        if (!is_string($function) && !is_array($function)) {
            require_once 'Zend/XmlRpc/Server/Exception.php';
            throw new Zend_XmlRpc_Server_Exception('Unable to attach function; invalid', 611);
        }

        $argv = null;
        if (2 < func_num_args()) {
            $argv = func_get_args();
            $argv = array_slice($argv, 2);
        }

        $function = (array) $function;
        foreach ($function as $func) {
            if (!is_string($func) || !function_exists($func)) {
                require_once 'Zend/XmlRpc/Server/Exception.php';
                throw new Zend_XmlRpc_Server_Exception('Unable to attach function; invalid', 611);
            }
            $reflection = Zend_Server_Reflection::reflectFunction($func, $argv, $namespace);
            $this->_buildSignature($reflection);
        }
    }

    /**
     * Attach class methods as XMLRPC method handlers
     *
     * $class may be either a class name or an object. Reflection is done on the
     * class or object to determine the available public methods, and each is
     * attached to the server as an available method; if a $namespace has been
     * provided, that namespace is used to prefix the XMLRPC method names.
     *
     * Any additional arguments beyond $namespace will be passed to a method at
     * invocation.
     *
     * @param string|object $class
     * @param string $namespace Optional
     * @param mixed $argv Optional arguments to pass to methods
     * @return void
     * @throws Zend_XmlRpc_Server_Exception on invalid input
     */
    public function setClass($class, $namespace = '', $argv = null)
    {
        if (is_string($class) && !class_exists($class)) {
            require_once 'Zend/XmlRpc/Server/Exception.php';
            throw new Zend_XmlRpc_Server_Exception('Invalid method class', 610);
        }

        $argv = null;
        if (2 < func_num_args()) {
            $argv = func_get_args();
            $argv = array_slice($argv, 2);
        }

        $dispatchable = Zend_Server_Reflection::reflectClass($class, $argv, $namespace);
        foreach ($dispatchable->getMethods() as $reflection) {
            $this->_buildSignature($reflection, $class);
        }
    }

    /**
     * Raise an xmlrpc server fault
     *
     * @param string|Exception $fault
     * @param int $code
     * @return Zend_XmlRpc_Server_Fault
     */
    public function fault($fault = null, $code = 404)
    {
        if (!$fault instanceof Exception) {
            $fault = (string) $fault;
            if (empty($fault)) {
                $fault = 'Unknown Error';
            }
            require_once 'Zend/XmlRpc/Server/Exception.php';
            $fault = new Zend_XmlRpc_Server_Exception($fault, $code);
        }

        return Zend_XmlRpc_Server_Fault::getInstance($fault);
    }

    /**
     * Handle an xmlrpc call
     *
     * @param Zend_XmlRpc_Request $request Optional
     * @return Zend_XmlRpc_Response|Zend_XmlRpc_Fault
     */
    public function handle($request = false)
    {
        // Get request
        if ((!$request || !$request instanceof Zend_XmlRpc_Request)
            && (null === ($request = $this->getRequest()))
        ) {
            require_once 'Zend/XmlRpc/Request/Http.php';
            $request = new Zend_XmlRpc_Request_Http();
            $request->setEncoding($this->getEncoding());
        }

        $this->setRequest($request);

        if ($request->isFault()) {
            $response = $request->getFault();
        } else {
            try {
                $response = $this->_handle($request);
            } catch (Exception $e) {
                $response = $this->fault($e);
            }
        }

        // Set output encoding
        $response->setEncoding($this->getEncoding());

        return $response;
    }

    /**
     * Load methods as returned from {@link getFunctions}
     *
     * Typically, you will not use this method; it will be called using the
     * results pulled from {@link Zend_XmlRpc_Server_Cache::get()}.
     *
     * @param  array|Zend_Server_Definition $definition
     * @return void
     * @throws Zend_XmlRpc_Server_Exception on invalid input
     */
    public function loadFunctions($definition)
    {
        if (!is_array($definition) && (!$definition instanceof Zend_Server_Definition)) {
            if (is_object($definition)) {
                $type = get_class($definition);
            } else {
                $type = gettype($definition);
            }
            require_once 'Zend/XmlRpc/Server/Exception.php';
            throw new Zend_XmlRpc_Server_Exception('Unable to load server definition; must be an array or Zend_Server_Definition, received ' . $type, 612);
        }

        $this->_table->clearMethods();
        $this->_registerSystemMethods();

        if ($definition instanceof Zend_Server_Definition) {
            $definition = $definition->getMethods();
        }

        foreach ($definition as $key => $method) {
            if ('system.' == substr($key, 0, 7)) {
                continue;
            }
            $this->_table->addMethod($method, $key);
        }
    }

    /**
     * Set encoding
     *
     * @param string $encoding
     * @return Zend_XmlRpc_Server
     */
    public function setEncoding($encoding)
    {
        $this->_encoding = $encoding;
        Zend_XmlRpc_Value::setEncoding($encoding);
        return $this;
    }

    /**
     * Retrieve current encoding
     *
     * @return string
     */
    public function getEncoding()
    {
        return $this->_encoding;
    }

    /**
     * Do nothing; persistence is handled via {@link Zend_XmlRpc_Server_Cache}
     *
     * @param  mixed $mode
     * @return void
     */
    public function setPersistence($mode)
    {
    }

    /**
     * Set the request object
     *
     * @param string|Zend_XmlRpc_Request $request
     * @return Zend_XmlRpc_Server
     * @throws Zend_XmlRpc_Server_Exception on invalid request class or object
     */
    public function setRequest($request)
    {
        if (is_string($request) && class_exists($request)) {
            $request = new $request();
            if (!$request instanceof Zend_XmlRpc_Request) {
                require_once 'Zend/XmlRpc/Server/Exception.php';
                throw new Zend_XmlRpc_Server_Exception('Invalid request class');
            }
            $request->setEncoding($this->getEncoding());
        } elseif (!$request instanceof Zend_XmlRpc_Request) {
            require_once 'Zend/XmlRpc/Server/Exception.php';
            throw new Zend_XmlRpc_Server_Exception('Invalid request object');
        }

        $this->_request = $request;
        return $this;
    }

    /**
     * Return currently registered request object
     *
     * @return null|Zend_XmlRpc_Request
     */
    public function getRequest()
    {
        return $this->_request;
    }

    /**
     * Set the class to use for the response
     *
     * @param string $class
     * @return boolean True if class was set, false if not
     */
    public function setResponseClass($class)
    {
        if (!class_exists($class) or
            ($c = new ReflectionClass($class) and !$c->isSubclassOf('Zend_XmlRpc_Response'))) {

            require_once 'Zend/XmlRpc/Server/Exception.php';
            throw new Zend_XmlRpc_Server_Exception('Invalid response class');
        }
        $this->_responseClass = $class;
        return true;
    }

    /**
     * Retrieve current response class
     *
     * @return string
     */
    public function getResponseClass()
    {
        return $this->_responseClass;
    }

    /**
     * Retrieve dispatch table
     *
     * @return array
     */
    public function getDispatchTable()
    {
        return $this->_table;
    }

    /**
     * Returns a list of registered methods
     *
     * Returns an array of dispatchables (Zend_Server_Reflection_Function,
     * _Method, and _Class items).
     *
     * @return array
     */
    public function getFunctions()
    {
        return $this->_table->toArray();
    }

    /**
     * Retrieve system object
     *
     * @return Zend_XmlRpc_Server_System
     */
    public function getSystem()
    {
        return $this->_system;
    }

    /**
     * Send arguments to all methods?
     *
     * If setClass() is used to add classes to the server, this flag defined
     * how to handle arguments. If set to true, all methods including constructor
     * will receive the arguments. If set to false, only constructor will receive the
     * arguments
     */
    public function sendArgumentsToAllMethods($flag = null)
    {
        if ($flag === null) {
            return $this->_sendArgumentsToAllMethods;
        }

        $this->_sendArgumentsToAllMethods = (bool)$flag;
        return $this;
    }

    /**
     * Map PHP type to XML-RPC type
     *
     * @param  string $type
     * @return string
     */
    protected function _fixType($type)
    {
        if (isset($this->_typeMap[$type])) {
            return $this->_typeMap[$type];
        }
        return 'void';
    }

    /**
     * Handle an xmlrpc call (actual work)
     *
     * @param Zend_XmlRpc_Request $request
     * @return Zend_XmlRpc_Response
     * @throws Zend_XmlRpcServer_Exception|Exception
     * Zend_XmlRpcServer_Exceptions are thrown for internal errors; otherwise,
     * any other exception may be thrown by the callback
     */
    protected function _handle(Zend_XmlRpc_Request $request)
    {
        $method = $request->getMethod();

        // Check for valid method
        if (!$this->_table->hasMethod($method)) {
            require_once 'Zend/XmlRpc/Server/Exception.php';
            throw new Zend_XmlRpc_Server_Exception('Method "' . $method . '" does not exist', 620);
        }

        $info     = $this->_table->getMethod($method);
        $params   = $request->getParams();
        $argv     = $info->getInvokeArguments();
        if (0 < count($argv) and $this->sendArgumentsToAllMethods()) {
            $params = array_merge($params, $argv);
        }

        // Check calling parameters against signatures
        $matched    = false;
        $sigCalled  = $request->getTypes();

        $sigLength  = count($sigCalled);
        $paramsLen  = count($params);
        if ($sigLength < $paramsLen) {
            for ($i = $sigLength; $i < $paramsLen; ++$i) {
                $xmlRpcValue = Zend_XmlRpc_Value::getXmlRpcValue($params[$i]);
                $sigCalled[] = $xmlRpcValue->getType();
            }
        }

        $signatures = $info->getPrototypes();
        foreach ($signatures as $signature) {
            $sigParams = $signature->getParameters();
            if ($sigCalled === $sigParams) {
                $matched = true;
                break;
            }
        }
        if (!$matched) {
            require_once 'Zend/XmlRpc/Server/Exception.php';
            throw new Zend_XmlRpc_Server_Exception('Calling parameters do not match signature', 623);
        }

        $return        = $this->_dispatch($info, $params);
        $responseClass = $this->getResponseClass();
        return new $responseClass($return);
    }

    /**
     * Register system methods with the server
     *
     * @return void
     */
    protected function _registerSystemMethods()
    {
        $system = new Zend_XmlRpc_Server_System($this);
        $this->_system = $system;
        $this->setClass($system, 'system');
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_XmlRpc
 * @subpackage Value
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Value.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * Represent a native XML-RPC value entity, used as parameters for the methods
 * called by the Zend_XmlRpc_Client object and as the return value for those calls.
 *
 * This object as a very important static function Zend_XmlRpc_Value::getXmlRpcValue, this
 * function acts likes a factory for the Zend_XmlRpc_Value objects
 *
 * Using this function, users/Zend_XmlRpc_Client object can create the Zend_XmlRpc_Value objects
 * from PHP variables, XML string or by specifing the exact XML-RPC natvie type
 *
 * @package    Zend_XmlRpc
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
abstract class Zend_XmlRpc_Value
{
    /**
     * The native XML-RPC representation of this object's value
     *
     * If the native type of this object is array or struct, this will be an array
     * of Zend_XmlRpc_Value objects
     */
    protected $_value;

    /**
     * The native XML-RPC type of this object
     * One of the XMLRPC_TYPE_* constants
     */
    protected $_type;

    /**
     * XML code representation of this object (will be calculated only once)
     */
    protected $_xml;

    /**
     * @var Zend_XmlRpc_Generator_GeneratorAbstract
     */
    protected static $_generator;

    /**
     * Specify that the XML-RPC native type will be auto detected from a PHP variable type
     */
    const AUTO_DETECT_TYPE = 'auto_detect';

    /**
     * Specify that the XML-RPC value will be parsed out from a given XML code
     */
    const XML_STRING = 'xml';

    /**
     * All the XML-RPC native types
     */
    const XMLRPC_TYPE_I4        = 'i4';
    const XMLRPC_TYPE_INTEGER   = 'int';
    const XMLRPC_TYPE_I8        = 'i8';
    const XMLRPC_TYPE_APACHEI8  = 'ex:i8';
    const XMLRPC_TYPE_DOUBLE    = 'double';
    const XMLRPC_TYPE_BOOLEAN   = 'boolean';
    const XMLRPC_TYPE_STRING    = 'string';
    const XMLRPC_TYPE_DATETIME  = 'dateTime.iso8601';
    const XMLRPC_TYPE_BASE64    = 'base64';
    const XMLRPC_TYPE_ARRAY     = 'array';
    const XMLRPC_TYPE_STRUCT    = 'struct';
    const XMLRPC_TYPE_NIL       = 'nil';
    const XMLRPC_TYPE_APACHENIL = 'ex:nil';

    /**
     * Get the native XML-RPC type (the type is one of the Zend_XmlRpc_Value::XMLRPC_TYPE_* constants)
     *
     * @return string
     */
    public function getType()
    {
        return $this->_type;
    }

    /**
     * Get XML generator instance
     *
     * @return Zend_XmlRpc_Generator_GeneratorAbstract
     */
    public static function getGenerator()
    {
        if (!self::$_generator) {
            if (extension_loaded('xmlwriter')) {
                require_once 'Zend/XmlRpc/Generator/XmlWriter.php';
                self::$_generator = new Zend_XmlRpc_Generator_XmlWriter();
            } else {
                require_once 'Zend/XmlRpc/Generator/DomDocument.php';
                self::$_generator = new Zend_XmlRpc_Generator_DomDocument();
            }
        }

        return self::$_generator;
    }

    /**
     * Sets XML generator instance
     *
     * @param Zend_XmlRpc_Generator_GeneratorAbstract $generator
     * @return void
     */
    public static function setGenerator(Zend_XmlRpc_Generator_GeneratorAbstract $generator)
    {
        self::$_generator = $generator;
    }

    /**
     * Changes the encoding of the generator
     *
     * @param string $encoding
     * @return void
     */
    public static function setEncoding($encoding)
    {
        $generator = self::getGenerator();
        $newGenerator = new $generator($encoding);
        self::setGenerator($newGenerator);
    }

    /**
     * Return the value of this object, convert the XML-RPC native value into a PHP variable
     *
     * @return mixed
     */
    abstract public function getValue();

    /**
     * Return the XML code that represent a native MXL-RPC value
     *
     * @return string
     */
    public function saveXml()
    {
        if (!$this->_xml) {
            $this->generateXml();
            $this->_xml = (string) $this->getGenerator();
        }
        return $this->_xml;
    }

    /**
     * Generate XML code that represent a native XML/RPC value
     *
     * @return void
     */
    public function generateXml()
    {
        $this->_generateXml();
    }

    /**
     * Creates a Zend_XmlRpc_Value* object, representing a native XML-RPC value
     * A XmlRpcValue object can be created in 3 ways:
     * 1. Autodetecting the native type out of a PHP variable
     *    (if $type is not set or equal to Zend_XmlRpc_Value::AUTO_DETECT_TYPE)
     * 2. By specifing the native type ($type is one of the Zend_XmlRpc_Value::XMLRPC_TYPE_* constants)
     * 3. From a XML string ($type is set to Zend_XmlRpc_Value::XML_STRING)
     *
     * By default the value type is autodetected according to it's PHP type
     *
     * @param mixed $value
     * @param Zend_XmlRpc_Value::constant $type
     *
     * @return Zend_XmlRpc_Value
     * @static
     */
    public static function getXmlRpcValue($value, $type = self::AUTO_DETECT_TYPE)
    {
        switch ($type) {
            case self::AUTO_DETECT_TYPE:
                // Auto detect the XML-RPC native type from the PHP type of $value
                return self::_phpVarToNativeXmlRpc($value);

            case self::XML_STRING:
                // Parse the XML string given in $value and get the XML-RPC value in it
                return self::_xmlStringToNativeXmlRpc($value);

            case self::XMLRPC_TYPE_I4:
                // fall through to the next case
            case self::XMLRPC_TYPE_INTEGER:
                require_once 'Zend/XmlRpc/Value/Integer.php';
                return new Zend_XmlRpc_Value_Integer($value);

            case self::XMLRPC_TYPE_I8:
                // fall through to the next case
            case self::XMLRPC_TYPE_APACHEI8:
                require_once 'Zend/XmlRpc/Value/BigInteger.php';
                return new Zend_XmlRpc_Value_BigInteger($value);

            case self::XMLRPC_TYPE_DOUBLE:
                require_once 'Zend/XmlRpc/Value/Double.php';
                return new Zend_XmlRpc_Value_Double($value);

            case self::XMLRPC_TYPE_BOOLEAN:
                require_once 'Zend/XmlRpc/Value/Boolean.php';
                return new Zend_XmlRpc_Value_Boolean($value);

            case self::XMLRPC_TYPE_STRING:
                require_once 'Zend/XmlRpc/Value/String.php';
                return new Zend_XmlRpc_Value_String($value);

            case self::XMLRPC_TYPE_BASE64:
                require_once 'Zend/XmlRpc/Value/Base64.php';
                return new Zend_XmlRpc_Value_Base64($value);

            case self::XMLRPC_TYPE_NIL:
                // fall through to the next case
            case self::XMLRPC_TYPE_APACHENIL:
                require_once 'Zend/XmlRpc/Value/Nil.php';
                return new Zend_XmlRpc_Value_Nil();

            case self::XMLRPC_TYPE_DATETIME:
                require_once 'Zend/XmlRpc/Value/DateTime.php';
                return new Zend_XmlRpc_Value_DateTime($value);

            case self::XMLRPC_TYPE_ARRAY:
                require_once 'Zend/XmlRpc/Value/Array.php';
                return new Zend_XmlRpc_Value_Array($value);

            case self::XMLRPC_TYPE_STRUCT:
                require_once 'Zend/XmlRpc/Value/Struct.php';
                return new Zend_XmlRpc_Value_Struct($value);

            default:
                require_once 'Zend/XmlRpc/Value/Exception.php';
                throw new Zend_XmlRpc_Value_Exception('Given type is not a '. __CLASS__ .' constant');
        }
    }

    /**
     * Get XML-RPC type for a PHP native variable
     *
     * @static
     * @param mixed $value
     * @return string
     */
    public static function getXmlRpcTypeByValue($value)
    {
        if (is_object($value)) {
            if ($value instanceof Zend_XmlRpc_Value) {
                return $value->getType();
            } elseif (($value instanceof Zend_Date) || ($value instanceof DateTime)) {
                return self::XMLRPC_TYPE_DATETIME;
            }
            return self::getXmlRpcTypeByValue(get_object_vars($value));
        } elseif (is_array($value)) {
            if (!empty($value) && is_array($value) && (array_keys($value) !== range(0, count($value) - 1))) {
                return self::XMLRPC_TYPE_STRUCT;
            }
            return self::XMLRPC_TYPE_ARRAY;
        } elseif (is_int($value)) {
            return ($value > PHP_INT_MAX) ? self::XMLRPC_TYPE_I8 : self::XMLRPC_TYPE_INTEGER;
        } elseif (is_double($value)) {
            return self::XMLRPC_TYPE_DOUBLE;
        } elseif (is_bool($value)) {
            return self::XMLRPC_TYPE_BOOLEAN;
        } elseif (is_null($value)) {
            return self::XMLRPC_TYPE_NIL;
        } elseif (is_string($value)) {
            return self::XMLRPC_TYPE_STRING;
        }
        throw new Zend_XmlRpc_Value_Exception(sprintf(
            'No matching XMLRPC type found for php type %s.',
            gettype($value)
        ));
    }

    /**
     * Transform a PHP native variable into a XML-RPC native value
     *
     * @param mixed $value The PHP variable for convertion
     *
     * @return Zend_XmlRpc_Value
     * @static
     */
    protected static function _phpVarToNativeXmlRpc($value)
    {
        // @see http://framework.zend.com/issues/browse/ZF-8623
        if (is_object($value)) {
            if ($value instanceof Zend_XmlRpc_Value) {
                return $value;
            }
            if ($value instanceof Zend_Crypt_Math_BigInteger) {
                require_once 'Zend/XmlRpc/Value/Exception.php';
                throw new Zend_XmlRpc_Value_Exception(
                    'Using Zend_Crypt_Math_BigInteger to get an ' .
                    'instance of Zend_XmlRpc_Value_BigInteger is not ' .
                    'available anymore.'
                );
            }
        }

        switch (self::getXmlRpcTypeByValue($value))
        {
            case self::XMLRPC_TYPE_DATETIME:
                require_once 'Zend/XmlRpc/Value/DateTime.php';
                return new Zend_XmlRpc_Value_DateTime($value);

            case self::XMLRPC_TYPE_ARRAY:
                require_once 'Zend/XmlRpc/Value/Array.php';
                return new Zend_XmlRpc_Value_Array($value);

            case self::XMLRPC_TYPE_STRUCT:
                require_once 'Zend/XmlRpc/Value/Struct.php';
                return new Zend_XmlRpc_Value_Struct($value);

            case self::XMLRPC_TYPE_INTEGER:
                require_once 'Zend/XmlRpc/Value/Integer.php';
                return new Zend_XmlRpc_Value_Integer($value);

            case self::XMLRPC_TYPE_DOUBLE:
                require_once 'Zend/XmlRpc/Value/Double.php';
                return new Zend_XmlRpc_Value_Double($value);

            case self::XMLRPC_TYPE_BOOLEAN:
                require_once 'Zend/XmlRpc/Value/Boolean.php';
                return new Zend_XmlRpc_Value_Boolean($value);

            case self::XMLRPC_TYPE_NIL:
                require_once 'Zend/XmlRpc/Value/Nil.php';
                return new Zend_XmlRpc_Value_Nil;

            case self::XMLRPC_TYPE_STRING:
                // Fall through to the next case
            default:
                // If type isn't identified (or identified as string), it treated as string
                require_once 'Zend/XmlRpc/Value/String.php';
                return new Zend_XmlRpc_Value_String($value);
        }
    }

    /**
     * Transform an XML string into a XML-RPC native value
     *
     * @param string|SimpleXMLElement $xml A SimpleXMLElement object represent the XML string
     *                                            It can be also a valid XML string for convertion
     *
     * @return Zend_XmlRpc_Value
     * @static
     */
    protected static function _xmlStringToNativeXmlRpc($xml)
    {
        self::_createSimpleXMLElement($xml);

        self::_extractTypeAndValue($xml, $type, $value);

        switch ($type) {
            // All valid and known XML-RPC native values
            case self::XMLRPC_TYPE_I4:
                // Fall through to the next case
            case self::XMLRPC_TYPE_INTEGER:
                require_once 'Zend/XmlRpc/Value/Integer.php';
                $xmlrpcValue = new Zend_XmlRpc_Value_Integer($value);
                break;
            case self::XMLRPC_TYPE_APACHEI8:
                // Fall through to the next case
            case self::XMLRPC_TYPE_I8:
                require_once 'Zend/XmlRpc/Value/BigInteger.php';
                $xmlrpcValue = new Zend_XmlRpc_Value_BigInteger($value);
                break;
            case self::XMLRPC_TYPE_DOUBLE:
                require_once 'Zend/XmlRpc/Value/Double.php';
                $xmlrpcValue = new Zend_XmlRpc_Value_Double($value);
                break;
            case self::XMLRPC_TYPE_BOOLEAN:
                require_once 'Zend/XmlRpc/Value/Boolean.php';
                $xmlrpcValue = new Zend_XmlRpc_Value_Boolean($value);
                break;
            case self::XMLRPC_TYPE_STRING:
                require_once 'Zend/XmlRpc/Value/String.php';
                $xmlrpcValue = new Zend_XmlRpc_Value_String($value);
                break;
            case self::XMLRPC_TYPE_DATETIME:  // The value should already be in a iso8601 format
                require_once 'Zend/XmlRpc/Value/DateTime.php';
                $xmlrpcValue = new Zend_XmlRpc_Value_DateTime($value);
                break;
            case self::XMLRPC_TYPE_BASE64:    // The value should already be base64 encoded
                require_once 'Zend/XmlRpc/Value/Base64.php';
                $xmlrpcValue = new Zend_XmlRpc_Value_Base64($value, true);
                break;
            case self::XMLRPC_TYPE_NIL:
                // Fall through to the next case
            case self::XMLRPC_TYPE_APACHENIL:
                // The value should always be NULL
                require_once 'Zend/XmlRpc/Value/Nil.php';
                $xmlrpcValue = new Zend_XmlRpc_Value_Nil();
                break;
            case self::XMLRPC_TYPE_ARRAY:
                // PHP 5.2.4 introduced a regression in how empty($xml->value)
                // returns; need to look for the item specifically
                $data = null;
                foreach ($value->children() as $key => $value) {
                    if ('data' == $key) {
                        $data = $value;
                        break;
                    }
                }

                if (null === $data) {
                    require_once 'Zend/XmlRpc/Value/Exception.php';
                    throw new Zend_XmlRpc_Value_Exception('Invalid XML for XML-RPC native '. self::XMLRPC_TYPE_ARRAY .' type: ARRAY tag must contain DATA tag');
                }
                $values = array();
                // Parse all the elements of the array from the XML string
                // (simple xml element) to Zend_XmlRpc_Value objects
                foreach ($data->value as $element) {
                    $values[] = self::_xmlStringToNativeXmlRpc($element);
                }
                require_once 'Zend/XmlRpc/Value/Array.php';
                $xmlrpcValue = new Zend_XmlRpc_Value_Array($values);
                break;
            case self::XMLRPC_TYPE_STRUCT:
                $values = array();
                // Parse all the memebers of the struct from the XML string
                // (simple xml element) to Zend_XmlRpc_Value objects
                foreach ($value->member as $member) {
                    // @todo? If a member doesn't have a <value> tag, we don't add it to the struct
                    // Maybe we want to throw an exception here ?
                    if (!isset($member->value) or !isset($member->name)) {
                        continue;
                        //throw new Zend_XmlRpc_Value_Exception('Member of the '. self::XMLRPC_TYPE_STRUCT .' XML-RPC native type must contain a VALUE tag');
                    }
                    $values[(string)$member->name] = self::_xmlStringToNativeXmlRpc($member->value);
                }
                require_once 'Zend/XmlRpc/Value/Struct.php';
                $xmlrpcValue = new Zend_XmlRpc_Value_Struct($values);
                break;
            default:
                require_once 'Zend/XmlRpc/Value/Exception.php';
                throw new Zend_XmlRpc_Value_Exception('Value type \''. $type .'\' parsed from the XML string is not a known XML-RPC native type');
                break;
        }
        $xmlrpcValue->_setXML($xml->asXML());

        return $xmlrpcValue;
    }

    protected static function _createSimpleXMLElement(&$xml)
    {
        if ($xml instanceof SimpleXMLElement) {
            return;
        }

        try {
            $xml = new SimpleXMLElement($xml);
        } catch (Exception $e) {
            // The given string is not a valid XML
            require_once 'Zend/XmlRpc/Value/Exception.php';
            throw new Zend_XmlRpc_Value_Exception('Failed to create XML-RPC value from XML string: ' . $e->getMessage(), $e->getCode(), $e);
        }
    }

    /**
     * Extract XML/RPC type and value from SimpleXMLElement object
     *
     * @param SimpleXMLElement $xml
     * @param string &$type Type bind variable
     * @param string &$value Value bind variable
     * @return void
     */
    protected static function _extractTypeAndValue(SimpleXMLElement $xml, &$type, &$value)
    {
        list($type, $value) = each($xml);

        if (!$type and $value === null) {
            $namespaces = array('ex' => 'http://ws.apache.org/xmlrpc/namespaces/extensions');
            foreach ($namespaces as $namespaceName => $namespaceUri) {
                $namespaceXml = $xml->children($namespaceUri);
                list($type, $value) = each($namespaceXml);
                if ($type !== null) {
                    $type = $namespaceName . ':' . $type;
                    break;
                }
            }
        }

        // If no type was specified, the default is string
        if (!$type) {
            $type = self::XMLRPC_TYPE_STRING;
        }
    }

    /**
     * @param string $xml
     * @return void
     */
    protected function _setXML($xml)
    {
        $this->_xml = $this->getGenerator()->stripDeclaration($xml);
    }
}