[ Index ]
 

Code source de Drupal 5.3

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/includes/ -> xmlrpc.inc (source)

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


Généré le : Fri Nov 30 16:20:15 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics