Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial XML_RPC2 import

git-svn-id: http://svn.php.net/repository/pear/packages/XML_RPC2/trunk@201638 c90b9560-bf6c-de11-be94-00142212c4b1
  • Loading branch information...
commit 048b726f2f65b6baf21e124208e2c5bc5fbe9643 1 parent 27a1655
Sergio Carvalho authored
Showing with 5,942 additions and 0 deletions.
  1. +15 −0 Makefile
  2. +158 −0 XML/RPC2/Backend.php
  3. +90 −0 XML/RPC2/Backend/Php/Client.php
  4. +166 −0 XML/RPC2/Backend/Php/Request.php
  5. +124 −0 XML/RPC2/Backend/Php/Response.php
  6. +112 −0 XML/RPC2/Backend/Php/Server.php
  7. +218 −0 XML/RPC2/Backend/Php/Value.php
  8. +134 −0 XML/RPC2/Backend/Php/Value/Array.php
  9. +89 −0 XML/RPC2/Backend/Php/Value/Base64.php
  10. +83 −0 XML/RPC2/Backend/Php/Value/Boolean.php
  11. +102 −0 XML/RPC2/Backend/Php/Value/Datetime.php
  12. +73 −0 XML/RPC2/Backend/Php/Value/Double.php
  13. +73 −0 XML/RPC2/Backend/Php/Value/Integer.php
  14. +162 −0 XML/RPC2/Backend/Php/Value/Scalar.php
  15. +86 −0 XML/RPC2/Backend/Php/Value/String.php
  16. +129 −0 XML/RPC2/Backend/Php/Value/Struct.php
  17. +92 −0 XML/RPC2/Backend/Xmlrpcext/Client.php
  18. +146 −0 XML/RPC2/Backend/Xmlrpcext/Server.php
  19. +61 −0 XML/RPC2/Backend/Xmlrpcext/Value.php
  20. +212 −0 XML/RPC2/Client.php
  21. +194 −0 XML/RPC2/Exception.php
  22. +169 −0 XML/RPC2/Server.php
  23. +167 −0 XML/RPC2/Server/CallHandler.php
  24. +143 −0 XML/RPC2/Server/CallHandler/Class.php
  25. +141 −0 XML/RPC2/Server/CallHandler/Instance.php
  26. +267 −0 XML/RPC2/Server/Method.php
  27. +273 −0 XML/RPC2/Util/HTTPRequest.php
  28. +58 −0 XML/RPC2/Value.php
  29. +2 −0  docs/Makefile
  30. +320 −0 docs/tutorials/XML_RPC2.lyx
  31. +137 −0 package.xml
  32. +9 −0 tests/Makefile
  33. +17 −0 tests/XML_RPC2/phpBackend/client/faultFromPython.phpt
  34. +13 −0 tests/XML_RPC2/phpBackend/client/okFromPython.phpt
  35. +17 −0 tests/XML_RPC2/phpBackend/client/protocolError.phpt
  36. +17 −0 tests/XML_RPC2/phpBackend/decoding/array.phpt
  37. +10 −0 tests/XML_RPC2/phpBackend/decoding/base64.phpt
  38. +12 −0 tests/XML_RPC2/phpBackend/decoding/boolean.phpt
  39. +10 −0 tests/XML_RPC2/phpBackend/decoding/datetime.phpt
  40. +10 −0 tests/XML_RPC2/phpBackend/decoding/double.phpt
  41. +25 −0 tests/XML_RPC2/phpBackend/decoding/faultResponse.phpt
  42. +10 −0 tests/XML_RPC2/phpBackend/decoding/integer.phpt
  43. +10 −0 tests/XML_RPC2/phpBackend/decoding/integer2.phpt
  44. +26 −0 tests/XML_RPC2/phpBackend/decoding/request.phpt
  45. +10 −0 tests/XML_RPC2/phpBackend/decoding/response.phpt
  46. +10 −0 tests/XML_RPC2/phpBackend/decoding/string.phpt
  47. +17 −0 tests/XML_RPC2/phpBackend/decoding/struct.phpt
  48. +11 −0 tests/XML_RPC2/phpBackend/encoding/array.phpt
  49. +14 −0 tests/XML_RPC2/phpBackend/encoding/base64.phpt
  50. +14 −0 tests/XML_RPC2/phpBackend/encoding/boolean.phpt
  51. +11 −0 tests/XML_RPC2/phpBackend/encoding/datetime.phpt
  52. +11 −0 tests/XML_RPC2/phpBackend/encoding/datetime1.phpt
  53. +11 −0 tests/XML_RPC2/phpBackend/encoding/datetime2.phpt
  54. +11 −0 tests/XML_RPC2/phpBackend/encoding/datetime3.phpt
  55. +11 −0 tests/XML_RPC2/phpBackend/encoding/datetime4.phpt
  56. +14 −0 tests/XML_RPC2/phpBackend/encoding/double.phpt
  57. +11 −0 tests/XML_RPC2/phpBackend/encoding/integer.phpt
  58. +18 −0 tests/XML_RPC2/phpBackend/encoding/request.phpt
  59. +10 −0 tests/XML_RPC2/phpBackend/encoding/response.phpt
  60. +10 −0 tests/XML_RPC2/phpBackend/encoding/response2.phpt
  61. +14 −0 tests/XML_RPC2/phpBackend/encoding/string.phpt
  62. +11 −0 tests/XML_RPC2/phpBackend/encoding/struct.phpt
  63. +42 −0 tests/XML_RPC2/phpBackend/server/invalidXMLRequest.phpt
  64. +42 −0 tests/XML_RPC2/phpBackend/server/nonexistantMethod.phpt
  65. +38 −0 tests/XML_RPC2/phpBackend/server/normalRequest.phpt
  66. +17 −0 tests/XML_RPC2/xmlrpcextBackend/client/faultFromPython.phpt
  67. +13 −0 tests/XML_RPC2/xmlrpcextBackend/client/okFromPython.phpt
  68. +17 −0 tests/XML_RPC2/xmlrpcextBackend/client/protocolError.phpt
  69. +17 −0 tests/XML_RPC2/xmlrpcextBackend/client/valueCreateFromNative.phpt
  70. +50 −0 tests/XML_RPC2/xmlrpcextBackend/server/invalidXMLRequest.phpt
  71. +44 −0 tests/XML_RPC2/xmlrpcextBackend/server/nonexistantMethod.phpt
  72. +38 −0 tests/XML_RPC2/xmlrpcextBackend/server/normalRequest.phpt
  73. +918 −0 tests/lib/run-tests
  74. +77 −0 tests/lib/tests-config
  75. +20 −0 util/filelist.sh
  76. +8 −0 util/indent.xsl
15 Makefile
View
@@ -0,0 +1,15 @@
+run-tests:
+ make -C tests run-tests
+
+
+phpdoc:
+ monotone log > CHANGELOG
+ make -C docs phpdoc
+ cp CHANGELOG XML
+ phpdoc --directory XML,docs/tutorials --examplesdir docs/examples --target docs/phpdoc --title "XML_RPC2 Documentation" --parseprivate --defaultpackagename XML_RPC2 --pear -ric --output HTML:Smarty:PHP
+ rm -f XML/CHANGELOG
+
+clean:
+ make -C tests/XML_RPC2 clean
+ rm -Rf docs/phpdoc
+ rm -f CHANGELOG
158 XML/RPC2/Backend.php
View
@@ -0,0 +1,158 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+/* }}} */
+/**
+ * XML_RPC Backend class. The backend is responsible for the actual execution of
+ * a request, as well as payload encoding and decoding.
+ *
+ * The only external usage of this class is when explicitely setting the backend, as in
+ * <code>
+ * XML_RPC2_Backend::setBackend('php');
+ * // or
+ * XML_RPC2_Backend::setBackend('xmlrpcext');
+ * </code>
+ * Note that if you do not explicitely set the backend, it will be selected automatically.
+ *
+ * Internally, this class provides methods to obtain the relevant backend classes:
+ * - The server class
+ * - The client class
+ * - The value class
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+abstract class XML_RPC2_Backend
+{
+ protected static $currentBackend;
+ /* setBackend {{{ */
+ /**
+ * Backend setter.
+ *
+ * Currently, two backends exist: 'php' and 'XMLRPCext'.
+ * The PHP backend has no external dependencies, while the xmlrpcext
+ * requires the xmlrpc extension.
+ *
+ * The XMLRPCext backend is quite faster, and will be automatically
+ * selected when no explicit backend has been set and the extension
+ * is available.
+ *
+ * @param string The backend to select. Either 'php' or 'XMLRPCext'.
+ */
+ public static function setBackend($backend)
+ {
+ $backend = ucfirst(strtolower($backend));
+ if (
+ $backend != 'Php' &&
+ $backend != 'Xmlrpcext'
+ ) {
+ throw new XML_RPC2_Exception(sprintf('Backend %s does not exist', $backend));
+ }
+
+ if (
+ $backend == 'Xmlrpcext' &&
+ !function_exists('xmlrpc_server_create') &&
+ !( // TODO Use PEAR::loadExtension once PEAR passes PHP5 unit tests (E_STRICT compliance, namely)
+ @dl('php_xmlrpc' . PHP_SHLIB_SUFFIX) || @dl('xmlrpc' . PHP_SHLIB_SUFFIX)
+ )
+ ) {
+ throw new XML_RPC2_Exception('Unable to load xmlrpc extension.');
+ }
+
+ self::$currentBackend = $backend;
+ }
+ /* }}} */
+ /* getBackend {{{ */
+ /**
+ * Backend getter.
+ *
+ * Return the current backend name. If no backend was previously selected
+ * elect one and set it.
+ *
+ * The xmlrpcext backend is preferred, and will be automatically
+ * selected when no explicit backend has been set and the xmlrpc
+ * extension exists. If it does not exist, then the php backend is
+ * selected.
+ *
+ * @return string The current backend
+ */
+ protected static function getBackend()
+ {
+ if (!isset(self::$currentBackend)) {
+ try {
+ self::setBackend('XMLRPCext'); // We prefer this one
+ } catch (XML_RPC2_Exception $e) {
+ // TODO According to PEAR CG logging should occur here
+ self::setBackend('php'); // But will settle with this one in case of error
+ }
+ }
+ return self::$currentBackend;
+ }
+ /* }}} */
+ /* getServerClassname {{{ */
+ /**
+ * Include the relevant php files for the server class, and return the backend server
+ * class name.
+ *
+ * @return string The Server class name
+ */
+ public static function getServerClassname() {
+ require_once(sprintf('XML/RPC2/Backend/%s/Server.php', self::getBackend()));
+ return sprintf('XML_RPC2_Backend_%s_Server', self::getBackend());
+ }
+ /* }}} */
+ /* getClientClassname {{{ */
+ /**
+ * Include the relevant php files for the client class, and return the backend client
+ * class name.
+ *
+ * @return string The Client class name
+ */
+ public static function getClientClassname() {
+ require_once(sprintf('XML/RPC2/Backend/%s/Client.php', self::getBackend()));
+ return sprintf('XML_RPC2_Backend_%s_Client', self::getBackend());
+ }
+ /* }}} */
+ /* getValueClassname {{{ */
+ /**
+ * Include the relevant php files for the value class, and return the backend value
+ * class name.
+ *
+ * @return string The Value class name
+ */
+ public static function getValueClassname() {
+ require_once(sprintf('XML/RPC2/Backend/%s/Value.php', self::getBackend()));
+ return sprintf('XML_RPC2_Backend_%s_Value', self::getBackend());
+ }
+ /* }}} */
+}
90 XML/RPC2/Backend/Php/Client.php
View
@@ -0,0 +1,90 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Util/HTTPRequest.php';
+require_once 'XML/RPC2/Value.php';
+require_once 'XML/RPC2/Client.php';
+require_once 'XML/RPC2/Backend/Php/Request.php';
+require_once 'XML/RPC2/Backend/Php/Response.php';
+/* }}} /*
+/**
+ * XML_RPC client backend class. This is the default, all-php XML_RPC client backend.
+ *
+ * This backend does not require the xmlrpc extension to be compiled in. It implements
+ * XML_RPC based on the always present DOM and SimpleXML PHP5 extensions.
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+class XML_RPC2_Backend_Php_Client extends XML_RPC2_Client
+{
+ /* constructor {{{ */
+ /**
+ * Construct a new XML_RPC2_Client PHP Backend.
+ *
+ * To create a new XML_RPC2_Client, a URI must be provided (e.g. http://xmlrpc.example.com/1.0/).
+ * Optionally, a prefix may be set, wich will be prepended to method names, before calling.
+ * Prefixes are extremely useful namely when method names contain a period '.' turning them invalid
+ * under PHP syntax.
+ *
+ * @param string URI for the XML-RPC server
+ * @param string (optional) Prefix to prepend on all called functions
+ * @param string (optional) Proxy server URI
+ *
+ */
+ function __construct($uri, $prefix = '', $proxy = null)
+ {
+ parent::__construct($uri, $prefix, $proxy);
+ }
+ /* }}} */
+ /* remoteCall {{{ */
+ /**
+ * remoteCall executes the XML-RPC call, and returns the result
+ *
+ * @param string Method name
+ * @param array Parameters
+ */
+ public function remoteCall($methodName, $parameters)
+ {
+ $request = new XML_RPC2_Backend_Php_Request($this->getPrefix() . $methodName);
+ $request->setParameters($parameters);
+ $request = $request->encode();
+ $uri = $this->getUri();
+ $httpRequest = new XML_RPC2_Util_HTTPRequest($uri);
+ $httpRequest->setPostData($request);
+ $httpRequest->sendRequest();
+ return XML_RPC2_Backend_Php_Response::decode(simplexml_load_string($httpRequest->getBody()));
+ }
+ /* }}} */
+}
+?>
166 XML/RPC2/Backend/Php/Request.php
View
@@ -0,0 +1,166 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ * @author Sergio Carvalho <sergio.carvalho@portugalmail.com>
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Backend/Php/Value.php';
+/* }}} /*
+/**
+ * XML_RPC request backend class. This class represents an XML_RPC request, exposing the methods
+ * needed to encode/decode a request.
+ *
+ * @author Sergio Carvalho <sergio.carvalho@portugalmail.com>
+ * @package XML_RPC2
+ */
+class XML_RPC2_Backend_Php_Request
+{
+ /* Fields {{{ */
+ /** Name of requested method */
+ protected $_methodName = '';
+ /** Request parameters */
+ protected $_parameters = null;
+ /* }}} */
+ /* setMethodName {{{ */
+ /**
+ * methodName property setter
+ *
+ * @param mixed value The new methodName
+ */
+ protected function setMethodName($value)
+ {
+ $this->_methodName = $value;
+ }
+ /* }}} */
+ /* getMethodName {{{ */
+ /**
+ * methodName property getter
+ *
+ * @return mixed The current methodName
+ */
+ public function getMethodName()
+ {
+ return $this->_methodName;
+ }
+ /* }}} */
+ /* setParameters {{{ */
+ /**
+ * parameters property setter
+ *
+ * @param mixed value The new parameters
+ */
+ public function setParameters($value)
+ {
+ $this->_parameters = $value;
+ }
+ /* }}} */
+ /* addParameter {{{ */
+ /**
+ * parameters property appender
+ *
+ * @param mixed value The new parameter
+ */
+ public function addParameter($value)
+ {
+ $this->_parameters[] = $value;
+ }
+ /* }}} */
+ /* getParameters {{{ */
+ /**
+ * parameters property getter
+ *
+ * @return mixed The current parameters
+ */
+ public function getParameters()
+ {
+ return $this->_parameters;
+ }
+ /* }}} */
+ /* constructor {{{ */
+ /**
+ * Create a new xml-rpc request with the provided methodname
+ *
+ * @param string Name of method targeted by this xml-rpc request
+ */
+ function __construct($methodName)
+ {
+ $this->setMethodName($methodName);
+ $this->setParameters(array());
+ }
+ /* }}} */
+ /* encode {{{ */
+ /**
+ * Encode the request for transmission.
+ *
+ * @return string XML-encoded request (a full XML document)
+ */
+ public function encode()
+ {
+ $methodName = $this->getMethodName();
+ $parameters = $this->getParameters();
+
+ $result = '<?xml version="1.0"?>';
+ $result .= '<methodCall>';
+ $result .= "<methodName>${methodName}</methodName>";
+ $result .= '<params>';
+ foreach($parameters as $parameter) {
+ $result .= '<param><value>';
+ $result .= ($parameter instanceof XML_RPC2_Backend_Php_Value) ? $parameter->encode() : XML_RPC2_Backend_Php_Value::createFromNative($parameter)->encode();
+ $result .= '</value></param>';
+ }
+ $result .= '</params>';
+ $result .= '</methodCall>';
+ return $result;
+ }
+ /* }}} */
+ /* createFromDecode {{{ */
+ /**
+ * Decode a request from XML and construct a request object with the createFromDecoded values
+ *
+ * @param SimpleXMLElement The encoded XML-RPC request.
+ * @return XML_RPC2_Backend_Php_Request The xml-rpc request, represented as an object instance
+ */
+ public static function createFromDecode($simpleXML)
+ {
+ $methodName = (string) $simpleXML->methodName;
+ $params = array();
+ foreach ($simpleXML->params->param as $param) {
+ foreach ($param->value as $value) {
+ $params[] = XML_RPC2_Backend_Php_Value::createFromDecode($value)->getNativeValue();
+ }
+ }
+ $result = new XML_RPC2_Backend_Php_Request($methodName);
+ $result->setParameters($params);
+ return $result;
+ }
+ /* }}} */
+}
+?>
124 XML/RPC2/Backend/Php/Response.php
View
@@ -0,0 +1,124 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Backend/Php/Value.php';
+require_once 'XML/RPC2/Backend/Php/Value/Struct.php';
+/* }}} /*
+/**
+ * XML-RPC response backend class.
+ *
+ * This class represents an XML_RPC request, exposing the methods
+ * needed to encode/decode an xml-rpc response.
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+class XML_RPC2_Backend_Php_Response
+{
+ /* encode {{{ */
+ /**
+ * Encode a normal XML-RPC response, containing the provided value
+ *
+ * You may supply a php-native value, or an XML_RPC2_Backend_Php_Value instance, to be returned. Usually providing a native value
+ * is more convenient. However, for some types, XML_RPC2_Backend_Php_Value::createFromNative can't properly choose the xml-rpc
+ * type. In these cases, constructing an XML_RPC2_Backend_Php_Value and using it as param here is the only way to return the desired
+ * type.
+ *
+ * @see http://www.xmlrpc.com/spec
+ * @see XML_RPC2_Backend_Php_Value::createFromNative
+ * @param mixed The result value which the response will envelop
+ * @return string The XML payload
+ */
+ public static function encode($param)
+ {
+ if (!$param instanceof XML_RPC2_Backend_Php_Value) {
+ $param = XML_RPC2_Backend_Php_Value::createFromNative($param);
+ }
+ ob_start();
+ print('<?xml version="1.0"?>');
+?>
+<methodResponse><params><param><value><?= $param->encode() ?></value></param></params></methodResponse><?php
+ $result = ob_get_contents();
+ ob_end_clean();
+ return $result;
+ }
+ /* }}} */
+ /* encodeFault {{{ */
+ /**
+ * Encode a fault XML-RPC response, containing the provided code and message
+ *
+ * @see http://www.xmlrpc.com/spec
+ * @param int Response code
+ * @param string Response message
+ * @return string The XML payload
+ */
+ public static function encodeFault($code, $message)
+ {
+ $value = new XML_RPC2_Backend_Php_Value_Struct(array('faultCode' => (int) $code, 'faultString' => (string) $message));
+ ob_start();
+ print('<?xml version="1.0"?>');
+?>
+<methodResponse><fault><value><?= $value->encode() ?></value></fault></methodResponse><?php
+ $result = ob_get_contents();
+ ob_end_clean();
+ return $result;
+ }
+ /* }}} */
+ /* decode {{{ */
+ /**
+ * Parse a response and either return the native PHP result.
+ *
+ * This method receives an XML-RPC response document, in SimpleXML format, decodes it and returns the payload value.
+ *
+ * @param SimpleXmlElement The Transport XML
+ * @return mixed The response payload
+ *
+ * @see http://www.xmlrpc.com/spec
+ * @throws XML_RPC2_FaultException Signals the decoded response was an XML-RPC fault
+ * @throws XML_RPC2_DecodeException Signals an ill formed payload response section
+ */
+ public static function decode(SimpleXMLElement $xml)
+ {
+ $faultNode = $xml->xpath('/methodResponse/fault');
+ if (count($faultNode) == 1) {
+ throw XML_RPC2_FaultException::createFromDecode($faultNode[0]);
+ }
+ $paramValueNode = $xml->xpath('/methodResponse/params/param/value');
+ if (count($paramValueNode) == 1) {
+ return XML_RPC2_Backend_Php_Value::createFromDecode($paramValueNode[0])->getNativeValue();
+ }
+ throw new XML_RPC2_DecodeException('Unable to decode xml-rpc response. No fault nor params/param elements found');
+ }
+ /* }}} */
+}
+?>
112 XML/RPC2/Backend/Php/Server.php
View
@@ -0,0 +1,112 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Backend/Php/Request.php';
+require_once 'XML/RPC2/Backend/Php/Response.php';
+require_once 'XML/RPC2/Exception.php';
+/* }}} */
+/**
+ * XML_RPC server class PHP-only backend.
+ *
+ * The XML_RPC2_Server does the work of decoding and encoding xml-rpc request and response. The actual
+ * method execution is delegated to the call handler instance.
+ *
+ * The XML_RPC server is responsible for decoding the request and calling the appropriate method in the
+ * call handler class. It then encodes the result into an XML-RPC response and returns it to the client.
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+class XML_RPC2_Backend_Php_Server extends XML_RPC2_Server
+{
+ /* Constructor {{{ */
+ /**
+ * Create a new XML-RPC Server.
+ *
+ * The constructor receives only one parameter: the Call Handler. The call handler executes the actual
+ * method call. XML_RPC2 server acts as a protocol decoder/encoder between the call handler and the client
+ */
+ function __construct($callHandler)
+ {
+ parent::__construct($callHandler);
+ }
+ /* }}} */
+
+ /* errorToException {{{ */
+ public static function errorToException($errno, $errstr, $errfile, $errline)
+ {
+ switch ($errno) {
+ case E_WARNING:
+ case E_NOTICE:
+ case E_USER_WARNING:
+ case E_USER_NOTICE:
+ case E_STRICT:
+ // Silence warnings
+ // TODO Logging should occur here
+ break;
+ default:
+ throw new Exception('PHP error reported "' . $errstr . '" on ' . $errfile . ':' . $errline);
+ }
+ }
+ /* }}} */
+
+ /* handleCall {{{ */
+ /**
+ * Respond to the XML-RPC request.
+ *
+ * handleCall reads the XML-RPC request from the raw HTTP body and decodes it. It then calls the
+ * corresponding method in the call handler class, returning the encoded result to the client.
+ */
+ public function handleCall()
+ {
+ try {
+ $oldErrorHandler = set_error_handler(array('XML_RPC2_Backend_Php_Server', 'errorToException'));
+ $request = @simplexml_load_string($GLOBALS['HTTP_RAW_POST_DATA']);
+ if (!is_object($request)) throw new XML_RPC2_FaultException('Unable to parse request XML', 0);
+ $request = XML_RPC2_Backend_Php_Request::createFromDecode($request);
+
+ $method = $request->getMethodName();
+ if (array_key_exists($method, $this->getAliases())) {
+ $method = $this->_aliases[$method];
+ }
+ $arguments = $request->getParameters();
+ print(XML_RPC2_Backend_Php_Response::encode(call_user_func_array(array($this->getCallHandler(), $method), $arguments)));
+ if ($oldErrorHandler !== FALSE) set_error_handler($oldErrorHandler);
+ } catch (XML_RPC2_FaultException $e) {
+ print(XML_RPC2_Backend_Php_Response::encodeFault($e->getFaultCode(), $e->getMessage()));
+ } catch (Exception $e) {
+ print(XML_RPC2_Backend_Php_Response::encodeFault(1, 'Unhandled ' . get_class($e) . ' exception:' . $e->getMessage()));
+ }
+ }
+ /* }}} */
+}
+?>
218 XML/RPC2/Backend/Php/Value.php
View
@@ -0,0 +1,218 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Value.php';
+/* }}} */
+/**
+ * XML_RPC value abstract class. All XML_RPC value classes inherit from XML_RPC2_Value
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+abstract class XML_RPC2_Backend_Php_Value extends XML_RPC2_Value
+{
+ /* createFromNative {{{ */
+ /**
+ * Choose a XML_RPC2_Value subclass appropriate for the
+ * given value and create it.
+ *
+ * This method tries to find the most adequate XML-RPC datatype to hold
+ * a given PHP native type. Note that distinguishing some datatypes may be
+ * difficult:
+ * - Timestamps are represented by PHP integers, so an XML_RPC2_Value_Datetime is never returned
+ * - Indexed arrays and associative arrays are the same native PHP type. In this case:
+ * a) The array's indexes start at 0 or 1 and increase monotonically with step 1, or
+ * b) they do not
+ * in the first case, an XML_RPC2_Value_Array is returned. In the second, a XML_RPC2_Value_Struct is returned.
+ * - PHP Objects are serialized and represented in an XML_RPC2_Value_Base64
+ *
+ * Whenever native object automatic detection proves inaccurate, use XML_RPC2_Value::createFromNative providing
+ * a valid explicit type as second argument
+ *
+ * the appropriate XML_RPC2_Value child class instead.
+ *
+ * @param mixed The native value
+ * @param string The xml-rpc target encoding type, as per the xmlrpc spec (optional)
+ * @throws XML_RPC2_InvalidTypeEncodeException When the native value has a type that can't be translated to XML_RPC
+ * @return A new XML_RPC2_Value instance
+ * @see XML_RPC_Client::__call
+ * @see XML_RPC_Server
+ */
+ public static function createFromNative($nativeValue, $explicitType = null)
+ {
+ if (is_null($explicitType)) {
+ switch (gettype($nativeValue)) {
+ case 'boolean':
+ $explicitType = 'boolean';
+ break;
+ case 'integer':
+ $explicitType = 'int';
+ break;
+ case 'double':
+ $explicitType = 'double';
+ break;
+ case 'string':
+ $explicitType = 'string';
+ break;
+ case 'array':
+ $explicitType = 'array';
+ $keys = array_keys($nativeValue);
+ if (($keys[0] !== 0) && ($keys[0] !== 1)) $explicitType = 'struct';
+ $i=0;
+ do {
+ $previous = $keys[$i];
+ $i++;
+ if (array_key_exists($i, $keys) && ($keys[$i] !== $keys[$i - 1] + 1)) $explicitType = 'struct';
+ } while (array_key_exists($i, $keys) && $explicitType == 'array');
+ break;
+ case 'object':
+ $nativeValue = serialize($nativeValue);
+ $explicitType = 'base64';
+ break;
+ case 'resource':
+ case 'NULL':
+ case 'unknown type':
+ throw new XML_RPC2_InvalidTypeEncodeException(sprintf('Impossible to encode value \'%s\' from type \'%s\'. No analogous type in XML_RPC.',
+ (string) $nativeValue,
+ gettype($nativeValue)));
+ default:
+ throw new XML_RPC2_InvalidTypeEncodeException(sprintf('Unexpected PHP native type returned by gettype: \'%s\', for value \'%s\'',
+ gettype($nativeValue),
+ (string) $nativeValue));
+ }
+ }
+
+ $explicitType = ucfirst(strtolower($explicitType));
+ switch ($explicitType) {
+ case 'I4':
+ case 'Int':
+ case 'Boolean':
+ case 'Double':
+ case 'String':
+ require_once 'XML/RPC2/Backend/Php/Value/Scalar.php';
+ return XML_RPC2_Backend_Php_Value_Scalar::createFromNative($nativeValue);
+ break;
+ case 'Datetime.iso8601':
+ require_once 'XML/RPC2/Backend/Php/Value/Datetime.php';
+ return new XML_RPC2_Backend_Php_Value_Datetime($nativeValue);
+ break;
+ case 'Base64':
+ require_once 'XML/RPC2/Backend/Php/Value/Base64.php';
+ return new XML_RPC2_Backend_Php_Value_Base64($nativeValue);
+ break;
+ case 'Array':
+ require_once 'XML/RPC2/Backend/Php/Value/Array.php';
+ return new XML_RPC2_Backend_Php_Value_Array($nativeValue);
+ break;
+ case 'Struct':
+ require_once 'XML/RPC2/Backend/Php/Value/Struct.php';
+ return new XML_RPC2_Backend_Php_Value_Struct($nativeValue);
+ break;
+ default:
+ throw new XML_RPC2_InvalidTypeEncodeException(sprintf('Unexpected explicit encoding type \'%s\'', $explicitType));
+ }
+ }
+ /* }}} */
+ /* createFromDecode {{{ */
+ /**
+ * Decode an encoded value and build the applicable XML_RPC2_Value subclass
+ *
+ * @param SimpleXMLElement The encoded XML-RPC value,
+ */
+ public static function createFromDecode($simpleXML)
+ {
+ // TODO Remove reparsing of XML fragment, when SimpleXML proves more solid. Currently it segfaults when
+ // xpath is used both in an element and in one of its children
+ $simpleXML = simplexml_load_string($simpleXML->asXML());
+
+ $valueType = $simpleXML->xpath('./*');
+ if (count($valueType) == 1) { // Usually we must check the node name
+ $nodename = dom_import_simplexml($valueType[0])->nodeName;
+ switch ($nodename) {
+ case 'i4':
+ case 'int':
+ $nativeType = 'Integer';
+ break;
+ case 'boolean':
+ $nativeType = 'Boolean';
+ break;
+ case 'double':
+ $nativeType = 'Double';
+ break;
+ case 'string':
+ $nativeType = 'String';
+ break;
+ case 'dateTime.iso8601':
+ $nativeType = 'Datetime';
+ break;
+ case 'base64':
+ $nativeType = 'Base64';
+ break;
+ case 'array':
+ $nativeType = 'Array';
+ break;
+ case 'struct':
+ $nativeType = 'Struct';
+ break;
+ default:
+ throw new XML_RPC2_DecodeException(sprintf('Unable to decode XML-RPC value. Value type is not recognized \'%s\'', $nodename));
+ }
+ } elseif (count($valueType) == 0) { // Default type is string
+ $nativeType = 'String';
+ } else {
+ throw new XML_RPC2_DecodeException(sprintf('Unable to decode XML-RPC value. Value presented %s type nodes: %s.', count($valueType), $simpleXML->asXML()));
+ }
+ require_once(sprintf('XML/RPC2/Backend/Php/Value/%s.php', $nativeType));
+ $nativeType = 'XML_RPC2_Backend_Php_Value_' . $nativeType;
+ return self::createFromNative(@call_user_func(array($nativeType, 'decode'), $simpleXML), $nodename);
+ }
+ /* }}} */
+
+ /* encode(abstract) {{{ */
+ /**
+ * Encode the instance into XML, for transport
+ *
+ * @return string The encoded XML-RPC value,
+ */
+ public abstract function encode();
+ /* }}} */
+ /* decode(abstract) {{{ */
+ /**
+ * decode. Decode transport XML and set the instance value accordingly
+ *
+ * @param mixed The encoded XML-RPC value,
+ */
+ public abstract static function decode($xml);
+ /* }}} */
+}
+?>
134 XML/RPC2/Backend/Php/Value/Array.php
View
@@ -0,0 +1,134 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Backend/Php/Value.php';
+/* }}} */
+/**
+ * XML_RPC array value class. Represents values of type array
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+class XML_RPC2_Backend_Php_Value_Array extends XML_RPC2_Backend_Php_Value
+{
+ /* Fields {{{ */
+ /** The native value of this scalar instance */
+ /* setNativeValue {{{ */
+ /**
+ * nativeValue property setter
+ *
+ * @param mixed value The new nativeValue
+ */
+ protected function setNativeValue($value)
+ {
+ if (!is_array($value)) {
+ throw new XML_RPC2_InvalidTypeException(sprintf('Cannot create XML_RPC2_Value_Array from type \'%s\'.', gettype($nativeValue)));
+ }
+ $this->_nativeValue = $value;
+ }
+ /* }}} */
+ /* getNativeValue {{{ */
+ /**
+ * nativeValue property getter
+ *
+ * @return mixed The current nativeValue
+ */
+ public function getNativeValue()
+ {
+ return $this->_nativeValue;
+ }
+ /* }}} */
+ protected $_nativeValue = null;
+ /* }}} */
+ /* Constructor {{{ */
+ /**
+ * Constructor. Will build a new XML_RPC2_Backend_Php_Value_Array with the given nativeValue
+ *
+ * @param mixed nativeValue
+ */
+ public function __construct($nativeValue)
+ {
+ $this->setNativeValue($nativeValue);
+ }
+ /* }}} */
+ /* createFromDecode {{{ */
+ /**
+ * Decode an encoded value and build the applicable XML_RPC2_Value subclass
+ *
+ * @param string The encoded XML-RPC value,
+ */
+ public static function createFromDecode($encodedString)
+ {
+ }
+ /* }}} */
+ /* encode {{{ */
+ /**
+ * Encode the instance into XML, for transport
+ *
+ * @return string The encoded XML-RPC value,
+ */
+ public function encode()
+ {
+ $result = '<array><data>';
+ foreach($this->getNativeValue() as $element) {
+ $result .= '<value>';
+ $result .= ($element instanceof XML_RPC2_Backend_Php_Value) ?
+ $element->encode() :
+ XML_RPC2_Backend_Php_Value::createFromNative($element)->encode();
+ $result .= '</value>';
+ }
+ $result .= '</data></array>';
+ return $result;
+ }
+ /* }}} */
+ /* decode {{{ */
+ /**
+ * decode. Decode transport XML and set the instance value accordingly
+ *
+ * @param mixed The encoded XML-RPC value,
+ */
+ public static function decode($xml)
+ {
+ // TODO Remove reparsing of XML fragment, when SimpleXML proves more solid. Currently it segfaults when
+ // xpath is used both in an element and in one of its children
+ $xml = simplexml_load_string($xml->asXML());
+ $values = $xml->xpath('/value/array/data/value');
+ $result = array();
+ foreach (array_keys($values) as $i) {
+ $result[] = XML_RPC2_Backend_Php_Value::createFromDecode($values[$i])->getNativeValue();
+ }
+ return $result;
+ }
+ /* }}} */
+}
+?>
89 XML/RPC2/Backend/Php/Value/Base64.php
View
@@ -0,0 +1,89 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Backend/Php/Value/Scalar.php';
+/* }}} */
+/**
+ * XML_RPC base64 value class. Instances of this class represent base64-encoded string scalars in XML_RPC
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+class XML_RPC2_Backend_Php_Value_Base64 extends XML_RPC2_Backend_Php_Value_Scalar
+{
+ /* Constructor {{{ */
+ /**
+ * Constructor. Will build a new XML_RPC2_Backend_Php_Value_Base64 with the given value
+ *
+ * This class handles encoding-decoding internally. Do not provide the
+ * native string base64-encoded
+ *
+ * @param mixed String to be transmited base64-encoded
+ */
+ public function __construct($nativeValue)
+ {
+ $this->setScalarType('base64');
+ $this->setNativeValue($nativeValue);
+ }
+ /* }}} */
+ /* encode {{{ */
+ /**
+ * Encode the instance into XML, for transport
+ *
+ * @return string The encoded XML-RPC value,
+ */
+ public function encode()
+ {
+ return '<' . $this->getScalarType() . '>' . base64_encode($this->getNativeValue()) . '</' . $this->getScalarType() . '>';
+ }
+ /* }}} */
+ /* decode {{{ */
+ /**
+ * decode. Decode transport XML and set the instance value accordingly
+ *
+ * @param mixed The encoded XML-RPC value,
+ */
+ public static function decode($xml)
+ {
+ // TODO Remove reparsing of XML fragment, when SimpleXML proves more solid. Currently it segfaults when
+ // xpath is used both in an element and in one of its children
+ $xml = simplexml_load_string($xml->asXML());
+ $value = $xml->xpath('/value/base64/text()');
+ if (!array_key_exists(0, $value)) {
+ $value = $xml->xpath('/value/text()');
+ }
+ return base64_decode($value[0]);
+ }
+ /* }}} */
+}
+?>
83 XML/RPC2/Backend/Php/Value/Boolean.php
View
@@ -0,0 +1,83 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Backend/Php/Value/Scalar.php';
+/* }}} */
+/**
+ * XML_RPC boolean value class. Instances of this class represent boolean scalars in XML_RPC
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+class XML_RPC2_Backend_Php_Value_Boolean extends XML_RPC2_Backend_Php_Value_Scalar
+{
+ /* Constructor {{{ */
+ /**
+ * Constructor. Will build a new XML_RPC2_Value_Boolean with the given value
+ *
+ * @param mixed value
+ */
+ public function __construct($nativeValue)
+ {
+ parent::__construct('boolean', $nativeValue);
+ }
+ /* }}} */
+ /* encode {{{ */
+ /**
+ * Encode the instance into XML, for transport
+ *
+ * @return string The encoded XML-RPC value,
+ */
+ public function encode()
+ {
+ return '<' . $this->getScalarType() . '>' . ($this->getNativeValue() ? 1 : 0). '</' . $this->getScalarType() . '>';
+ }
+ /* }}} */
+ /* decode {{{ */
+ /**
+ * decode. Decode transport XML and set the instance value accordingly
+ *
+ * @param mixed The encoded XML-RPC value,
+ */
+ public static function decode($xml)
+ {
+ // TODO Remove reparsing of XML fragment, when SimpleXML proves more solid. Currently it segfaults when
+ // xpath is used both in an element and in one of its children
+ $xml = simplexml_load_string($xml->asXML());
+ $value = $xml->xpath('/value/boolean/text()');
+
+ return (boolean) $value[0];
+ }
+ /* }}} */
+}
+?>
102 XML/RPC2/Backend/Php/Value/Datetime.php
View
@@ -0,0 +1,102 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Backend/Php/Value/Scalar.php';
+/* }}} */
+/**
+ * XML_RPC datetime value class. Instances of this class represent datetime scalars in XML_RPC
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+class XML_RPC2_Backend_Php_Value_Datetime extends XML_RPC2_Backend_Php_Value_Scalar
+{
+ /* Constructor {{{ */
+ /**
+ * Constructor. Will build a new XML_RPC2_Backend_Php_Value_Datetime with the given value
+ *
+ * The provided value can be an int, which will be interpreted as a Unix timestamp, or
+ * a string in iso8601 format
+ *
+ * @param mixed value
+ * @see http://www.w3.org/TR/NOTE-datetime
+ */
+ public function __construct($nativeValue)
+ {
+ $this->setScalarType('dateTime.iso8601');
+ if (gettype($nativeValue) == 'string') {
+ if (!preg_match('/([0-9]{4})(-?([0-9]{2})(-?([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?/',
+ $nativeValue,
+ $matches)) {
+ throw new XML_RPC2_InvalidDateFormatException(sprintf('Provided date \'%s\' is not ISO-8601.', $nativeValue));
+ } else {
+ $year = $matches[1];
+ $month = array_key_exists(3, $matches) ? $matches[3] : 1;
+ $day = array_key_exists(5, $matches) ? $matches[5] : 1;
+ $hour = array_key_exists(7, $matches) ? $matches[7] : 0;
+ $minutes = array_key_exists(8, $matches) ? $matches[8] : 0;
+ $seconds = array_key_exists(10, $matches) ? $matches[10] : 0;
+ $milliseconds = array_key_exists(12, $matches) ? ((double) ('0.' . $matches[12])) : 0;
+ $tzSeconds = array_key_exists(13, $matches) ?
+ ($matches[13] == 'Z' ? 0 : ($matches[15] == '-' ? -1 : 1) * (((int) $matches[16]) * 3600 + ((int) $matches[17]) * 60))
+ : 0;
+ $this->setNativeValue(
+ ((double) @gmmktime($hour, $minutes, $seconds, $month, $day, $year, 0)) +
+ ((double) $milliseconds) -
+ ((double) $tzSeconds));
+ }
+ } else {
+ $this->setNativeValue($nativeValue);
+ }
+ }
+ /* }}} */
+ /* decode {{{ */
+ /**
+ * decode. Decode transport XML and set the instance value accordingly
+ *
+ * @param mixed The encoded XML-RPC value,
+ */
+ public static function decode($xml)
+ {
+ // TODO Remove reparsing of XML fragment, when SimpleXML proves more solid. Currently it segfaults when
+ // xpath is used both in an element and in one of its children
+ $xml = simplexml_load_string($xml->asXML());
+ $value = $xml->xpath('/value/dateTime.iso8601/text()');
+ if (!array_key_exists(0, $value)) {
+ $value = $xml->xpath('/value/text()');
+ }
+ return (string) $value[0];
+ }
+ /* }}} */
+}
+?>
73 XML/RPC2/Backend/Php/Value/Double.php
View
@@ -0,0 +1,73 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Backend/Php/Value/Scalar.php';
+/* }}} */
+/**
+ * XML_RPC double value class. Instances of this class represent int scalars in XML_RPC
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+class XML_RPC2_Backend_Php_Value_Double extends XML_RPC2_Backend_Php_Value_Scalar
+{
+ /* Constructor {{{ */
+ /**
+ * Constructor. Will build a new XML_RPC2_Backend_Php_Value_Double with the given value
+ *
+ * @param mixed value
+ */
+ public function __construct($nativeValue)
+ {
+ $this->setScalarType('double');
+ $this->setNativeValue($nativeValue);
+ }
+ /* }}} */
+ /* decode {{{ */
+ /**
+ * decode. Decode transport XML and set the instance value accordingly
+ *
+ * @param mixed The encoded XML-RPC value,
+ */
+ public static function decode($xml)
+ {
+ // TODO Remove reparsing of XML fragment, when SimpleXML proves more solid. Currently it segfaults when
+ // xpath is used both in an element and in one of its children
+ $xml = simplexml_load_string($xml->asXML());
+ $value = $xml->xpath('/value/double/text()');
+
+ return (double) $value[0];
+ }
+ /* }}} */
+}
+?>
73 XML/RPC2/Backend/Php/Value/Integer.php
View
@@ -0,0 +1,73 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Backend/Php/Value/Scalar.php';
+/* }}} */
+/**
+ * XML_RPC integer value class. Instances of this class represent int scalars in XML_RPC
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+class XML_RPC2_Backend_Php_Value_Integer extends XML_RPC2_Backend_Php_Value_Scalar
+{
+ /* Constructor {{{ */
+ /**
+ * Constructor. Will build a new XML_RPC2_Backend_Php_Value_Integer with the given value
+ *
+ * @param mixed value
+ */
+ public function __construct($nativeValue)
+ {
+ $this->setScalarType('int');
+ $this->setNativeValue($nativeValue);
+ }
+ /* }}} */
+ /* decode {{{ */
+ /**
+ * decode. Decode transport XML and set the instance value accordingly
+ *
+ * @param mixed The decoded XML-RPC value,
+ */
+ public static function decode($xml)
+ {
+ // TODO Remove reparsing of XML fragment, when SimpleXML proves more solid. Currently it segfaults when
+ // xpath is used both in an element and in one of its children
+ $xml = simplexml_load_string($xml->asXML());
+ $value = $xml->xpath('/value/int/text()|/value/i4/text()');
+
+ return (int) $value[0];
+ }
+ /* }}} */
+}
+?>
162 XML/RPC2/Backend/Php/Value/Scalar.php
View
@@ -0,0 +1,162 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Backend/Php/Value.php';
+/* }}} */
+/**
+ * XML_RPC scalar value abstract class. All XML_RPC value classes representing scalar types inherit from XML_RPC2_Value_Scalar
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+abstract class XML_RPC2_Backend_Php_Value_Scalar extends XML_RPC2_Backend_Php_Value
+{
+ /* Fields {{{ */
+ /** The native type of this scalar instance as per XML_RPC spec */
+ /* setScalarType {{{ */
+ /**
+ * scalarType property setter
+ *
+ * @param mixed value The new scalarType
+ */
+ protected function setScalarType($value)
+ {
+ switch ($value) {
+ case 'int':
+ case 'i4':
+ case 'boolean':
+ case 'string':
+ case 'double':
+ case 'dateTime.iso8601':
+ case 'base64':
+ $this->_scalarType = $value;
+ break;
+ default:
+ throw new XML_RPC2_InvalidTypeException(sprintf('Type \'%s\' is not an XML-RPC scalar type', $value));
+ }
+ }
+ /* }}} */
+ /* getScalarType {{{ */
+ /**
+ * scalarType property getter
+ *
+ * @return mixed The current scalarType
+ */
+ public function getScalarType()
+ {
+ return $this->_scalarType;
+ }
+ /* }}} */
+ protected $_scalarType = null;
+ /** The native value of this scalar instance */
+ /* setNativeValue {{{ */
+ /**
+ * nativeValue property setter
+ *
+ * @param mixed value The new nativeValue
+ */
+ protected function setNativeValue($value)
+ {
+ $this->_nativeValue = $value;
+ }
+ /* }}} */
+ /* getNativeValue {{{ */
+ /**
+ * nativeValue property getter
+ *
+ * @return mixed The current nativeValue
+ */
+ public function getNativeValue()
+ {
+ return $this->_nativeValue;
+ }
+ /* }}} */
+ protected $_nativeValue = null;
+ /* }}} */
+ /* Constructor {{{ */
+ /**
+ * Constructor. Will build a new XML_RPC2_Value_Scalar with the given nativeValue
+ *
+ * @param mixed nativeValue
+ */
+ public function __construct($scalarType, $nativeValue)
+ {
+ $this->setScalarType($scalarType);
+ $this->setNativeValue($nativeValue);
+ }
+ /* }}} */
+ /* createFromNative {{{ */
+ /**
+ * Choose a XML_RPC2_Value subclass appropriate for the
+ * given value and create it.
+ *
+ * @param string The native value
+ * @param string Optinally, the scalar type to use
+ * @throws XML_RPC2_InvalidTypeEncodeException When native value's type is not a native type
+ * @return XML_RPC2_Value The newly created value
+ */
+ public static function createFromNative($nativeValue, $explicitType = null)
+ {
+ if (is_null($explicitType)) {
+ switch (gettype($nativeValue)) {
+ case 'boolean':
+ case 'integer':
+ case 'double':
+ case 'string':
+ $explicitType = gettype($nativeValue);
+ break;
+ default:
+ throw new XML_RPC2_InvalidTypeEncodeException(sprintf('Impossible to encode scalar value \'%s\' from type \'%s\'. Native type is not a scalar XML_RPC type (boolean, integer, double, string)',
+ (string) $nativeValue,
+ gettype($nativeValue)));
+ }
+ }
+ $explicitType = ucfirst(strtolower($explicitType));
+ require_once(sprintf('XML/RPC2/Backend/Php/Value/%s.php', $explicitType));
+ $explicitType = sprintf('XML_RPC2_Backend_Php_Value_%s', $explicitType);
+ return new $explicitType($nativeValue);
+ }
+ /* }}} */
+ /* encode {{{ */
+ /**
+ * Encode the instance into XML, for transport
+ *
+ * @return string The encoded XML-RPC value,
+ */
+ public function encode()
+ {
+ return '<' . $this->getScalarType() . '>' . $this->getNativeValue() . '</' . $this->getScalarType() . '>';
+ }
+ /* }}} */
+}
+?>
86 XML/RPC2/Backend/Php/Value/String.php
View
@@ -0,0 +1,86 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Backend/Php/Value/Scalar.php';
+/* }}} */
+/**
+ * XML_RPC string value class. Instances of this class represent string scalars in XML_RPC
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+class XML_RPC2_Backend_Php_Value_String extends XML_RPC2_Backend_Php_Value_Scalar
+{
+ /* Constructor {{{ */
+ /**
+ * Constructor. Will build a new XML_RPC2_Backend_Php_Value_String with the given value
+ *
+ * @param mixed value
+ */
+ public function __construct($nativeValue)
+ {
+ $this->setScalarType('string');
+ $this->setNativeValue($nativeValue);
+ }
+ /* }}} */
+ /* encode {{{ */
+ /**
+ * Encode the instance into XML, for transport
+ *
+ * @return string The encoded XML-RPC value,
+ */
+ public function encode()
+ {
+ return '<' . $this->getScalarType() . '>' . strtr($this->getNativeValue(),array('&' => '&amp;', '<' => '&lt;' , '>' => '&gt;')) . '</' . $this->getScalarType() . '>';
+ }
+ /* }}} */
+ /* decode {{{ */
+ /**
+ * decode. Decode transport XML and set the instance value accordingly
+ *
+ * @param mixed The encoded XML-RPC value,
+ */
+ public static function decode($xml)
+ {
+ // TODO Remove reparsing of XML fragment, when SimpleXML proves more solid. Currently it segfaults when
+ // xpath is used both in an element and in one of its children
+ $xml = simplexml_load_string($xml->asXML());
+ $value = $xml->xpath('/value/string/text()');
+ if (!array_key_exists(0, $value)) {
+ $value = $xml->xpath('/value/text()');
+ }
+ return (string) $value[0];
+ }
+ /* }}} */
+}
+?>
129 XML/RPC2/Backend/Php/Value/Struct.php
View
@@ -0,0 +1,129 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Backend/Php/Value.php';
+/* }}} */
+/**
+ * XML_RPC struct value class. Represents values of type struct (associative struct)
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+class XML_RPC2_Backend_Php_Value_Struct extends XML_RPC2_Backend_Php_Value
+{
+ /* Fields {{{ */
+ /** The native value of this scalar instance */
+ /* setNativeValue {{{ */
+ /**
+ * nativeValue property setter
+ *
+ * @param mixed value The new nativeValue
+ */
+ protected function setNativeValue($value)
+ {
+ if (!is_array($value)) {
+ throw new XML_RPC2_InvalidTypeException(sprintf('Cannot create XML_RPC2_Backend_Php_Value_Struct from type \'%s\'.', gettype($nativeValue)));
+ }
+ $this->_nativeValue = $value;
+ }
+ /* }}} */
+ /* getNativeValue {{{ */
+ /**
+ * nativeValue property getter
+ *
+ * @return mixed The current nativeValue
+ */
+ public function getNativeValue()
+ {
+ return $this->_nativeValue;
+ }
+ /* }}} */
+ protected $_nativeValue = null;
+ /* }}} */
+ /* Constructor {{{ */
+ /**
+ * Constructor. Will build a new XML_RPC2_Backend_Php_Value_Scalar with the given nativeValue
+ *
+ * @param mixed nativeValue
+ */
+ public function __construct($nativeValue)
+ {
+ $this->setNativeValue($nativeValue);
+ }
+ /* }}} */
+ /* encode {{{ */
+ /**
+ * Encode the instance into XML, for transport
+ *
+ * @return string The encoded XML-RPC value,
+ */
+ public function encode()
+ {
+ $result = '<struct>';
+ foreach($this->getNativeValue() as $name => $element) {
+ $result .= '<member>';
+ $result .= '<name>';
+ $result .= strtr($name, array('&' => '&amp;', '<' => '&lt;', '>' => '&gt;'));
+ $result .= '</name>';
+ $result .= '<value>';
+ $result .= ($element instanceof XML_RPC2_Backend_Php_Value) ?
+ $element->encode() :
+ XML_RPC2_Backend_Php_Value::createFromNative($element)->encode();
+ $result .= '</value>';
+ $result .= '</member>';
+ }
+ $result .= '</struct>';
+ return $result;
+ }
+ /* }}} */
+ /* decode {{{ */
+ /**
+ * decode. Decode transport XML and set the instance value accordingly
+ *
+ * @param mixed The encoded XML-RPC value,
+ */
+ public static function decode($xml)
+ {
+ // TODO Remove reparsing of XML fragment, when SimpleXML proves more solid. Currently it segfaults when
+ // xpath is used both in an element and in one of its children
+ $xml = simplexml_load_string($xml->asXML());
+ $values = $xml->xpath('/value/struct/member');
+ $result = array();
+ foreach (array_keys($values) as $i) {
+ $result[(string) $values[$i]->name] = XML_RPC2_Backend_Php_Value::createFromDecode($values[$i]->value)->getNativeValue();
+ }
+ return $result;
+ }
+ /* }}} */
+}
+?>
92 XML/RPC2/Backend/Xmlrpcext/Client.php
View
@@ -0,0 +1,92 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Value.php';
+require_once 'XML/RPC2/Client.php';
+require_once 'XML/RPC2/Backend/Php/Request.php';
+require_once 'XML/RPC2/Backend/Php/Response.php';
+require_once 'XML/RPC2/Util/HTTPRequest.php';
+/* }}} /*
+/**
+ * XML_RPC client backend class. This backend class uses the XMLRPCext extension to execute the call.
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+class XML_RPC2_Backend_Xmlrpcext_Client extends XML_RPC2_Client
+{
+ /* constructor {{{ */
+ /**
+ * Construct a new XML_RPC2_Client PHP Backend.
+ *
+ * To create a new XML_RPC2_Client, a URI must be provided (e.g. http://xmlrpc.example.com/1.0/).
+ * Optionally, a prefix may be set, wich will be prepended to method names, before calling.
+ * Prefixes are extremely useful namely when method names contain a period '.' turning them invalid
+ * under PHP syntax.
+ *
+ * @param string URI for the XML-RPC server
+ * @param string (optional) Prefix to prepend on all called functions
+ * @param string (optional) Proxy server URI
+ *
+ */
+ function __construct($uri, $prefix = '', $proxy = null)
+ {
+ parent::__construct($uri, $prefix, $proxy);
+ }
+ /* }}} */
+ /* remoteCall {{{ */
+ /**
+ * remoteCall executes the XML-RPC call, and returns the result
+ *
+ * @param string Method name
+ * @param array Parameters
+ */
+ public function remoteCall($methodName, $parameters)
+ {
+ $request = xmlrpc_encode_request($this->getPrefix() . $methodName, $parameters);
+ $uri = $this->getUri();
+ $httpRequest = new XML_RPC2_Util_HTTPRequest($uri);
+ $httpRequest->setPostData($request);
+ $httpRequest->sendRequest();
+ $result = xmlrpc_decode($httpRequest->getBody());
+ if ($result === false) {
+ throw new XML_RPC2_Exception('Unable to decode response');
+ }
+ if (xmlrpc_is_fault($result)) {
+ throw new XML_RPC2_FaultException($result['faultString'], $result['faultCode']);
+ }
+ return $result;
+ }
+ /* }}} */
+}
+?>
146 XML/RPC2/Backend/Xmlrpcext/Server.php
View
@@ -0,0 +1,146 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Backend/Php/Request.php';
+require_once 'XML/RPC2/Backend/Php/Response.php';
+require_once 'XML/RPC2/Exception.php';
+/* }}} */
+/**
+ * XML_RPC server class XMLRPCext extension-based backend
+ *
+ * The XML_RPC2_Server does the work of decoding and encoding xml-rpc request and response. The actual
+ * method execution is delegated to the call handler instance.
+ *
+ * The XML_RPC server is responsible for decoding the request and calling the appropriate method in the
+ * call handler class. It then encodes the result into an XML-RPC response and returns it to the client.
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+class XML_RPC2_Backend_Xmlrpcext_Server extends XML_RPC2_Server
+{
+ /* _xmlrpcextServer Field {{{ */
+ private $_xmlrpcextServer;
+ /** _xmlrpcextServer getter
+ *
+ * @return resource xmlrpcext server
+ */
+ private function getXmlrpcextServer()
+ {
+ return $this->_xmlrpcextServer;
+ }
+ /** _xmlrpcextServer setter
+ *
+ * @param resource xmlrpcext server
+ */
+ private function setXmlrpcextServer($server)
+ {
+ $this->_xmlrpcextServer = $server;
+ }
+ /* }}} */
+ /* Constructor {{{ */
+ /**
+ * Create a new XML-RPC Server.
+ *
+ * The constructor receives only one parameter: the Call Handler. The call handler executes the actual
+ * method call. XML_RPC2 server acts as a protocol decoder/encoder between the call handler and the client
+ */
+ function __construct($callHandler)
+ {
+ parent::__construct($callHandler);
+ $this->setXmlrpcextServer(xmlrpc_server_create());
+ foreach ($callHandler->getMethods() as $method) {
+ if (xmlrpc_server_register_method($this->getXmlrpcextServer(),
+ $method->getName(),
+ array($this, 'epiFunctionHandlerAdapter')) !== true) {
+ throw new XML_RPC2_Exception('Unable to setup XMLRPCext server. xmlrpc_server_register_method returned non-true.');
+ }
+ }
+ }
+ /* }}} */
+ /* epiFunctionHandlerAdapter {{{ */
+ /**
+ * This is an adapter between XML_RPC2_CallHandler::__call and xmlrpc_server_register_method callback interface
+ *
+ * @param string Method name
+ * @param array Parameters
+ * @param array Application data (ignored)
+ */
+ protected function epiFunctionHandlerAdapter($method_name, $params, $app_data) {
+ return @call_user_func_array(array($this->getCallHandler(), $method_name), $params);
+ }
+ /* }}} */
+ /* errorToException {{{ */
+ public static function errorToException($errno, $errstr, $errfile, $errline)
+ {
+ switch ($errno) {
+ case E_WARNING:
+ case E_NOTICE:
+ case E_USER_WARNING:
+ case E_USER_NOTICE:
+ case E_STRICT:
+ // Silence warnings
+ // TODO Logging should occur here
+ break;
+ default:
+ throw new Exception('Classic error reported "' . $errstr . '" on ' . $errfile . ':' . $errline);
+ }
+ }
+ /* }}} */
+ /* handleCall {{{ */
+ /**
+ * Respond to the XML-RPC request.
+ *
+ * handleCall reads the XML-RPC request from the raw HTTP body and decodes it. It then calls the
+ * corresponding method in the call handler class, returning the encoded result to the client.
+ */
+ public function handleCall()
+ {
+ try {
+ $oldErrorHandler = set_error_handler(array('XML_RPC2_Backend_Xmlrpcext_Server', 'errorToException'));
+ $response = @xmlrpc_server_call_method($this->getXmlrpcextServer(),
+ $GLOBALS['HTTP_RAW_POST_DATA'],
+ null,
+ array('output_type' => 'xml'));
+ header('Content-type: text/xml');
+ header('Content-length: '.strlen($response));
+ print $response;
+ if ($oldErrorHandler !== FALSE) set_error_handler($oldErrorHandler);
+ } catch (XML_RPC2_FaultException $e) {
+ print(XML_RPC2_Backend_Php_Response::encodeFault($e->getFaultCode(), $e->getMessage()));
+ } catch (Exception $e) {
+ print(XML_RPC2_Backend_Php_Response::encodeFault(1, 'Unhandled ' . get_class($e) . ' exception:' . $e->getMessage()));
+ }
+ }
+ /* }}} */
+}
+?>
61 XML/RPC2/Backend/Xmlrpcext/Value.php
View
@@ -0,0 +1,61 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Backend.php';
+/* }}} */
+/**
+ * XML_RPC value class for the XMLRPCext backend.
+ *
+ * @author Sérgio Carvalho
+ * @package XML_RPC2
+ */
+class XML_RPC2_Backend_Xmlrpcext_Value
+{
+ /* createFromNative {{{ */
+ /**
+ * Factory method that constructs the appropriate XML-RPC encoded type value
+ *
+ * @param mixed Value to be encode
+ * @param string Explicit XML-RPC type as enumerated in the XML-RPC spec (defaults to automatically selected type)
+ * @return mixed The encoded value
+ */
+ public static function createFromNative($value, $explicitType)
+ {
+ if (!xmlrpc_set_type($value, $explicitType)) {
+ throw new XML_RPC2_Exception('Error returned from xmlrpc_set_type');
+ }
+ return $value;
+ }
+ /* }}} */
+}
+?>
212 XML/RPC2/Client.php
View
@@ -0,0 +1,212 @@
+<?php
+/* LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
+ vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker:
+ +-----------------------------------------------------------------------------+
+ | Copyright (c) 2004 Sérgio Gonçalves Carvalho |
+ +-----------------------------------------------------------------------------+
+ | This file is part of XML_RPC2. |
+ | |
+ | XML_RPC is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU Lesser General Public License as published by |
+ | the Free Software Foundation; either version 2.1 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | XML_RPC2 is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Lesser General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Lesser General Public License |
+ | along with XML_RPC2; if not, write to the Free Software |
+ | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
+ | 02111-1307 USA |
+ +-----------------------------------------------------------------------------+
+ | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
+ +-----------------------------------------------------------------------------+
+}}} */
+/**
+ * @package XML_RPC2
+ */
+/**
+ */
+/* dependencies {{{ */
+require_once 'XML/RPC2/Exception.php';
+require_once 'XML/RPC2/Backend.php';
+/* }}} /*
+/**
+ * XML_RPC client class. Use this class to access remote methods.
+ *
+ * To use this class, construct it providing the server URL and method prefix.
+ * Then, call remote methods on the new instance as if they were local.
+ *
+ * Example:
+ * <code>
+ * require_once 'XML_RPC2/Client.php';
+ *
+ * $client = XML_RPC2_Client('http://xmlrpc.example.com/1.0/', 'example.');
+ * $result = $client->hello('Sérgio');
+ * print($result);
+ * </code>
+ *
+ * The above example will call the example.hello method on the xmlrpc.example.com
+ * server, under the /1.0/ URI.
+ *
+ * @package XML_RPC2
+ * @author Sérgio Carvalho
+ */
+abstract class XML_RPC2_Client
+{
+ /* uri Field {{{ */
+ /** Holds the uri for the XML_RPC server */
+ protected $_uri = null;
+ /** uri setter */
+ protected function setUri($uri)
+ {
+ if (!$uriParse = parse_url($uri)) {
+ throw new XML_RPC2_InvalidUriException(sprintf('Client URI \'%s\' is not valid', $uri));
+ }
+ $this->_uri = $uriParse;
+ foreach (array_keys($this->_uri) as $key) {
+ $this->_uri[$key] = urldecode($this->_uri[$key]);
+ }
+ $this->_uri['uri'] = $uri;
+ }
+ /** uri getter */
+ protected function getUri()
+ {
+ return $this->_uri['uri'];
+ }
+ /* }}} */
+ /* proxy Field {{{ */
+ /** Holds the proxy server data */
+ protected $_proxy = null;
+ /** proxy setter */
+ protected function setProxy($proxy)
+ {
+ if (is_null($proxy)) {
+ $this->_proxy = null;
+ return;
+ }
+ if (!$proxyParse = parse_url($proxy)) throw new XML_RPC2_InvalidProxyException(sprintf('Proxy URI \'%s\' is not valid', $proxy));
+ $this->_proxy = $proxyParse;
+ foreach (array_keys($this->_proxy) as $key) {
+ $this->_proxy[$key] = urldecode($this->_proxy[$key]);
+ }
+ $this->_proxy['uri'] = $proxy;