| <?php |
|
|
| |
| |
| |
| |
| |
| |
| class IXR_Server |
| { |
| var $data; |
| var $callbacks = array(); |
| var $message; |
| var $capabilities; |
|
|
| |
| |
| |
| function __construct( $callbacks = false, $data = false, $wait = false ) |
| { |
| $this->setCapabilities(); |
| if ($callbacks) { |
| $this->callbacks = $callbacks; |
| } |
| $this->setCallbacks(); |
| if (!$wait) { |
| $this->serve($data); |
| } |
| } |
|
|
| |
| |
| |
| 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 ); |
| header( 'Allow: POST' ); |
| } |
| header('Content-Type: text/plain'); |
| die('XML-RPC server accepts POST requests only.'); |
| } |
|
|
| $data = file_get_contents('php://input'); |
| } |
| $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); |
|
|
| |
| if (is_a($result, 'IXR_Error')) { |
| $this->error($result); |
| } |
|
|
| |
| $r = new IXR_Value($result); |
| $resultxml = $r->getXml(); |
|
|
| |
| $xml = <<<EOD |
| <methodResponse> |
| <params> |
| <param> |
| <value> |
| $resultxml |
| </value> |
| </param> |
| </params> |
| </methodResponse> |
| |
| EOD; |
| |
| $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]; |
|
|
| |
| if (count($args) == 1) { |
| |
| $args = $args[0]; |
| } |
|
|
| |
| if (is_string($method) && substr($method, 0, 5) == 'this:') { |
| |
| $method = substr($method, 5); |
| if (!method_exists($this, $method)) { |
| return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.'); |
| } |
|
|
| |
| $result = $this->$method($args); |
| } else { |
| |
| 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.'); |
| } |
|
|
| |
| $result = call_user_func($method, $args); |
| } |
| return $result; |
| } |
|
|
| function error($error, $message = false) |
| { |
| |
| 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() |
| { |
| |
| $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) |
| { |
| |
| |
| return array_reverse(array_keys($this->callbacks)); |
| } |
|
|
| function multiCall($methodcalls) |
| { |
| |
| $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; |
| } |
| } |
|
|