[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/includes/ -> xmlrpc.inc (source)

   1  <?php
   2  // $Id: xmlrpc.inc,v 1.47.2.6 2010/06/02 12:22:02 goba Exp $
   3  
   4  /**
   5   * @file
   6   * Drupal XML-RPC library. Based on the IXR - The Incutio XML-RPC Library - (c) Incutio Ltd 2002-2005
   7   * Version 1.7 (beta) - Simon Willison, 23rd May 2005
   8   * Site:   http://scripts.incutio.com/xmlrpc/
   9   * Manual: http://scripts.incutio.com/xmlrpc/manual.php
  10   * This version is made available under the GNU GPL License
  11   */
  12  
  13  /**
  14   * Recursively turn a data structure into objects with 'data' and 'type' attributes.
  15   *
  16   * @param $data
  17   *   The data structure.
  18   * @param  $type
  19   *   Optional type assign to $data.
  20   * @return
  21   *   Object.
  22   */
  23  function xmlrpc_value($data, $type = FALSE) {
  24    $xmlrpc_value = new stdClass();
  25    $xmlrpc_value->data = $data;
  26    if (!$type) {
  27      $type = xmlrpc_value_calculate_type($xmlrpc_value);
  28    }
  29    $xmlrpc_value->type = $type;
  30    if ($type == 'struct') {
  31      // Turn all the values in the array into new xmlrpc_values
  32      foreach ($xmlrpc_value->data as $key => $value) {
  33        $xmlrpc_value->data[$key] = xmlrpc_value($value);
  34      }
  35    }
  36    if ($type == 'array') {
  37      for ($i = 0, $j = count($xmlrpc_value->data); $i < $j; $i++) {
  38        $xmlrpc_value->data[$i] = xmlrpc_value($xmlrpc_value->data[$i]);
  39      }
  40    }
  41    return $xmlrpc_value;
  42  }
  43  
  44  /**
  45   * Map PHP type to XML-RPC type.
  46   *
  47   * @param $xmlrpc_value
  48   *   Variable whose type should be mapped.
  49   * @return
  50   *   XML-RPC type as string.
  51   * @see
  52   *   http://www.xmlrpc.com/spec#scalars
  53   */
  54  function xmlrpc_value_calculate_type(&$xmlrpc_value) {
  55    // http://www.php.net/gettype: Never use gettype() to test for a certain type [...] Instead, use the is_* functions.
  56    if (is_bool($xmlrpc_value->data)) {
  57      return 'boolean';
  58    }
  59    if (is_double($xmlrpc_value->data)) {
  60      return 'double';
  61    }
  62    if (is_int($xmlrpc_value->data)) {
  63        return 'int';
  64    }
  65    if (is_array($xmlrpc_value->data)) {
  66      // empty or integer-indexed arrays are 'array', string-indexed arrays 'struct'
  67      return empty($xmlrpc_value->data) || range(0, count($xmlrpc_value->data) - 1) === array_keys($xmlrpc_value->data) ? 'array' : 'struct';
  68    }
  69    if (is_object($xmlrpc_value->data)) {
  70      if ($xmlrpc_value->data->is_date) {
  71        return 'date';
  72      }
  73      if ($xmlrpc_value->data->is_base64) {
  74        return 'base64';
  75      }
  76      $xmlrpc_value->data = get_object_vars($xmlrpc_value->data);
  77      return 'struct';
  78    }
  79    // default
  80    return 'string';
  81  }
  82  
  83  /**
  84   * Generate XML representing the given value.
  85   *
  86   * @param $xmlrpc_value
  87   * @return
  88   *   XML representation of value.
  89   */
  90  function xmlrpc_value_get_xml($xmlrpc_value) {
  91    switch ($xmlrpc_value->type) {
  92      case 'boolean':
  93        return '<boolean>'. (($xmlrpc_value->data) ? '1' : '0') .'</boolean>';
  94        break;
  95      case 'int':
  96        return '<int>'. $xmlrpc_value->data .'</int>';
  97        break;
  98      case 'double':
  99        return '<double>'. $xmlrpc_value->data .'</double>';
 100        break;
 101      case 'string':
 102        // Note: we don't escape apostrophes because of the many blogging clients
 103        // that don't support numerical entities (and XML in general) properly.
 104        return '<string>'. htmlspecialchars($xmlrpc_value->data) .'</string>';
 105        break;
 106      case 'array':
 107        $return = '<array><data>'."\n";
 108        foreach ($xmlrpc_value->data as $item) {
 109          $return .= '  <value>'. xmlrpc_value_get_xml($item) ."</value>\n";
 110        }
 111        $return .= '</data></array>';
 112        return $return;
 113        break;
 114      case 'struct':
 115        $return = '<struct>'."\n";
 116        foreach ($xmlrpc_value->data as $name => $value) {
 117          $return .= "  <member><name>". check_plain($name) ."</name><value>";
 118          $return .= xmlrpc_value_get_xml($value) ."</value></member>\n";
 119        }
 120        $return .= '</struct>';
 121        return $return;
 122        break;
 123      case 'date':
 124        return xmlrpc_date_get_xml($xmlrpc_value->data);
 125        break;
 126      case 'base64':
 127        return xmlrpc_base64_get_xml($xmlrpc_value->data);
 128        break;
 129    }
 130    return FALSE;
 131  }
 132  
 133  /**
 134   * Construct an object representing an XML-RPC message.
 135   *
 136   * @param $message
 137   *   String containing XML as defined at http://www.xmlrpc.com/spec
 138   * @return
 139   *   Object
 140   */
 141  function xmlrpc_message($message) {
 142    $xmlrpc_message = new stdClass();
 143    $xmlrpc_message->array_structs = array();   // The stack used to keep track of the current array/struct
 144    $xmlrpc_message->array_structs_types = array(); // The stack used to keep track of if things are structs or array
 145    $xmlrpc_message->current_struct_name = array();  // A stack as well
 146    $xmlrpc_message->message = $message;
 147    return $xmlrpc_message;
 148  }
 149  
 150  /**
 151   * Parse an XML-RPC message. If parsing fails, the faultCode and faultString
 152   * will be added to the message object.
 153   *
 154   * @param $xmlrpc_message
 155   *   Object generated by xmlrpc_message()
 156   * @return
 157   *   TRUE if parsing succeeded; FALSE otherwise
 158   */
 159  function xmlrpc_message_parse(&$xmlrpc_message) {
 160    $xmlrpc_message->_parser = xml_parser_create();
 161    // Set XML parser to take the case of tags into account.
 162    xml_parser_set_option($xmlrpc_message->_parser, XML_OPTION_CASE_FOLDING, FALSE);
 163    // Set XML parser callback functions
 164    xml_set_element_handler($xmlrpc_message->_parser, 'xmlrpc_message_tag_open', 'xmlrpc_message_tag_close');
 165    xml_set_character_data_handler($xmlrpc_message->_parser, 'xmlrpc_message_cdata');
 166    xmlrpc_message_set($xmlrpc_message);
 167    if (!xml_parse($xmlrpc_message->_parser, $xmlrpc_message->message)) {
 168      return FALSE;
 169    }
 170    xml_parser_free($xmlrpc_message->_parser);
 171    // Grab the error messages, if any
 172    $xmlrpc_message = xmlrpc_message_get();
 173    if (!isset($xmlrpc_message->messagetype)) {
 174      return FALSE;
 175    }
 176    elseif ($xmlrpc_message->messagetype == 'fault') {
 177      $xmlrpc_message->fault_code = $xmlrpc_message->params[0]['faultCode'];
 178      $xmlrpc_message->fault_string = $xmlrpc_message->params[0]['faultString'];
 179    }
 180    return TRUE;
 181  }
 182  
 183  /**
 184   * Store a copy of the $xmlrpc_message object temporarily.
 185   *
 186   * @param $value
 187   *   Object
 188   * @return
 189   *   The most recently stored $xmlrpc_message
 190   */
 191  function xmlrpc_message_set($value = NULL) {
 192    static $xmlrpc_message;
 193    if ($value) {
 194      $xmlrpc_message = $value;
 195    }
 196    return $xmlrpc_message;
 197  }
 198  
 199  function xmlrpc_message_get() {
 200    return xmlrpc_message_set();
 201  }
 202  
 203  function xmlrpc_message_tag_open($parser, $tag, $attr) {
 204    $xmlrpc_message = xmlrpc_message_get();
 205    $xmlrpc_message->current_tag_contents = '';
 206    $xmlrpc_message->last_open = $tag;
 207    switch ($tag) {
 208      case 'methodCall':
 209      case 'methodResponse':
 210      case 'fault':
 211        $xmlrpc_message->messagetype = $tag;
 212        break;
 213      // Deal with stacks of arrays and structs
 214      case 'data':
 215        $xmlrpc_message->array_structs_types[] = 'array';
 216        $xmlrpc_message->array_structs[] = array();
 217        break;
 218      case 'struct':
 219        $xmlrpc_message->array_structs_types[] = 'struct';
 220        $xmlrpc_message->array_structs[] = array();
 221        break;
 222    }
 223    xmlrpc_message_set($xmlrpc_message);
 224  }
 225  
 226  function xmlrpc_message_cdata($parser, $cdata) {
 227    $xmlrpc_message = xmlrpc_message_get();
 228    $xmlrpc_message->current_tag_contents .= $cdata;
 229    xmlrpc_message_set($xmlrpc_message);
 230  }
 231  
 232  function xmlrpc_message_tag_close($parser, $tag) {
 233    $xmlrpc_message = xmlrpc_message_get();
 234    $value_flag = FALSE;
 235    switch ($tag) {
 236      case 'int':
 237      case 'i4':
 238        $value = (int)trim($xmlrpc_message->current_tag_contents);
 239        $value_flag = TRUE;
 240        break;
 241      case 'double':
 242        $value = (double)trim($xmlrpc_message->current_tag_contents);
 243        $value_flag = TRUE;
 244        break;
 245      case 'string':
 246        $value = $xmlrpc_message->current_tag_contents;
 247        $value_flag = TRUE;
 248        break;
 249      case 'dateTime.iso8601':
 250        $value = xmlrpc_date(trim($xmlrpc_message->current_tag_contents));
 251        // $value = $iso->getTimestamp();
 252        $value_flag = TRUE;
 253        break;
 254      case 'value':
 255        // If no type is indicated, the type is string
 256        // We take special care for empty values
 257        if (trim($xmlrpc_message->current_tag_contents) != '' || (isset($xmlrpc_message->last_open) && ($xmlrpc_message->last_open == 'value'))) {
 258          $value = (string)$xmlrpc_message->current_tag_contents;
 259          $value_flag = TRUE;
 260        }
 261        unset($xmlrpc_message->last_open);
 262        break;
 263      case 'boolean':
 264        $value = (boolean)trim($xmlrpc_message->current_tag_contents);
 265        $value_flag = TRUE;
 266        break;
 267      case 'base64':
 268        $value = base64_decode(trim($xmlrpc_message->current_tag_contents));
 269        $value_flag = TRUE;
 270        break;
 271      // Deal with stacks of arrays and structs
 272      case 'data':
 273      case 'struct':
 274        $value = array_pop($xmlrpc_message->array_structs );
 275        array_pop($xmlrpc_message->array_structs_types);
 276        $value_flag = TRUE;
 277        break;
 278      case 'member':
 279        array_pop($xmlrpc_message->current_struct_name);
 280        break;
 281      case 'name':
 282        $xmlrpc_message->current_struct_name[] = trim($xmlrpc_message->current_tag_contents);
 283        break;
 284      case 'methodName':
 285        $xmlrpc_message->methodname = trim($xmlrpc_message->current_tag_contents);
 286        break;
 287    }
 288    if ($value_flag) {
 289      if (count($xmlrpc_message->array_structs ) > 0) {
 290        // Add value to struct or array
 291        if ($xmlrpc_message->array_structs_types[count($xmlrpc_message->array_structs_types)-1] == 'struct') {
 292          // Add to struct
 293          $xmlrpc_message->array_structs [count($xmlrpc_message->array_structs )-1][$xmlrpc_message->current_struct_name[count($xmlrpc_message->current_struct_name)-1]] = $value;
 294        }
 295        else {
 296          // Add to array
 297          $xmlrpc_message->array_structs [count($xmlrpc_message->array_structs )-1][] = $value;
 298        }
 299      }
 300      else {
 301        // Just add as a parameter
 302        $xmlrpc_message->params[] = $value;
 303      }
 304    }
 305    if (!in_array($tag, array("data", "struct", "member"))) {
 306      $xmlrpc_message->current_tag_contents = '';
 307    }
 308    xmlrpc_message_set($xmlrpc_message);
 309  }
 310  
 311  /**
 312   * Construct an object representing an XML-RPC request
 313   *
 314   * @param $method
 315   *   The name of the method to be called
 316   * @param $args
 317   *   An array of parameters to send with the method.
 318   * @return
 319   *   Object
 320   */
 321  function xmlrpc_request($method, $args) {
 322    $xmlrpc_request = new stdClass();
 323    $xmlrpc_request->method = $method;
 324    $xmlrpc_request->args = $args;
 325    $xmlrpc_request->xml = <<<EOD
 326  <?xml version="1.0"?>
 327  <methodCall>
 328  <methodName>{$xmlrpc_request->method}</methodName>
 329  <params>
 330  
 331  EOD;
 332    foreach ($xmlrpc_request->args as $arg) {
 333      $xmlrpc_request->xml .= '<param><value>';
 334      $v = xmlrpc_value($arg);
 335      $xmlrpc_request->xml .= xmlrpc_value_get_xml($v);
 336      $xmlrpc_request->xml .= "</value></param>\n";
 337    }
 338    $xmlrpc_request->xml .= '</params></methodCall>';
 339    return $xmlrpc_request;
 340  }
 341  
 342  
 343  function xmlrpc_error($code = NULL, $message = NULL, $reset = FALSE) {
 344    static $xmlrpc_error;
 345    if (isset($code)) {
 346      $xmlrpc_error = new stdClass();
 347      $xmlrpc_error->is_error = TRUE;
 348      $xmlrpc_error->code = $code;
 349      $xmlrpc_error->message = $message;
 350    }
 351    elseif ($reset) {
 352      $xmlrpc_error = NULL;
 353    }
 354    return $xmlrpc_error;
 355  }
 356  
 357  function xmlrpc_error_get_xml($xmlrpc_error) {
 358    return <<<EOD
 359  <methodResponse>
 360    <fault>
 361    <value>
 362      <struct>
 363      <member>
 364        <name>faultCode</name>
 365        <value><int>{$xmlrpc_error->code}</int></value>
 366      </member>
 367      <member>
 368        <name>faultString</name>
 369        <value><string>{$xmlrpc_error->message}</string></value>
 370      </member>
 371      </struct>
 372    </value>
 373    </fault>
 374  </methodResponse>
 375  
 376  EOD;
 377  }
 378  
 379  function xmlrpc_date($time) {
 380    $xmlrpc_date = new stdClass();
 381    $xmlrpc_date->is_date = TRUE;
 382    // $time can be a PHP timestamp or an ISO one
 383    if (is_numeric($time)) {
 384      $xmlrpc_date->year = gmdate('Y', $time);
 385      $xmlrpc_date->month = gmdate('m', $time);
 386      $xmlrpc_date->day = gmdate('d', $time);
 387      $xmlrpc_date->hour = gmdate('H', $time);
 388      $xmlrpc_date->minute = gmdate('i', $time);
 389      $xmlrpc_date->second = gmdate('s', $time);
 390      $xmlrpc_date->iso8601 = gmdate('Ymd\TH:i:s', $time);
 391    }
 392    else {
 393      $xmlrpc_date->iso8601 = $time;
 394      $time = str_replace(array('-', ':'), '', $time);
 395      $xmlrpc_date->year = substr($time, 0, 4);
 396      $xmlrpc_date->month = substr($time, 4, 2);
 397      $xmlrpc_date->day = substr($time, 6, 2);
 398      $xmlrpc_date->hour = substr($time, 9, 2);
 399      $xmlrpc_date->minute = substr($time, 11, 2);
 400      $xmlrpc_date->second = substr($time, 13, 2);
 401    }
 402    return $xmlrpc_date;
 403  }
 404  
 405  function xmlrpc_date_get_xml($xmlrpc_date) {
 406    return '<dateTime.iso8601>'. $xmlrpc_date->year . $xmlrpc_date->month . $xmlrpc_date->day .'T'. $xmlrpc_date->hour .':'. $xmlrpc_date->minute .':'. $xmlrpc_date->second .'</dateTime.iso8601>';
 407  }
 408  
 409  function xmlrpc_base64($data) {
 410    $xmlrpc_base64 = new stdClass();
 411    $xmlrpc_base64->is_base64 = TRUE;
 412    $xmlrpc_base64->data = $data;
 413    return $xmlrpc_base64;
 414  }
 415  
 416  function xmlrpc_base64_get_xml($xmlrpc_base64) {
 417    return '<base64>'. base64_encode($xmlrpc_base64->data) .'</base64>';
 418  }
 419  
 420  /**
 421   * Execute an XML remote procedural call. This is private function; call xmlrpc()
 422   * in common.inc instead of this function.
 423   *
 424   * @return
 425   *   A $xmlrpc_message object if the call succeeded; FALSE if the call failed
 426   */
 427  function _xmlrpc() {
 428    $args = func_get_args();
 429    $url = array_shift($args);
 430    xmlrpc_clear_error();
 431    if (is_array($args[0])) {
 432      $method = 'system.multicall';
 433      $multicall_args = array();
 434      foreach ($args[0] as $call) {
 435        $multicall_args[] = array('methodName' => array_shift($call), 'params' => $call);
 436      }
 437      $args = array($multicall_args);
 438    }
 439    else {
 440      $method = array_shift($args);
 441    }
 442    $xmlrpc_request = xmlrpc_request($method, $args);
 443    $result = drupal_http_request($url, array("Content-Type" => "text/xml"), 'POST', $xmlrpc_request->xml);
 444    if ($result->code != 200) {
 445      xmlrpc_error($result->code, $result->error);
 446      return FALSE;
 447    }
 448    $message = xmlrpc_message($result->data);
 449    // Now parse what we've got back
 450    if (!xmlrpc_message_parse($message)) {
 451      // XML error
 452      xmlrpc_error(-32700, t('Parse error. Not well formed'));
 453      return FALSE;
 454    }
 455    // Is the message a fault?
 456    if ($message->messagetype == 'fault') {
 457      xmlrpc_error($message->fault_code, $message->fault_string);
 458      return FALSE;
 459    }
 460    // Message must be OK
 461    return $message->params[0];
 462  }
 463  
 464  /**
 465   * Returns the last XML-RPC client error number
 466   */
 467  function xmlrpc_errno() {
 468    $error = xmlrpc_error();
 469    return ($error != NULL ? $error->code : NULL);
 470  }
 471  
 472  /**
 473   * Returns the last XML-RPC client error message
 474   */
 475  function xmlrpc_error_msg() {
 476    $error = xmlrpc_error();
 477    return ($error != NULL ? $error->message : NULL);
 478  }
 479  
 480  /**
 481   * Clears any previous error.
 482   */
 483  function xmlrpc_clear_error() {
 484    xmlrpc_error(NULL, NULL, TRUE);
 485  }


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