[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/includes/ -> xmlrpcs.inc (source)

   1  <?php
   2  // $Id: xmlrpcs.inc,v 1.24.2.4 2010/06/02 12:52:07 goba Exp $
   3  
   4  /**
   5   * The main entry point for XML-RPC requests.
   6   *
   7   * @param $callbacks
   8   *   Array of external XML-RPC method names with the callbacks they map to.
   9   */
  10  function xmlrpc_server($callbacks) {
  11    $xmlrpc_server = new stdClass();
  12    // Define built-in XML-RPC method names
  13    $defaults = array(
  14        'system.multicall' => 'xmlrpc_server_multicall',
  15      array(
  16        'system.methodSignature',
  17        'xmlrpc_server_method_signature',
  18        array('array', 'string'),
  19        'Returns an array describing the return type and required parameters of a method.'
  20      ),
  21      array(
  22        'system.getCapabilities',
  23        'xmlrpc_server_get_capabilities',
  24        array('struct'),
  25        'Returns a struct describing the XML-RPC specifications supported by this server.'
  26      ),
  27      array(
  28        'system.listMethods',
  29        'xmlrpc_server_list_methods',
  30        array('array'),
  31        'Returns an array of available methods on this server.'),
  32      array(
  33        'system.methodHelp',
  34        'xmlrpc_server_method_help',
  35        array('string', 'string'),
  36        'Returns a documentation string for the specified method.')
  37    );
  38    // We build an array of all method names by combining the built-ins
  39    // with those defined by modules implementing the _xmlrpc hook.
  40    // Built-in methods are overridable.
  41    foreach (array_merge($defaults, (array)$callbacks) as $key => $callback) {
  42      // we could check for is_array($callback)
  43      if (is_int($key)) {
  44        $method = $callback[0];
  45        $xmlrpc_server->callbacks[$method] = $callback[1];
  46        $xmlrpc_server->signatures[$method] = $callback[2];
  47        $xmlrpc_server->help[$method] = $callback[3];
  48      }
  49      else {
  50        $xmlrpc_server->callbacks[$key] = $callback;
  51        $xmlrpc_server->signatures[$key] = '';
  52        $xmlrpc_server->help[$key] = '';
  53      }
  54    }
  55  
  56    $data = file_get_contents('php://input');
  57    if (!$data) {
  58      die('XML-RPC server accepts POST requests only.');
  59    }
  60    $xmlrpc_server->message = xmlrpc_message($data);
  61    if (!xmlrpc_message_parse($xmlrpc_server->message)) {
  62      xmlrpc_server_error(-32700, t('Parse error. Request not well formed.'));
  63    }
  64    if ($xmlrpc_server->message->messagetype != 'methodCall') {
  65      xmlrpc_server_error(-32600, t('Server error. Invalid XML-RPC. Request must be a methodCall.'));
  66    }
  67    if (!isset($xmlrpc_server->message->params)) {
  68      $xmlrpc_server->message->params = array();
  69    }
  70    xmlrpc_server_set($xmlrpc_server);
  71    $result = xmlrpc_server_call($xmlrpc_server, $xmlrpc_server->message->methodname, $xmlrpc_server->message->params);
  72  
  73    if (is_object($result) && !empty($result->is_error)) {
  74      xmlrpc_server_error($result);
  75    }
  76    // Encode the result
  77    $r = xmlrpc_value($result);
  78    // Create the XML
  79    $xml = '
  80  <methodResponse>
  81    <params>
  82    <param>
  83      <value>'.
  84      xmlrpc_value_get_xml($r)
  85      .'</value>
  86    </param>
  87    </params>
  88  </methodResponse>
  89  
  90  ';
  91    // Send it
  92    xmlrpc_server_output($xml);
  93  }
  94  
  95  /**
  96   * Throw an XML-RPC error.
  97   *
  98   * @param $error
  99   *   an error object OR integer error code
 100   * @param $message
 101   *   description of error, used only if integer error code was passed
 102   */
 103  function xmlrpc_server_error($error, $message = FALSE) {
 104    if ($message && !is_object($error)) {
 105      $error = xmlrpc_error($error, $message);
 106    }
 107    xmlrpc_server_output(xmlrpc_error_get_xml($error));
 108  }
 109  
 110  function xmlrpc_server_output($xml) {
 111    $xml = '<?xml version="1.0"?>'."\n". $xml;
 112    header('Connection: close');
 113    header('Content-Length: '. strlen($xml));
 114    header('Content-Type: text/xml');
 115    header('Date: '. date('r'));
 116    echo $xml;
 117    exit;
 118  }
 119  
 120  /**
 121   * Store a copy of the request temporarily.
 122   *
 123   * @param $xmlrpc_server
 124   *   Request object created by xmlrpc_server().
 125   */
 126  function xmlrpc_server_set($xmlrpc_server = NULL) {
 127    static $server;
 128    if (!isset($server)) {
 129      $server = $xmlrpc_server;
 130    }
 131    return $server;
 132  }
 133  
 134  // Retrieve the stored request.
 135  function xmlrpc_server_get() {
 136    return xmlrpc_server_set();
 137  }
 138  
 139  /**
 140   * Dispatch the request and any parameters to the appropriate handler.
 141   *
 142   * @param $xmlrpc_server
 143   * @param $methodname
 144   *   The external XML-RPC method name, e.g. 'system.methodHelp'
 145   * @param $args
 146   *   Array containing any parameters that were sent along with the request.
 147   */
 148  function xmlrpc_server_call($xmlrpc_server, $methodname, $args) {
 149    // Make sure parameters are in an array
 150    if ($args && !is_array($args)) {
 151      $args = array($args);
 152    }
 153    // Has this method been mapped to a Drupal function by us or by modules?
 154    if (!isset($xmlrpc_server->callbacks[$methodname])) {
 155      return xmlrpc_error(-32601, t('Server error. Requested method @methodname not specified.', array("@methodname" => $xmlrpc_server->message->methodname)));
 156    }
 157    $method = $xmlrpc_server->callbacks[$methodname];
 158    $signature = $xmlrpc_server->signatures[$methodname];
 159  
 160    // If the method has a signature, validate the request against the signature
 161    if (is_array($signature)) {
 162      $ok = TRUE;
 163      $return_type = array_shift($signature);
 164      // Check the number of arguments
 165      if (count($args) != count($signature)) {
 166        return xmlrpc_error(-32602, t('Server error. Wrong number of method parameters.'));
 167      }
 168      // Check the argument types
 169      foreach ($signature as $key => $type) {
 170        $arg = $args[$key];
 171        switch ($type) {
 172          case 'int':
 173          case 'i4':
 174            if (is_array($arg) || !is_int($arg)) {
 175              $ok = FALSE;
 176            }
 177            break;
 178          case 'base64':
 179          case 'string':
 180            if (!is_string($arg)) {
 181              $ok = FALSE;
 182            }
 183            break;
 184          case 'boolean':
 185            if ($arg !== FALSE && $arg !== TRUE) {
 186              $ok = FALSE;
 187            }
 188            break;
 189          case 'float':
 190          case 'double':
 191            if (!is_float($arg)) {
 192              $ok = FALSE;
 193            }
 194            break;
 195          case 'date':
 196          case 'dateTime.iso8601':
 197            if (!$arg->is_date) {
 198              $ok = FALSE;
 199            }
 200            break;
 201        }
 202        if (!$ok) {
 203          return xmlrpc_error(-32602, t('Server error. Invalid method parameters.'));
 204        }
 205      }
 206    }
 207  
 208    if (!function_exists($method)) {
 209      return xmlrpc_error(-32601, t('Server error. Requested function @method does not exist.', array("@method" => $method)));
 210    }
 211    // Call the mapped function
 212    return call_user_func_array($method, $args);
 213  }
 214  
 215  function xmlrpc_server_multicall($methodcalls) {
 216    // See http://www.xmlrpc.com/discuss/msgReader$1208
 217    $return = array();
 218    $xmlrpc_server = xmlrpc_server_get();
 219    foreach ($methodcalls as $call) {
 220      $ok = TRUE;
 221      if (!isset($call['methodName']) || !isset($call['params'])) {
 222        $result = xmlrpc_error(3, t('Invalid syntax for system.multicall.'));
 223        $ok = FALSE;
 224      }
 225      $method = $call['methodName'];
 226      $params = $call['params'];
 227      if ($method == 'system.multicall') {
 228        $result = xmlrpc_error(-32600, t('Recursive calls to system.multicall are forbidden.'));
 229      }
 230      elseif ($ok) {
 231        $result = xmlrpc_server_call($xmlrpc_server, $method, $params);
 232      }
 233      if (is_object($result) && !empty($result->is_error)) {
 234        $return[] = array(
 235          'faultCode' => $result->code,
 236          'faultString' => $result->message
 237        );
 238      }
 239      else {
 240        $return[] = $result;
 241      }
 242    }
 243    return $return;
 244  }
 245  
 246  
 247  /**
 248   * XML-RPC method system.listMethods maps to this function.
 249   */
 250  function xmlrpc_server_list_methods() {
 251    $xmlrpc_server = xmlrpc_server_get();
 252    return array_keys($xmlrpc_server->callbacks);
 253  }
 254  
 255  /**
 256   * XML-RPC method system.getCapabilities maps to this function.
 257   * See http://groups.yahoo.com/group/xml-rpc/message/2897
 258   */
 259  function xmlrpc_server_get_capabilities() {
 260    return array(
 261      'xmlrpc' => array(
 262        'specUrl' => 'http://www.xmlrpc.com/spec',
 263        'specVersion' => 1
 264      ),
 265      'faults_interop' => array(
 266        'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php',
 267        'specVersion' => 20010516
 268      ),
 269      'system.multicall' => array(
 270        'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208',
 271        'specVersion' => 1
 272      ),
 273      'introspection' => array(
 274      'specUrl' => 'http://scripts.incutio.com/xmlrpc/introspection.html',
 275      'specVersion' => 1
 276      )
 277    );
 278  }
 279  
 280  /**
 281   * XML-RPC method system.methodSignature maps to this function.
 282   *
 283   * @param $methodname
 284   *   Name of method for which we return a method signature.
 285   * @return array
 286   *   An array of types representing the method signature of the
 287   *   function that the methodname maps to. The methodSignature of
 288   *   this function is 'array', 'string' because it takes an array
 289   *   and returns a string.
 290   */
 291  function xmlrpc_server_method_signature($methodname) {
 292    $xmlrpc_server = xmlrpc_server_get();
 293    if (!isset($xmlrpc_server->callbacks[$methodname])) {
 294      return xmlrpc_error(-32601, t('Server error. Requested method @methodname not specified.', array("@methodname" => $methodname)));
 295    }
 296    if (!is_array($xmlrpc_server->signatures[$methodname])) {
 297      return xmlrpc_error(-32601, t('Server error. Requested method @methodname signature not specified.', array("@methodname" => $methodname)));
 298    }
 299    // We array of types
 300    $return = array();
 301    foreach ($xmlrpc_server->signatures[$methodname] as $type) {
 302      $return[] = $type;
 303    }
 304    return $return;
 305  }
 306  
 307  /**
 308   * XML-RPC method system.methodHelp maps to this function.
 309   *
 310   * @param $method
 311   *   Name of method for which we return a help string.
 312   */
 313  function xmlrpc_server_method_help($method) {
 314    $xmlrpc_server = xmlrpc_server_get();
 315    return $xmlrpc_server->help[$method];
 316  }


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7