summaryrefslogtreecommitdiffstats
path: root/etc/inc
diff options
context:
space:
mode:
authorBill Marquette <billm@pfsense.org>2005-07-04 23:57:31 +0000
committerBill Marquette <billm@pfsense.org>2005-07-04 23:57:31 +0000
commit605938e5d037ba81982bfdd94e14000047901593 (patch)
tree2c30b8a35e904b985b903f4a6aadafca7464b8e1 /etc/inc
parent247c58ada314d1a5fb9938c95d856d32c6767892 (diff)
downloadpfsense-605938e5d037ba81982bfdd94e14000047901593.zip
pfsense-605938e5d037ba81982bfdd94e14000047901593.tar.gz
Import PEAR XMLRPC 1.3.1 - this includes the security fix for:
http://www.gulftech.org/?node=research&article_id=00088-07022005
Diffstat (limited to 'etc/inc')
-rw-r--r--etc/inc/xmlrpc_client.inc290
-rw-r--r--etc/inc/xmlrpc_server.inc193
2 files changed, 356 insertions, 127 deletions
diff --git a/etc/inc/xmlrpc_client.inc b/etc/inc/xmlrpc_client.inc
index 10ed4ac..f33c8cd 100644
--- a/etc/inc/xmlrpc_client.inc
+++ b/etc/inc/xmlrpc_client.inc
@@ -1,4 +1,5 @@
<?php
+
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/* $Id$ */
@@ -31,28 +32,43 @@
* @author Stig Bakken <stig@php.net>
* @author Martin Jansen <mj@php.net>
* @author Daniel Convissor <danielc@php.net>
- * @copyright 1999-2001 Edd Dumbill
+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
* @version CVS: $Id$
* @link http://pear.php.net/package/XML_RPC
*/
if (!function_exists('xml_parser_create')) {
- // Win 32 fix. From: "Leo West" <lwest@imaginet.fr>
- if ($WINDIR) {
- dl('php_xml.dll');
- } else {
- dl('xml.so');
- }
+ PEAR::loadExtension('xml');
}
/**#@+
* Error constants
*/
-define('XML_RPC_ERROR_INVALID_TYPE', 101);
-define('XML_RPC_ERROR_NON_NUMERIC_FOUND', 102);
-define('XML_RPC_ERROR_CONNECTION_FAILED', 103);
+/**
+ * Parameter values don't match parameter types
+ */
+define('XML_RPC_ERROR_INVALID_TYPE', 101);
+/**
+ * Parameter declared to be numeric but the values are not
+ */
+define('XML_RPC_ERROR_NON_NUMERIC_FOUND', 102);
+/**
+ * Communication error
+ */
+define('XML_RPC_ERROR_CONNECTION_FAILED', 103);
+/**
+ * The array or struct has already been started
+ */
define('XML_RPC_ERROR_ALREADY_INITIALIZED', 104);
+/**
+ * Incorrect parameters submitted
+ */
+define('XML_RPC_ERROR_INCORRECT_PARAMS', 105);
+/**
+ * Programming error by developer
+ */
+define('XML_RPC_ERROR_PROGRAMMING', 106);
/**#@-*/
@@ -138,6 +154,7 @@ $GLOBALS['XML_RPC_err'] = array(
'incorrect_params' => 3,
'introspect_unknown' => 4,
'http_error' => 5,
+ 'not_response_object' => 6,
);
/**
@@ -150,6 +167,7 @@ $GLOBALS['XML_RPC_str'] = array(
'incorrect_params' => 'Incorrect parameters passed to method',
'introspect_unknown' => 'Can\'t introspect: method unknown',
'http_error' => 'Didn\'t receive 200 OK from remote server.',
+ 'not_response_object' => 'The requested method didn\'t return an XML_RPC_Response object.',
);
@@ -220,7 +238,7 @@ function XML_RPC_se($parser_resource, $name, $attrs)
break;
case 'NAME':
- $XML_RPC_xh[$parser]['st'] .= "'";
+ $XML_RPC_xh[$parser]['st'] .= '"';
$XML_RPC_xh[$parser]['ac'] = '';
break;
@@ -303,7 +321,7 @@ function XML_RPC_ee($parser_resource, $name)
break;
case 'NAME':
- $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'] . "' => ";
+ $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'] . '" => ';
break;
case 'BOOLEAN':
@@ -328,8 +346,8 @@ function XML_RPC_ee($parser_resource, $name)
// we use double quotes rather than single so backslashification works OK
$XML_RPC_xh[$parser]['st'] .= '"' . $XML_RPC_xh[$parser]['ac'] . '"';
} elseif ($XML_RPC_xh[$parser]['qt'] == 2) {
- $XML_RPC_xh[$parser]['st'] .= "base64_decode('"
- . $XML_RPC_xh[$parser]['ac'] . "')";
+ $XML_RPC_xh[$parser]['st'] .= 'base64_decode("'
+ . $XML_RPC_xh[$parser]['ac'] . '")';
} elseif ($name == 'BOOLEAN') {
$XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
} else {
@@ -384,20 +402,10 @@ function XML_RPC_ee($parser_resource, $name)
break;
case 'METHODNAME':
+ case 'RPCMETHODNAME':
$XML_RPC_xh[$parser]['method'] = ereg_replace("^[\n\r\t ]+", '',
$XML_RPC_xh[$parser]['ac']);
break;
-
- case 'BOOLEAN':
- // special case here: we translate boolean 1 or 0 into PHP
- // constants true or false
- if ($XML_RPC_xh[$parser]['ac'] == '1') {
- $XML_RPC_xh[$parser]['ac'] = 'true';
- } else {
- $XML_RPC_xh[$parser]['ac'] = 'false';
- }
-
- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
}
// if it's a valid type name, set the type
@@ -440,17 +448,16 @@ function XML_RPC_cd($parser_resource, $data)
}
/**
- * Base class
- *
- * This class provides common functions for all of the XML_RPC classes.
+ * The common methods and properties for all of the XML_RPC classes
*
* @category Web Services
* @package XML_RPC
* @author Edd Dumbill <edd@usefulinc.com>
* @author Stig Bakken <stig@php.net>
* @author Martin Jansen <mj@php.net>
- * @copyright 1999-2001 Edd Dumbill
- * @version Release: @package_version@
+ * @author Daniel Convissor <danielc@php.net>
+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
+ * @version Release: 1.3.1
* @link http://pear.php.net/package/XML_RPC
*/
class XML_RPC_Base {
@@ -486,7 +493,7 @@ class XML_RPC_Base {
}
/**
- *
+ * The methods and properties for submitting XML RPC requests
*
* @category Web Services
* @package XML_RPC
@@ -494,8 +501,8 @@ class XML_RPC_Base {
* @author Stig Bakken <stig@php.net>
* @author Martin Jansen <mj@php.net>
* @author Daniel Convissor <danielc@php.net>
- * @copyright 1999-2001 Edd Dumbill
- * @version Release: @package_version@
+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
+ * @version Release: 1.3.1
* @link http://pear.php.net/package/XML_RPC
*/
class XML_RPC_Client extends XML_RPC_Base {
@@ -594,6 +601,12 @@ class XML_RPC_Client extends XML_RPC_Base {
*/
var $debug = 0;
+ /**
+ * The HTTP headers for the current request.
+ * @var string
+ */
+ var $headers = '';
+
/**
* Sets the object's properties
@@ -730,6 +743,12 @@ class XML_RPC_Client extends XML_RPC_Base {
*/
function send($msg, $timeout = 0)
{
+ if (strtolower(get_class($msg)) != 'xml_rpc_message') {
+ $this->errstr = 'send()\'s $msg parameter must be an'
+ . ' XML_RPC_Message object.';
+ $this->raiseError($this->errstr, XML_RPC_ERROR_PROGRAMMING);
+ return 0;
+ }
$msg->debug = $this->debug;
return $this->sendPayloadHTTP10($msg, $this->server, $this->port,
$timeout, $this->username,
@@ -753,6 +772,7 @@ class XML_RPC_Client extends XML_RPC_Base {
* @return object an XML_RPC_Response object. 0 is returned if any
* problems happen.
*
+ * @access protected
* @see XML_RPC_Client::send()
*/
function sendPayloadHTTP10($msg, $server, $port, $timeout = 0,
@@ -808,60 +828,99 @@ class XML_RPC_Client extends XML_RPC_Base {
return 0;
}
+ if ($timeout) {
+ stream_set_timeout($fp, $timeout);
+ }
+
+ // Pre-emptive BC hacks for fools calling sendPayloadHTTP10() directly
+ if ($username != $this->username) {
+ $this->setCredentials($username, $password);
+ }
+
// Only create the payload if it was not created previously
if (empty($msg->payload)) {
$msg->createPayload();
}
+ $this->createHeaders($msg);
- // thanks to Grant Rauscher <grant7@firstworld.net> for this
- $credentials = '';
- if ($username != '') {
- $credentials = 'Authorization: Basic ' .
- base64_encode($username . ':' . $password) . "\r\n";
+ $op = $this->headers . "\r\n\r\n";
+ $op .= $msg->payload;
+
+ if (!fputs($fp, $op, strlen($op))) {
+ $this->errstr = 'Write error';
+ return 0;
}
+ $resp = $msg->parseResponseFile($fp);
+
+ $meta = stream_get_meta_data($fp);
+ if ($meta['timed_out']) {
+ fclose($fp);
+ $this->errstr = 'RPC server did not send response before timeout.';
+ $this->raiseError($this->errstr, XML_RPC_ERROR_CONNECTION_FAILED);
+ return 0;
+ }
+
+ fclose($fp);
+ return $resp;
+ }
+ /**
+ * Determines the HTTP headers and puts it in the $headers property
+ *
+ * @param object $msg the XML_RPC_Message object
+ *
+ * @return boolean TRUE if okay, FALSE if the message payload isn't set.
+ *
+ * @access protected
+ */
+ function createHeaders($msg)
+ {
+ if (empty($msg->payload)) {
+ return false;
+ }
if ($this->proxy) {
- $op = 'POST ' . $this->protocol . $server;
+ $this->headers = 'POST ' . $this->protocol . $this->server;
if ($this->proxy_port) {
- $op .= ':' . $this->port;
+ $this->headers .= ':' . $this->port;
}
} else {
- $op = 'POST ';
+ $this->headers = 'POST ';
}
-
- $op .= $this->path. " HTTP/1.0\r\n" .
- "User-Agent: PEAR XML_RPC\r\n" .
- 'Host: ' . $server . "\r\n";
- if ($this->proxy && $this->proxy_user != '') {
- $op .= 'Proxy-Authorization: Basic ' .
- base64_encode($this->proxy_user . ':' . $this->proxy_pass) .
- "\r\n";
+ $this->headers .= $this->path. " HTTP/1.0\r\n";
+
+ $this->headers .= "User-Agent: PEAR XML_RPC\r\n";
+ $this->headers .= 'Host: ' . $this->server . "\r\n";
+
+ if ($this->proxy && $this->proxy_user) {
+ $this->headers .= 'Proxy-Authorization: Basic '
+ . base64_encode("$this->proxy_user:$this->proxy_pass")
+ . "\r\n";
}
- $op .= $credentials .
- "Content-Type: text/xml\r\n" .
- 'Content-Length: ' . strlen($msg->payload) . "\r\n\r\n" .
- $msg->payload;
- if (!fputs($fp, $op, strlen($op))) {
- $this->errstr = 'Write error';
- return 0;
+ // thanks to Grant Rauscher <grant7@firstworld.net> for this
+ if ($this->username) {
+ $this->headers .= 'Authorization: Basic '
+ . base64_encode("$this->username:$this->password")
+ . "\r\n";
}
- $resp = $msg->parseResponseFile($fp);
- fclose($fp);
- return $resp;
+
+ $this->headers .= "Content-Type: text/xml\r\n";
+ $this->headers .= 'Content-Length: ' . strlen($msg->payload);
+ return true;
}
}
/**
- *
+ * The methods and properties for interpreting responses to XML RPC requests
*
* @category Web Services
* @package XML_RPC
* @author Edd Dumbill <edd@usefulinc.com>
* @author Stig Bakken <stig@php.net>
* @author Martin Jansen <mj@php.net>
- * @copyright 1999-2001 Edd Dumbill
- * @version Release: @package_version@
+ * @author Daniel Convissor <danielc@php.net>
+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
+ * @version Release: 1.3.1
* @link http://pear.php.net/package/XML_RPC
*/
class XML_RPC_Response extends XML_RPC_Base
@@ -943,7 +1002,7 @@ class XML_RPC_Response extends XML_RPC_Base
}
/**
- *
+ * The methods and properties for composing XML RPC messages
*
* @category Web Services
* @package XML_RPC
@@ -951,8 +1010,8 @@ class XML_RPC_Response extends XML_RPC_Base
* @author Stig Bakken <stig@php.net>
* @author Martin Jansen <mj@php.net>
* @author Daniel Convissor <danielc@php.net>
- * @copyright 1999-2001 Edd Dumbill
- * @version Release: @package_version@
+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
+ * @version Release: 1.3.1
* @link http://pear.php.net/package/XML_RPC
*/
class XML_RPC_Message extends XML_RPC_Base
@@ -1082,11 +1141,27 @@ class XML_RPC_Message extends XML_RPC_Base
}
/**
- * @return void
+ * Obtains an XML_RPC_Value object for the given parameter
+ *
+ * @param int $i the index number of the parameter to obtain
+ *
+ * @return object the XML_RPC_Value object.
+ * If the parameter doesn't exist, an XML_RPC_Response object.
+ *
+ * @since Returns XML_RPC_Response object on error since Release 1.3.0
*/
function getParam($i)
{
- return $this->params[$i];
+ global $XML_RPC_err, $XML_RPC_str;
+
+ if (isset($this->params[$i])) {
+ return $this->params[$i];
+ } else {
+ $this->raiseError('The submitted request did not contain this parameter',
+ XML_RPC_ERROR_INCORRECT_PARAMS);
+ return new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'],
+ $XML_RPC_str['incorrect_params']);
+ }
}
/**
@@ -1191,10 +1266,12 @@ class XML_RPC_Message extends XML_RPC_Base
print "\n---END---\n</PRE>";
}
- // see if we got an HTTP 200 OK, else bomb
- // but only do this if we're using the HTTP protocol.
+ // See if response is a 200 or a 100 then a 200, else raise error.
+ // But only do this if we're using the HTTP protocol.
if (ereg('^HTTP', $data) &&
- !ereg('^HTTP/[0-9\.]+ 200 ', $data)) {
+ !ereg('^HTTP/[0-9\.]+ 200 ', $data) &&
+ !preg_match('@^HTTP/[0-9\.]+ 10[0-9]([A-Za-z ]+)?[\r\n]+HTTP/[0-9\.]+ 200@', $data))
+ {
$errstr = substr($data, 0, strpos($data, "\n") - 1);
error_log('HTTP error, got response: ' . $errstr);
$r = new XML_RPC_Response(0, $XML_RPC_err['http_error'],
@@ -1206,7 +1283,7 @@ class XML_RPC_Message extends XML_RPC_Base
// gotta get rid of headers here
- if ((!$hdrfnd) && ($brpos = strpos($data,"\r\n\r\n"))) {
+ if (!$hdrfnd && ($brpos = strpos($data,"\r\n\r\n"))) {
$XML_RPC_xh[$parser]['ha'] = substr($data, 0, $brpos);
$data = substr($data, $brpos + 4);
$hdrfnd = 1;
@@ -1221,7 +1298,7 @@ class XML_RPC_Message extends XML_RPC_Base
if (!xml_parse($parser_resource, $data, sizeof($data))) {
// thanks to Peter Kocks <peter.kocks@baygate.com>
- if ((xml_get_current_line_number($parser_resource)) == 1) {
+ if (xml_get_current_line_number($parser_resource) == 1) {
$errstr = 'XML error at line 1, check URL';
} else {
$errstr = sprintf('XML error: %s at line %d',
@@ -1263,15 +1340,16 @@ class XML_RPC_Message extends XML_RPC_Base
}
/**
- *
+ * The methods and properties that represent data in XML RPC format
*
* @category Web Services
* @package XML_RPC
* @author Edd Dumbill <edd@usefulinc.com>
* @author Stig Bakken <stig@php.net>
* @author Martin Jansen <mj@php.net>
- * @copyright 1999-2001 Edd Dumbill
- * @version Release: @package_version@
+ * @author Daniel Convissor <danielc@php.net>
+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
+ * @version Release: 1.3.1
* @link http://pear.php.net/package/XML_RPC
*/
class XML_RPC_Value extends XML_RPC_Base
@@ -1387,11 +1465,11 @@ class XML_RPC_Value extends XML_RPC_Base
function dump($ar)
{
reset($ar);
- while (list($key, $val) = each($ar)) {
- echo "$key => $val<br>";
+ foreach ($ar as $key => $val) {
+ echo "$key => $val<br />";
if ($key == 'array') {
- while (list($key2, $val2) = each($val)) {
- echo "-- $key2 => $val2<br>";
+ foreach ($val as $key2 => $val2) {
+ echo "-- $key2 => $val2<br />";
}
}
}
@@ -1434,7 +1512,7 @@ class XML_RPC_Value extends XML_RPC_Base
// struct
$rs .= "<struct>\n";
reset($val);
- while (list($key2, $val2) = each($val)) {
+ foreach ($val as $key2 => $val2) {
$rs .= "<member><name>${key2}</name>\n";
$rs .= $this->serializeval($val2);
$rs .= "</member>\n";
@@ -1460,7 +1538,6 @@ class XML_RPC_Value extends XML_RPC_Base
$rs .= "<${typ}>" . ($val ? '1' : '0') . "</${typ}>";
break;
case $XML_RPC_String:
- if(is_array($val)) $val = 'array';
$rs .= "<${typ}>" . htmlspecialchars($val). "</${typ}>";
break;
default:
@@ -1520,12 +1597,13 @@ class XML_RPC_Value extends XML_RPC_Base
/**
* @return mixed the current value
*/
- function getval() {
+ function getval()
+ {
// UNSTABLE
global $XML_RPC_BOOLEAN, $XML_RPC_Base64;
reset($this->me);
- list($a, $b) = each($this->me);
+ $b = current($this->me);
// contributed by I Sofer, 2001-03-24
// add support for nested arrays to scalarval
@@ -1560,8 +1638,7 @@ class XML_RPC_Value extends XML_RPC_Base
{
global $XML_RPC_Boolean, $XML_RPC_Base64;
reset($this->me);
- list($a, $b) = each($this->me);
- return $b;
+ return current($this->me);
}
/**
@@ -1571,7 +1648,7 @@ class XML_RPC_Value extends XML_RPC_Base
{
global $XML_RPC_I4, $XML_RPC_Int;
reset($this->me);
- list($a, $b) = each($this->me);
+ $a = key($this->me);
if ($a == $XML_RPC_I4) {
$a = $XML_RPC_Int;
}
@@ -1595,6 +1672,21 @@ class XML_RPC_Value extends XML_RPC_Base
list($a, $b) = each($this->me);
return sizeof($b);
}
+
+ /**
+ * Determines if the item submitted is an XML_RPC_Value object
+ *
+ * @param mixed $val the variable to be evaluated
+ *
+ * @return bool TRUE if the item is an XML_RPC_Value object
+ *
+ * @static
+ * @since Method available since Release 1.3.0
+ */
+ function isValue($val)
+ {
+ return (strtolower(get_class($val)) == 'xml_rpc_value');
+ }
}
/**
@@ -1610,7 +1702,8 @@ class XML_RPC_Value extends XML_RPC_Base
*
* @return string the formatted date
*/
-function XML_RPC_iso8601_encode($timet, $utc = 0) {
+function XML_RPC_iso8601_encode($timet, $utc = 0)
+{
if (!$utc) {
$t = strftime('%Y%m%dT%H:%M:%S', $timet);
} else {
@@ -1638,7 +1731,8 @@ function XML_RPC_iso8601_encode($timet, $utc = 0) {
*
* @return int the unix timestamp of the date submitted
*/
-function XML_RPC_iso8601_decode($idate, $utc = 0) {
+function XML_RPC_iso8601_decode($idate, $utc = 0)
+{
$t = 0;
if (ereg('([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})', $idate, $regs)) {
if ($utc) {
@@ -1651,12 +1745,11 @@ function XML_RPC_iso8601_decode($idate, $utc = 0) {
}
/**
- * Takes a message in PHP XML_RPC object format and translates it into
- * native PHP types
+ * Converts an XML_RPC_Value object into native PHP types
*
- * @return mixed
+ * @param object $XML_RPC_val the XML_RPC_Value object to decode
*
- * @author Dan Libby <dan@libby.com>
+ * @return mixed the PHP values
*/
function XML_RPC_decode($XML_RPC_val)
{
@@ -1684,17 +1777,16 @@ function XML_RPC_decode($XML_RPC_val)
}
/**
- * Takes native php types and encodes them into XML_RPC PHP object format
- *
- * Feature creep -- could support more types via optional type argument.
+ * Converts native PHP types into an XML_RPC_Value object
*
- * @return string
+ * @param mixed $php_val the PHP value or variable you want encoded
*
- * @author Dan Libby <dan@libby.com>
+ * @return object the XML_RPC_Value object
*/
-function XML_RPC_encode($php_val) {
+function XML_RPC_encode($php_val)
+{
global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double, $XML_RPC_String,
- $XML_RPC_Array, $XML_RPC_Struct;
+ $XML_RPC_Array, $XML_RPC_Struct;
$type = gettype($php_val);
$XML_RPC_val = new XML_RPC_Value;
diff --git a/etc/inc/xmlrpc_server.inc b/etc/inc/xmlrpc_server.inc
index 89ebcae..f7c398f 100644
--- a/etc/inc/xmlrpc_server.inc
+++ b/etc/inc/xmlrpc_server.inc
@@ -1,9 +1,10 @@
<?php
+
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/* $Id$ */
/**
- * PHP implementation of the XML-RPC protocol
+ * Server commands for our PHP implementation of the XML-RPC protocol
*
* This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
* It has support for HTTP transport, proxies and authentication.
@@ -30,7 +31,8 @@
* @author Edd Dumbill <edd@usefulinc.com>
* @author Stig Bakken <stig@php.net>
* @author Martin Jansen <mj@php.net>
- * @copyright 1999-2001 Edd Dumbill
+ * @author Daniel Convissor <danielc@php.net>
+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
* @version CVS: $Id$
* @link http://pear.php.net/package/XML_RPC
*/
@@ -39,11 +41,12 @@
/**
* Pull in the XML_RPC class
*/
-require_once 'xmlrpc_client.inc';
+require_once 'XML/RPC.php';
/**
- * listMethods: either a string, or nothing
+ * signature for system.listMethods: return = array,
+ * parameters = a string or nothing
* @global array $GLOBALS['XML_RPC_Server_listMethods_sig']
*/
$GLOBALS['XML_RPC_Server_listMethods_sig'] = array(
@@ -54,12 +57,15 @@ $GLOBALS['XML_RPC_Server_listMethods_sig'] = array(
);
/**
+ * docstring for system.listMethods
* @global string $GLOBALS['XML_RPC_Server_listMethods_doc']
*/
$GLOBALS['XML_RPC_Server_listMethods_doc'] = 'This method lists all the'
. ' methods that the XML-RPC server knows how to dispatch';
/**
+ * signature for system.methodSignature: return = array,
+ * parameters = string
* @global array $GLOBALS['XML_RPC_Server_methodSignature_sig']
*/
$GLOBALS['XML_RPC_Server_methodSignature_sig'] = array(
@@ -69,6 +75,7 @@ $GLOBALS['XML_RPC_Server_methodSignature_sig'] = array(
);
/**
+ * docstring for system.methodSignature
* @global string $GLOBALS['XML_RPC_Server_methodSignature_doc']
*/
$GLOBALS['XML_RPC_Server_methodSignature_doc'] = 'Returns an array of known'
@@ -77,6 +84,8 @@ $GLOBALS['XML_RPC_Server_methodSignature_doc'] = 'Returns an array of known'
. ' array to detect missing signature)';
/**
+ * signature for system.methodHelp: return = string,
+ * parameters = string
* @global array $GLOBALS['XML_RPC_Server_methodHelp_sig']
*/
$GLOBALS['XML_RPC_Server_methodHelp_sig'] = array(
@@ -86,12 +95,14 @@ $GLOBALS['XML_RPC_Server_methodHelp_sig'] = array(
);
/**
+ * docstring for methodHelp
* @global string $GLOBALS['XML_RPC_Server_methodHelp_doc']
*/
$GLOBALS['XML_RPC_Server_methodHelp_doc'] = 'Returns help text if defined'
. ' for the method passed, otherwise returns an empty string';
/**
+ * dispatch map for the automatically declared XML-RPC methods.
* @global array $GLOBALS['XML_RPC_Server_dmap']
*/
$GLOBALS['XML_RPC_Server_dmap'] = array(
@@ -128,13 +139,11 @@ function XML_RPC_Server_listMethods($server, $m)
global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
$v = new XML_RPC_Value();
- $dmap = $server->dmap;
$outAr = array();
- for (reset($dmap); list($key, $val) = each($dmap); ) {
+ foreach ($server->dmap as $key => $val) {
$outAr[] = new XML_RPC_Value($key, 'string');
}
- $dmap = $XML_RPC_Server_dmap;
- for (reset($dmap); list($key, $val) = each($dmap); ) {
+ foreach ($XML_RPC_Server_dmap as $key => $val) {
$outAr[] = new XML_RPC_Value($key, 'string');
}
$v->addArray($outAr);
@@ -232,24 +241,94 @@ function XML_RPC_Server_debugmsg($m)
/**
+ * A server for receiving and replying to XML RPC requests
*
+ * <code>
+ * $server = new XML_RPC_Server(
+ * array(
+ * 'isan8' =>
+ * array(
+ * 'function' => 'is_8',
+ * 'signature' =>
+ * array(
+ * array('boolean', 'int'),
+ * array('boolean', 'int', 'boolean'),
+ * array('boolean', 'string'),
+ * array('boolean', 'string', 'boolean'),
+ * ),
+ * 'docstring' => 'Is the value an 8?'
+ * ),
+ * ),
+ * 1,
+ * 0
+ * );
+ * </code>
*
* @category Web Services
* @package XML_RPC
* @author Edd Dumbill <edd@usefulinc.com>
* @author Stig Bakken <stig@php.net>
* @author Martin Jansen <mj@php.net>
- * @copyright 1999-2001 Edd Dumbill
- * @version Release: @package_version@
+ * @author Daniel Convissor <danielc@php.net>
+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
+ * @version Release: 1.3.1
* @link http://pear.php.net/package/XML_RPC
*/
class XML_RPC_Server
{
+ /**
+ * The dispatch map, listing the methods this server provides.
+ * @var array
+ */
var $dmap = array();
+
+ /**
+ * The present response's encoding
+ * @var string
+ * @see XML_RPC_Message::getEncoding()
+ */
var $encoding = '';
+
+ /**
+ * Debug mode (0 = off, 1 = on)
+ * @var integer
+ */
var $debug = 0;
/**
+ * The response's HTTP headers
+ * @var string
+ */
+ var $server_headers = '';
+
+ /**
+ * The response's XML payload
+ * @var string
+ */
+ var $server_payload = '';
+
+
+ /**
+ * Constructor for the XML_RPC_Server class
+ *
+ * @param array $dispMap the dispatch map. An associative array
+ * explaining each function. The keys of the main
+ * array are the procedure names used by the
+ * clients. The value is another associative array
+ * that contains up to three elements:
+ * + The 'function' element's value is the name
+ * of the function or method that gets called.
+ * To define a class' method: 'class::method'.
+ * + The 'signature' element (optional) is an
+ * array describing the return values and
+ * parameters
+ * + The 'docstring' element (optional) is a
+ * string describing what the method does
+ * @param int $serviceNow should the HTTP response be sent now?
+ * (1 = yes, 0 = no)
+ * @param int $debug should debug output be displayed?
+ * (1 = yes, 0 = no)
+ *
* @return void
*/
function XML_RPC_Server($dispMap, $serviceNow = 1, $debug = 0)
@@ -262,14 +341,13 @@ class XML_RPC_Server
$this->debug = 0;
}
- // dispMap is a despatch array of methods
- // mapped to function names and signatures
- // if a method
- // doesn't appear in the map then an unknown
- // method error is generated
$this->dmap = $dispMap;
+
if ($serviceNow) {
$this->service();
+ } else {
+ $this->createServerPayload();
+ $this->createServerHeaders();
}
}
@@ -296,25 +374,60 @@ class XML_RPC_Server
}
/**
- * Print out the result
+ * Sends the response
*
* The encoding and content-type are determined by
* XML_RPC_Message::getEncoding()
*
* @return void
*
- * @see XML_RPC_Message::getEncoding()
+ * @uses XML_RPC_Server::createServerPayload(),
+ * XML_RPC_Server::createServerHeaders()
*/
function service()
{
+ $this->createServerPayload();
+ $this->createServerHeaders();
+ header($this->server_headers);
+ print $this->server_payload;
+ }
+
+ /**
+ * Generates the payload and puts it in the $server_payload property
+ *
+ * @return void
+ *
+ * @uses XML_RPC_Server::parseRequest(), XML_RPC_Server::$encoding,
+ * XML_RPC_Response::serialize(), XML_RPC_Server::serializeDebug()
+ */
+ function createServerPayload()
+ {
$r = $this->parseRequest();
- $payload = '<?xml version="1.0" encoding="'
- . $this->encoding . '"?>' . "\n"
- . $this->serializeDebug()
- . $r->serialize();
- header('Content-Length: ' . strlen($payload));
- header('Content-Type: text/xml; charset=' . $this->encoding);
- print $payload;
+ $this->server_payload = '<?xml version="1.0" encoding="'
+ . $this->encoding . '"?>' . "\n"
+ . $this->serializeDebug()
+ . $r->serialize();
+ }
+
+ /**
+ * Determines the HTTP headers and puts them in the $server_headers
+ * property
+ *
+ * @return boolean TRUE if okay, FALSE if $server_payload isn't set.
+ *
+ * @uses XML_RPC_Server::createServerPayload(),
+ * XML_RPC_Server::$server_headers
+ */
+ function createServerHeaders()
+ {
+ if (!$this->server_payload) {
+ return false;
+ }
+ $this->server_headers = 'Content-Length: '
+ . strlen($this->server_payload) . "\r\n"
+ . 'Content-Type: text/xml;'
+ . ' charset=' . $this->encoding;
+ return true;
}
/**
@@ -336,7 +449,7 @@ class XML_RPC_Server
$pt = $p->kindOf();
}
// $n+1 as first type of sig is return type
- if ($pt != strtolower($cursig[$n+1])) {
+ if ($pt != $cursig[$n+1]) {
$itsOK = 0;
$pno = $n+1;
$wanted = $cursig[$n+1];
@@ -349,11 +462,30 @@ class XML_RPC_Server
}
}
}
- return array(0, "Wanted ${wanted}, got ${got} at param ${pno})");
+ if (isset($wanted)) {
+ return array(0, "Wanted ${wanted}, got ${got} at param ${pno}");
+ } else {
+ $allowed = array();
+ foreach ($sig as $val) {
+ end($val);
+ $allowed[] = key($val);
+ }
+ $allowed = array_unique($allowed);
+ $last = count($allowed) - 1;
+ if ($last > 0) {
+ $allowed[$last] = 'or ' . $allowed[$last];
+ }
+ return array(0,
+ 'Signature permits ' . implode(', ', $allowed)
+ . ' parameters but the request had '
+ . $in->getNumParams());
+ }
}
/**
* @return object a new XML_RPC_Response object
+ *
+ * @uses XML_RPC_Message::getEncoding(), XML_RPC_Server::$encoding
*/
function parseRequest($data = '')
{
@@ -428,13 +560,17 @@ class XML_RPC_Server
$sr = $this->verifySignature($m,
$dmap[$methName]['signature'] );
}
- if ( (!isset($dmap[$methName]['signature'])) || $sr[0]) {
+ if (!isset($dmap[$methName]['signature']) || $sr[0]) {
// if no signature or correct signature
if ($sysCall) {
$r = call_user_func($dmap[$methName]['function'], $this, $m);
} else {
$r = call_user_func($dmap[$methName]['function'], $m);
}
+ if (!is_a($r, 'XML_RPC_Response')) {
+ $r = new XML_RPC_Response(0, $XML_RPC_err['not_response_object'],
+ $XML_RPC_str['not_response_object']);
+ }
} else {
$r = new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'],
$XML_RPC_str['incorrect_params']
@@ -456,7 +592,8 @@ class XML_RPC_Server
*
* Useful for debugging.
*/
- function echoInput() {
+ function echoInput()
+ {
global $HTTP_RAW_POST_DATA;
$r = new XML_RPC_Response(0);
OpenPOWER on IntegriCloud