| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 | <?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;    }}
 |