ru-se.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-IXR-server.php (6670B)


      1 <?php
      2 
      3 /**
      4  * IXR_Server
      5  *
      6  * @package IXR
      7  * @since 1.5.0
      8  */
      9 class IXR_Server
     10 {
     11     var $data;
     12     var $callbacks = array();
     13     var $message;
     14     var $capabilities;
     15 
     16 	/**
     17 	 * PHP5 constructor.
     18 	 */
     19     function __construct( $callbacks = false, $data = false, $wait = false )
     20     {
     21         $this->setCapabilities();
     22         if ($callbacks) {
     23             $this->callbacks = $callbacks;
     24         }
     25         $this->setCallbacks();
     26         if (!$wait) {
     27             $this->serve($data);
     28         }
     29     }
     30 
     31 	/**
     32 	 * PHP4 constructor.
     33 	 */
     34 	public function IXR_Server( $callbacks = false, $data = false, $wait = false ) {
     35 		self::__construct( $callbacks, $data, $wait );
     36 	}
     37 
     38     function serve($data = false)
     39     {
     40         if (!$data) {
     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' );
     45                 }
     46                 header('Content-Type: text/plain'); // merged from WP #9093
     47                 die('XML-RPC server accepts POST requests only.');
     48             }
     49 
     50             $data = file_get_contents('php://input');
     51         }
     52         $this->message = new IXR_Message($data);
     53         if (!$this->message->parse()) {
     54             $this->error(-32700, 'parse error. not well formed');
     55         }
     56         if ($this->message->messageType != 'methodCall') {
     57             $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall');
     58         }
     59         $result = $this->call($this->message->methodName, $this->message->params);
     60 
     61         // Is the result an error?
     62         if (is_a($result, 'IXR_Error')) {
     63             $this->error($result);
     64         }
     65 
     66         // Encode the result
     67         $r = new IXR_Value($result);
     68         $resultxml = $r->getXml();
     69 
     70         // Create the XML
     71         $xml = <<<EOD
     72 <methodResponse>
     73   <params>
     74     <param>
     75       <value>
     76       $resultxml
     77       </value>
     78     </param>
     79   </params>
     80 </methodResponse>
     81 
     82 EOD;
     83       // Send it
     84       $this->output($xml);
     85     }
     86 
     87     function call($methodname, $args)
     88     {
     89         if (!$this->hasMethod($methodname)) {
     90             return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.');
     91         }
     92         $method = $this->callbacks[$methodname];
     93 
     94         // Perform the callback and send the response
     95         if (count($args) == 1) {
     96             // If only one parameter just send that instead of the whole array
     97             $args = $args[0];
     98         }
     99 
    100         // Are we dealing with a function or a method?
    101         if (is_string($method) && substr($method, 0, 5) == 'this:') {
    102             // It's a class method - check it exists
    103             $method = substr($method, 5);
    104             if (!method_exists($this, $method)) {
    105                 return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.');
    106             }
    107 
    108             //Call the method
    109             $result = $this->$method($args);
    110         } else {
    111             // It's a function - does it exist?
    112             if (is_array($method)) {
    113                 if (!is_callable(array($method[0], $method[1]))) {
    114                     return new IXR_Error(-32601, 'server error. requested object method "'.$method[1].'" does not exist.');
    115                 }
    116             } else if (!function_exists($method)) {
    117                 return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.');
    118             }
    119 
    120             // Call the function
    121             $result = call_user_func($method, $args);
    122         }
    123         return $result;
    124     }
    125 
    126     function error($error, $message = false)
    127     {
    128         // Accepts either an error object or an error code and message
    129         if ($message && !is_object($error)) {
    130             $error = new IXR_Error($error, $message);
    131         }
    132 
    133         $this->output($error->getXml());
    134     }
    135 
    136     function output($xml)
    137     {
    138         $charset = function_exists('get_option') ? get_option('blog_charset') : '';
    139         if ($charset)
    140             $xml = '<?xml version="1.0" encoding="'.$charset.'"?>'."\n".$xml;
    141         else
    142             $xml = '<?xml version="1.0"?>'."\n".$xml;
    143         $length = strlen($xml);
    144         header('Connection: close');
    145         if ($charset)
    146             header('Content-Type: text/xml; charset='.$charset);
    147         else
    148             header('Content-Type: text/xml');
    149         header('Date: '.gmdate('r'));
    150         echo $xml;
    151         exit;
    152     }
    153 
    154     function hasMethod($method)
    155     {
    156         return in_array($method, array_keys($this->callbacks));
    157     }
    158 
    159     function setCapabilities()
    160     {
    161         // Initialises capabilities array
    162         $this->capabilities = array(
    163             'xmlrpc' => array(
    164                 'specUrl' => 'http://www.xmlrpc.com/spec',
    165                 'specVersion' => 1
    166         ),
    167             'faults_interop' => array(
    168                 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php',
    169                 'specVersion' => 20010516
    170         ),
    171             'system.multicall' => array(
    172                 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208',
    173                 'specVersion' => 1
    174         ),
    175         );
    176     }
    177 
    178     function getCapabilities($args)
    179     {
    180         return $this->capabilities;
    181     }
    182 
    183     function setCallbacks()
    184     {
    185         $this->callbacks['system.getCapabilities'] = 'this:getCapabilities';
    186         $this->callbacks['system.listMethods'] = 'this:listMethods';
    187         $this->callbacks['system.multicall'] = 'this:multiCall';
    188     }
    189 
    190     function listMethods($args)
    191     {
    192         // Returns a list of methods - uses array_reverse to ensure user defined
    193         // methods are listed before server defined methods
    194         return array_reverse(array_keys($this->callbacks));
    195     }
    196 
    197     function multiCall($methodcalls)
    198     {
    199         // See http://www.xmlrpc.com/discuss/msgReader$1208
    200         $return = array();
    201         foreach ($methodcalls as $call) {
    202             $method = $call['methodName'];
    203             $params = $call['params'];
    204             if ($method == 'system.multicall') {
    205                 $result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden');
    206             } else {
    207                 $result = $this->call($method, $params);
    208             }
    209             if (is_a($result, 'IXR_Error')) {
    210                 $return[] = array(
    211                     'faultCode' => $result->code,
    212                     'faultString' => $result->message
    213                 );
    214             } else {
    215                 $return[] = array($result);
    216             }
    217         }
    218         return $return;
    219     }
    220 }