You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
6.8 KiB
225 lines
6.8 KiB
<?php |
|
|
|
/** |
|
* IXR_Server |
|
* |
|
* @package IXR |
|
* @since 1.5.0 |
|
*/ |
|
class IXR_Server |
|
{ |
|
var $data; |
|
var $callbacks = array(); |
|
var $message; |
|
var $capabilities; |
|
|
|
/** |
|
* PHP5 constructor. |
|
*/ |
|
function __construct( $callbacks = false, $data = false, $wait = false ) |
|
{ |
|
$this->setCapabilities(); |
|
if ($callbacks) { |
|
$this->callbacks = $callbacks; |
|
} |
|
$this->setCallbacks(); |
|
if (!$wait) { |
|
$this->serve($data); |
|
} |
|
} |
|
|
|
/** |
|
* PHP4 constructor. |
|
*/ |
|
public function IXR_Server( $callbacks = false, $data = false, $wait = false ) { |
|
self::__construct( $callbacks, $data, $wait ); |
|
} |
|
|
|
function serve($data = false) |
|
{ |
|
if (!$data) { |
|
if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] !== 'POST') { |
|
if ( function_exists( 'status_header' ) ) { |
|
status_header( 405 ); // WP #20986 |
|
header( 'Allow: POST' ); |
|
} |
|
header('Content-Type: text/plain'); // merged from WP #9093 |
|
die('XML-RPC server accepts POST requests only.'); |
|
} |
|
|
|
global $HTTP_RAW_POST_DATA; |
|
if (empty($HTTP_RAW_POST_DATA)) { |
|
// workaround for a bug in PHP 5.2.2 - http://bugs.php.net/bug.php?id=41293 |
|
$data = file_get_contents('php://input'); |
|
} else { |
|
$data =& $HTTP_RAW_POST_DATA; |
|
} |
|
} |
|
$this->message = new IXR_Message($data); |
|
if (!$this->message->parse()) { |
|
$this->error(-32700, 'parse error. not well formed'); |
|
} |
|
if ($this->message->messageType != 'methodCall') { |
|
$this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall'); |
|
} |
|
$result = $this->call($this->message->methodName, $this->message->params); |
|
|
|
// Is the result an error? |
|
if (is_a($result, 'IXR_Error')) { |
|
$this->error($result); |
|
} |
|
|
|
// Encode the result |
|
$r = new IXR_Value($result); |
|
$resultxml = $r->getXml(); |
|
|
|
// Create the XML |
|
$xml = <<<EOD |
|
<methodResponse> |
|
<params> |
|
<param> |
|
<value> |
|
$resultxml |
|
</value> |
|
</param> |
|
</params> |
|
</methodResponse> |
|
|
|
EOD; |
|
// Send it |
|
$this->output($xml); |
|
} |
|
|
|
function call($methodname, $args) |
|
{ |
|
if (!$this->hasMethod($methodname)) { |
|
return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.'); |
|
} |
|
$method = $this->callbacks[$methodname]; |
|
|
|
// Perform the callback and send the response |
|
if (count($args) == 1) { |
|
// If only one parameter just send that instead of the whole array |
|
$args = $args[0]; |
|
} |
|
|
|
// Are we dealing with a function or a method? |
|
if (is_string($method) && substr($method, 0, 5) == 'this:') { |
|
// It's a class method - check it exists |
|
$method = substr($method, 5); |
|
if (!method_exists($this, $method)) { |
|
return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.'); |
|
} |
|
|
|
//Call the method |
|
$result = $this->$method($args); |
|
} else { |
|
// It's a function - does it exist? |
|
if (is_array($method)) { |
|
if (!is_callable(array($method[0], $method[1]))) { |
|
return new IXR_Error(-32601, 'server error. requested object method "'.$method[1].'" does not exist.'); |
|
} |
|
} else if (!function_exists($method)) { |
|
return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.'); |
|
} |
|
|
|
// Call the function |
|
$result = call_user_func($method, $args); |
|
} |
|
return $result; |
|
} |
|
|
|
function error($error, $message = false) |
|
{ |
|
// Accepts either an error object or an error code and message |
|
if ($message && !is_object($error)) { |
|
$error = new IXR_Error($error, $message); |
|
} |
|
$this->output($error->getXml()); |
|
} |
|
|
|
function output($xml) |
|
{ |
|
$charset = function_exists('get_option') ? get_option('blog_charset') : ''; |
|
if ($charset) |
|
$xml = '<?xml version="1.0" encoding="'.$charset.'"?>'."\n".$xml; |
|
else |
|
$xml = '<?xml version="1.0"?>'."\n".$xml; |
|
$length = strlen($xml); |
|
header('Connection: close'); |
|
if ($charset) |
|
header('Content-Type: text/xml; charset='.$charset); |
|
else |
|
header('Content-Type: text/xml'); |
|
header('Date: '.gmdate('r')); |
|
echo $xml; |
|
exit; |
|
} |
|
|
|
function hasMethod($method) |
|
{ |
|
return in_array($method, array_keys($this->callbacks)); |
|
} |
|
|
|
function setCapabilities() |
|
{ |
|
// Initialises capabilities array |
|
$this->capabilities = array( |
|
'xmlrpc' => array( |
|
'specUrl' => 'http://www.xmlrpc.com/spec', |
|
'specVersion' => 1 |
|
), |
|
'faults_interop' => array( |
|
'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php', |
|
'specVersion' => 20010516 |
|
), |
|
'system.multicall' => array( |
|
'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208', |
|
'specVersion' => 1 |
|
), |
|
); |
|
} |
|
|
|
function getCapabilities($args) |
|
{ |
|
return $this->capabilities; |
|
} |
|
|
|
function setCallbacks() |
|
{ |
|
$this->callbacks['system.getCapabilities'] = 'this:getCapabilities'; |
|
$this->callbacks['system.listMethods'] = 'this:listMethods'; |
|
$this->callbacks['system.multicall'] = 'this:multiCall'; |
|
} |
|
|
|
function listMethods($args) |
|
{ |
|
// Returns a list of methods - uses array_reverse to ensure user defined |
|
// methods are listed before server defined methods |
|
return array_reverse(array_keys($this->callbacks)); |
|
} |
|
|
|
function multiCall($methodcalls) |
|
{ |
|
// See http://www.xmlrpc.com/discuss/msgReader$1208 |
|
$return = array(); |
|
foreach ($methodcalls as $call) { |
|
$method = $call['methodName']; |
|
$params = $call['params']; |
|
if ($method == 'system.multicall') { |
|
$result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden'); |
|
} else { |
|
$result = $this->call($method, $params); |
|
} |
|
if (is_a($result, 'IXR_Error')) { |
|
$return[] = array( |
|
'faultCode' => $result->code, |
|
'faultString' => $result->message |
|
); |
|
} else { |
|
$return[] = array($result); |
|
} |
|
} |
|
return $return; |
|
} |
|
}
|
|
|