[ Index ]

PHP Cross Reference of Drupal 6 (yi-drupal)

title

Body

[close]

/includes/ -> xmlrpcs.inc (source)

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


Generated: Mon Jul 9 18:01:44 2012 Cross-referenced by PHPXref 0.7