12 var $callbacks = array();
19 function __construct( $callbacks = false, $data = false, $wait = false )
21 $this->setCapabilities();
23 $this->callbacks = $callbacks;
25 $this->setCallbacks();
34 public function IXR_Server( $callbacks = false, $data = false, $wait = false ) {
35 self::__construct( $callbacks, $data, $wait );
38 function serve($data = false)
41 if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] !== 'POST') {
42 if ( function_exists( 'status_header' ) ) {
43 status_header( 405 ); // WP #20986
44 header( 'Allow: POST' );
46 header('Content-Type: text/plain'); // merged from WP #9093
47 die('XML-RPC server accepts POST requests only.');
50 global $HTTP_RAW_POST_DATA;
51 if (empty($HTTP_RAW_POST_DATA)) {
52 // workaround for a bug in PHP 5.2.2 - http://bugs.php.net/bug.php?id=41293
53 $data = file_get_contents('php://input');
55 $data =& $HTTP_RAW_POST_DATA;
58 $this->message = new IXR_Message($data);
59 if (!$this->message->parse()) {
60 $this->error(-32700, 'parse error. not well formed');
62 if ($this->message->messageType != 'methodCall') {
63 $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall');
65 $result = $this->call($this->message->methodName, $this->message->params);
67 // Is the result an error?
68 if (is_a($result, 'IXR_Error')) {
69 $this->error($result);
73 $r = new IXR_Value($result);
74 $resultxml = $r->getXml();
93 function call($methodname, $args)
95 if (!$this->hasMethod($methodname)) {
96 return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.');
98 $method = $this->callbacks[$methodname];
100 // Perform the callback and send the response
101 if (count($args) == 1) {
102 // If only one parameter just send that instead of the whole array
106 // Are we dealing with a function or a method?
107 if (is_string($method) && substr($method, 0, 5) == 'this:') {
108 // It's a class method - check it exists
109 $method = substr($method, 5);
110 if (!method_exists($this, $method)) {
111 return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.');
115 $result = $this->$method($args);
117 // It's a function - does it exist?
118 if (is_array($method)) {
119 if (!is_callable(array($method[0], $method[1]))) {
120 return new IXR_Error(-32601, 'server error. requested object method "'.$method[1].'" does not exist.');
122 } else if (!function_exists($method)) {
123 return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.');
127 $result = call_user_func($method, $args);
132 function error($error, $message = false)
134 // Accepts either an error object or an error code and message
135 if ($message && !is_object($error)) {
136 $error = new IXR_Error($error, $message);
138 $this->output($error->getXml());
141 function output($xml)
143 $charset = function_exists('get_option') ? get_option('blog_charset') : '';
145 $xml = '<?xml version="1.0" encoding="'.$charset.'"?>'."\n".$xml;
147 $xml = '<?xml version="1.0"?>'."\n".$xml;
148 $length = strlen($xml);
149 header('Connection: close');
151 header('Content-Type: text/xml; charset='.$charset);
153 header('Content-Type: text/xml');
154 header('Date: '.date('r'));
159 function hasMethod($method)
161 return in_array($method, array_keys($this->callbacks));
164 function setCapabilities()
166 // Initialises capabilities array
167 $this->capabilities = array(
169 'specUrl' => 'http://www.xmlrpc.com/spec',
172 'faults_interop' => array(
173 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php',
174 'specVersion' => 20010516
176 'system.multicall' => array(
177 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208',
183 function getCapabilities($args)
185 return $this->capabilities;
188 function setCallbacks()
190 $this->callbacks['system.getCapabilities'] = 'this:getCapabilities';
191 $this->callbacks['system.listMethods'] = 'this:listMethods';
192 $this->callbacks['system.multicall'] = 'this:multiCall';
195 function listMethods($args)
197 // Returns a list of methods - uses array_reverse to ensure user defined
198 // methods are listed before server defined methods
199 return array_reverse(array_keys($this->callbacks));
202 function multiCall($methodcalls)
204 // See http://www.xmlrpc.com/discuss/msgReader$1208
206 foreach ($methodcalls as $call) {
207 $method = $call['methodName'];
208 $params = $call['params'];
209 if ($method == 'system.multicall') {
210 $result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden');
212 $result = $this->call($method, $params);
214 if (is_a($result, 'IXR_Error')) {
216 'faultCode' => $result->code,
217 'faultString' => $result->message
220 $return[] = array($result);