[ Index ]
 

Code source de Dolibarr 2.0.1

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/htdocs/lib/ -> xmlrpc.php (source)

   1  <?php
   2  /*
   3  An XML-RPC implementation by Keith Devens, version 2.5f.
   4  http://www.keithdevens.com/software/xmlrpc/
   5  
   6  Release history available at:
   7  http://www.keithdevens.com/software/xmlrpc/history/
   8  
   9  This code is Open Source, released under terms similar to the Artistic License.
  10  Read the license at http://www.keithdevens.com/software/license/
  11  
  12  Note: this code requires version 4.1.0 or higher of PHP.
  13  */
  14  
  15  function & XML_serialize(&$data, $level = 0, $prior_key = NULL){
  16      #assumes a hash, keys are the variable names
  17      $xml_serialized_string = "";
  18      while(list($key, $value) = each($data)){
  19          $inline = false;
  20          $numeric_array = false;
  21          $attributes = "";
  22          #echo "My current key is '$key', called with prior key '$prior_key'<br>";
  23          if(!strstr($key, " attr")){ #if it's not an attribute
  24              if(array_key_exists("$key attr", $data)){
  25                  while(list($attr_name, $attr_value) = each($data["$key attr"])){
  26                      #echo "Found attribute $attribute_name with value $attribute_value<br>";
  27                      $attr_value = &htmlspecialchars($attr_value, ENT_QUOTES);
  28                      $attributes .= " $attr_name=\"$attr_value\"";
  29                  }
  30              }
  31  
  32              if(is_numeric($key)){
  33                  #echo "My current key ($key) is numeric. My parent key is '$prior_key'<br>";
  34                  $key = $prior_key;
  35              }else{
  36                  #you can't have numeric keys at two levels in a row, so this is ok
  37                  #echo "Checking to see if a numeric key exists in data.";
  38                  if(is_array($value) and array_key_exists(0, $value)){
  39                  #    echo " It does! Calling myself as a result of a numeric array.<br>";
  40                      $numeric_array = true;
  41                      $xml_serialized_string .= XML_serialize($value, $level, $key);
  42                  }
  43                  #echo "<br>";
  44              }
  45  
  46              if(!$numeric_array){
  47                  $xml_serialized_string .= str_repeat("\t", $level) . "<$key$attributes>";
  48  
  49                  if(is_array($value)){
  50                      $xml_serialized_string .= "\r\n" . XML_serialize($value, $level+1);
  51                  }else{
  52                      $inline = true;
  53                      $xml_serialized_string .= htmlspecialchars($value);
  54                  }
  55  
  56                  $xml_serialized_string .= (!$inline ? str_repeat("\t", $level) : "") . "</$key>\r\n";
  57              }
  58          }else{
  59              #echo "Skipping attribute record for key $key<bR>";
  60          }
  61      }
  62      if($level == 0){
  63          $xml_serialized_string = "<?xml version=\"1.0\" ?>\r\n" . $xml_serialized_string;
  64          return $xml_serialized_string;
  65      }else{
  66          return $xml_serialized_string;
  67      }
  68  }
  69  
  70  class XML {
  71      var $parser; #a reference to the XML parser
  72      var $document; #the entire XML structure built up so far
  73      var $current; #a pointer to the current item - what is this
  74      var $parent; #a pointer to the current parent - the parent will be an array
  75      var $parents; #an array of the most recent parent at each level
  76  
  77      var $last_opened_tag;
  78  
  79      function XML($data=null){
  80          $this->parser = xml_parser_create();
  81  
  82          xml_parser_set_option ($this->parser, XML_OPTION_CASE_FOLDING, 0);
  83          xml_set_object($this->parser, &$this);
  84          xml_set_element_handler($this->parser, "open", "close");
  85          xml_set_character_data_handler($this->parser, "data");
  86  #        register_shutdown_function(array(&$this, 'destruct'));
  87      }
  88  
  89      function destruct(){
  90          xml_parser_free($this->parser);
  91      }
  92  
  93      function parse($data){
  94          $this->document = array();
  95          $this->parent = &$this->document;
  96          $this->parents = array();
  97          $this->last_opened_tag = NULL;
  98          xml_parse($this->parser, $data);
  99          return $this->document;
 100      }
 101  
 102      function open($parser, $tag, $attributes){
 103          #echo "Opening tag $tag<br>\n";
 104          $this->data = "";
 105          $this->last_opened_tag = $tag; #tag is a string
 106          if(array_key_exists($tag, $this->parent)){
 107              #echo "There's already an instance of '$tag' at the current level ($level)<br>\n";
 108              if(is_array($this->parent[$tag]) and array_key_exists(0, $this->parent[$tag])){ #if the keys are numeric
 109                  #need to make sure they're numeric (account for attributes)
 110                  $key = count_numeric_items($this->parent[$tag]);
 111                  #echo "There are $key instances: the keys are numeric.<br>\n";
 112              }else{
 113                  #echo "There is only one instance. Shifting everything around<br>\n";
 114                  $temp = &$this->parent[$tag];
 115                  unset($this->parent[$tag]);
 116                  $this->parent[$tag][0] = &$temp;
 117  
 118                  if(array_key_exists("$tag attr", $this->parent)){
 119                      #shift the attributes around too if they exist
 120                      $temp = &$this->parent["$tag attr"];
 121                      unset($this->parent["$tag attr"]);
 122                      $this->parent[$tag]["0 attr"] = &$temp;
 123                  }
 124                  $key = 1;
 125              }
 126              $this->parent = &$this->parent[$tag];
 127          }else{
 128              $key = $tag;
 129          }
 130          if($attributes){
 131              $this->parent["$key attr"] = $attributes;
 132          }
 133  
 134          $this->parent[$key] = array();
 135          $this->parent = &$this->parent[$key];
 136          array_unshift($this->parents, &$this->parent);
 137      }
 138  
 139      function data($parser, $data){
 140          #echo "Data is '", htmlspecialchars($data), "'<br>\n";
 141          if($this->last_opened_tag != NULL){
 142              $this->data .= $data;
 143          }
 144      }
 145  
 146      function close($parser, $tag){
 147          #echo "Close tag $tag<br>\n";
 148          if($this->last_opened_tag == $tag){
 149              $this->parent = $this->data;
 150              $this->last_opened_tag = NULL;
 151          }
 152          array_shift($this->parents);
 153          $this->parent = &$this->parents[0];
 154      }
 155  }
 156  
 157  function & XML_unserialize(&$xml){
 158      $xml_parser = new XML();
 159      $data = &$xml_parser->parse(&$xml);
 160      $xml_parser->destruct();
 161      return $data;
 162  }
 163  
 164  function & XMLRPC_parse(&$request){
 165      if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
 166          XMLRPC_debug('XMLRPC_parse', "<p>Received the following raw request:</p>" . XMLRPC_show($request, 'print_r', true));
 167      }
 168      $data = &XML_unserialize(&$request);
 169      if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
 170          XMLRPC_debug('XMLRPC_parse', "<p>Returning the following parsed request:</p>" . XMLRPC_show($data, 'print_r', true));
 171      }
 172      return $data;
 173  }
 174  
 175  function & XMLRPC_prepare($data, $type = NULL){
 176      if(is_array($data)){
 177          $num_elements = count($data);
 178          if((array_key_exists(0, $data) or !$num_elements) and $type != 'struct'){ #it's an array
 179              if(!$num_elements){ #if the array is empty
 180                  $returnvalue =  array('array' => array('data' => NULL));
 181              }else{
 182                  $returnvalue['array']['data']['value'] = array();
 183                  $temp = &$returnvalue['array']['data']['value'];
 184                  $count = count_numeric_items($data);
 185                  for($n=0; $n<$count; $n++){
 186                      $type = NULL;
 187                      if(array_key_exists("$n type", $data)){
 188                          $type = $data["$n type"];
 189                      }
 190                      $temp[$n] = XMLRPC_prepare(&$data[$n], $type);
 191                  }
 192              }
 193          }else{ #it's a struct
 194              if(!$num_elements){ #if the struct is empty
 195                  $returnvalue = array('struct' => NULL);
 196              }else{
 197                  $returnvalue['struct']['member'] = array();
 198                  $temp = &$returnvalue['struct']['member'];
 199                  while(list($key, $value) = each($data)){
 200                      if(substr($key, -5) != ' type'){ #if it's not a type specifier
 201                          $type = NULL;
 202                          if(array_key_exists("$key type", $data)){
 203                              $type = $data["$key type"];
 204                          }
 205                          $temp[] = array('name' => $key, 'value' => XMLRPC_prepare(&$value, $type));
 206                      }
 207                  }
 208              }
 209          }
 210      }else{ #it's a scalar
 211          if(!$type){
 212              if(is_int($data)){
 213                  $returnvalue['int'] = $data;
 214                  return $returnvalue;
 215              }elseif(is_float($data)){
 216                  $returnvalue['double'] = $data;
 217                  return $returnvalue;
 218              }elseif(is_bool($data)){
 219                  $returnvalue['boolean'] = ($data ? 1 : 0);
 220                  return $returnvalue;
 221              }elseif(preg_match('/^\d{8}T\d{2}:\d{2}:\d{2}$/', $data, $matches)){ #it's a date
 222                  $returnvalue['dateTime.iso8601'] = $data;
 223                  return $returnvalue;
 224              }elseif(is_string($data)){
 225                  $returnvalue['string'] = htmlspecialchars($data);
 226                  return $returnvalue;
 227              }
 228          }else{
 229              $returnvalue[$type] = htmlspecialchars($data);
 230          }
 231      }
 232      return $returnvalue;
 233  }
 234  
 235  function & XMLRPC_adjustValue(&$current_node){
 236      if(is_array($current_node)){
 237          if(isset($current_node['array'])){
 238              if(!is_array($current_node['array']['data'])){
 239                  #If there are no elements, return an empty array
 240                  return array();
 241              }else{
 242                  #echo "Getting rid of array -> data -> value<br>\n";
 243                  $temp = &$current_node['array']['data']['value'];
 244                  if(is_array($temp) and array_key_exists(0, $temp)){
 245                      $count = count($temp);
 246                      for($n=0;$n<$count;$n++){
 247                          $temp2[$n] = &XMLRPC_adjustValue(&$temp[$n]);
 248                      }
 249                      $temp = &$temp2;
 250                  }else{
 251                      $temp2 = &XMLRPC_adjustValue(&$temp);
 252                      $temp = array(&$temp2);
 253                      #I do the temp assignment because it avoids copying,
 254                      # since I can put a reference in the array
 255                      #PHP's reference model is a bit silly, and I can't just say:
 256                      # $temp = array(&XMLRPC_adjustValue(&$temp));
 257                  }
 258              }
 259          }elseif(isset($current_node['struct'])){
 260              if(!is_array($current_node['struct'])){
 261                  #If there are no members, return an empty array
 262                  return array();
 263              }else{
 264                  #echo "Getting rid of struct -> member<br>\n";
 265                  $temp = &$current_node['struct']['member'];
 266                  if(is_array($temp) and array_key_exists(0, $temp)){
 267                      $count = count($temp);
 268                      for($n=0;$n<$count;$n++){
 269                          #echo "Passing name {$temp[$n][name]}. Value is: " . show($temp[$n][value], var_dump, true) . "<br>\n";
 270                          $temp2[$temp[$n]['name']] = &XMLRPC_adjustValue(&$temp[$n]['value']);
 271                          #echo "adjustValue(): After assigning, the value is " . show($temp2[$temp[$n]['name']], var_dump, true) . "<br>\n";
 272                      }
 273                  }else{
 274                      #echo "Passing name $temp[name]<br>\n";
 275                      $temp2[$temp['name']] = &XMLRPC_adjustValue(&$temp['value']);
 276                  }
 277                  $temp = &$temp2;
 278              }
 279          }else{
 280              $types = array('string', 'int', 'i4', 'double', 'dateTime.iso8601', 'base64', 'boolean');
 281              $fell_through = true;
 282              foreach($types as $type){
 283                  if(array_key_exists($type, $current_node)){
 284                      #echo "Getting rid of '$type'<br>\n";
 285                      $temp = &$current_node[$type];
 286                      #echo "adjustValue(): The current node is set with a type of $type<br>\n";
 287                      $fell_through = false;
 288                      break;
 289                  }
 290              }
 291              if($fell_through){
 292                  $type = 'string';
 293                  #echo "Fell through! Type is $type<br>\n";
 294              }
 295              switch ($type){
 296                  case 'int': case 'i4': $temp = (int)$temp;    break;
 297                  case 'string':         $temp = (string)$temp; break;
 298                  case 'double':         $temp = (double)$temp; break;
 299                  case 'boolean':        $temp = (bool)$temp;   break;
 300              }
 301          }
 302      }else{
 303          $temp = (string)$current_node;
 304      }
 305      return $temp;
 306  }
 307  
 308  function XMLRPC_getParams($request){
 309      if(!is_array($request['methodCall']['params'])){
 310          #If there are no parameters, return an empty array
 311          return array();
 312      }else{
 313          #echo "Getting rid of methodCall -> params -> param<br>\n";
 314          $temp = &$request['methodCall']['params']['param'];
 315          if(is_array($temp) and array_key_exists(0, $temp)){
 316              $count = count($temp);
 317              for($n = 0; $n < $count; $n++){
 318                  #echo "Serializing parameter $n<br>";
 319                  $temp2[$n] = &XMLRPC_adjustValue(&$temp[$n]['value']);
 320              }
 321          }else{
 322              $temp2[0] = &XMLRPC_adjustValue($temp['value']);
 323          }
 324          $temp = &$temp2;
 325          return $temp;
 326      }
 327  }
 328  
 329  function XMLRPC_getMethodName($methodCall){
 330      #returns the method name
 331      return $methodCall['methodCall']['methodName'];
 332  }
 333  
 334  function XMLRPC_request($site, $location, $methodName, $params = NULL, $user_agent = NULL){
 335      $site = explode(':', $site);
 336      if(isset($site[1]) and is_numeric($site[1])){
 337          $port = $site[1];
 338      }else{
 339          $port = 80;
 340      }
 341      $site = $site[0];
 342  
 343      $data["methodCall"]["methodName"] = $methodName;
 344      $param_count = count($params);
 345      if(!$param_count){
 346          $data["methodCall"]["params"] = NULL;
 347      }else{
 348          for($n = 0; $n<$param_count; $n++){
 349              $data["methodCall"]["params"]["param"][$n]["value"] = $params[$n];
 350          }
 351      }
 352      $data = XML_serialize($data);
 353  
 354      if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
 355          XMLRPC_debug('XMLRPC_request', "<p>Received the following parameter list to send:</p>" . XMLRPC_show($params, 'print_r', true));
 356      }
 357      $conn = fsockopen ($site, $port); #open the connection
 358      if(!$conn){ #if the connection was not opened successfully
 359          if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
 360              XMLRPC_debug('XMLRPC_request', "<p>Connection failed: Couldn't make the connection to $site.</p>");
 361          }
 362          return array(false, array('faultCode'=>10532, 'faultString'=>"Connection failed: Couldn't make the connection to $site."));
 363      }else{
 364          $headers =
 365              "POST $location HTTP/1.0\r\n" .
 366              "Host: $site\r\n" .
 367              "Connection: close\r\n" .
 368              ($user_agent ? "User-Agent: $user_agent\r\n" : '') .
 369              "Content-Type: text/xml\r\n" .
 370              "Content-Length: " . strlen($data) . "\r\n\r\n";
 371  
 372          fputs($conn, "$headers");
 373          fputs($conn, $data);
 374  
 375          if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
 376              XMLRPC_debug('XMLRPC_request', "<p>Sent the following request:</p>\n\n" . XMLRPC_show($headers . $data, 'print_r', true));
 377          }
 378  
 379          #socket_set_blocking ($conn, false);
 380          $response = "";
 381          while(!feof($conn)){
 382              $response .= fgets($conn, 1024);
 383          }
 384          fclose($conn);
 385  
 386          #strip headers off of response
 387          $data = XML_unserialize(substr($response, strpos($response, "\r\n\r\n")+4));
 388  
 389          if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
 390              XMLRPC_debug('XMLRPC_request', "<p>Received the following response:</p>\n\n" . XMLRPC_show($response, 'print_r', true) . "<p>Which was serialized into the following data:</p>\n\n" . XMLRPC_show($data, 'print_r', true));
 391          }
 392          if(isset($data['methodResponse']['fault'])){
 393              $return =  array(false, XMLRPC_adjustValue(&$data['methodResponse']['fault']['value']));
 394              if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
 395                  XMLRPC_debug('XMLRPC_request', "<p>Returning:</p>\n\n" . XMLRPC_show($return, 'var_dump', true));
 396              }
 397              return $return;
 398          }else{
 399              $return = array(true, XMLRPC_adjustValue(&$data['methodResponse']['params']['param']['value']));
 400              if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
 401                  XMLRPC_debug('XMLRPC_request', "<p>Returning:</p>\n\n" . XMLRPC_show($return, 'var_dump', true));
 402              }
 403              return $return;
 404          }
 405      }
 406  }
 407  
 408  function XMLRPC_response($return_value, $server = NULL){
 409      $data["methodResponse"]["params"]["param"]["value"] = &$return_value;
 410      $return = XML_serialize(&$data);
 411  
 412      if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
 413          XMLRPC_debug('XMLRPC_response', "<p>Received the following data to return:</p>\n\n" . XMLRPC_show($return_value, 'print_r', true));
 414      }
 415  
 416      header("Connection: close");
 417      header("Content-Length: " . strlen($return));
 418      header("Content-Type: text/xml");
 419      header("Date: " . date("r"));
 420      if($server){
 421          header("Server: $server");
 422      }
 423  
 424      if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
 425          XMLRPC_debug('XMLRPC_response', "<p>Sent the following response:</p>\n\n" . XMLRPC_show($return, 'print_r', true));
 426      }
 427      echo $return;
 428  }
 429  
 430  function XMLRPC_error($faultCode, $faultString, $server = NULL){
 431      $array["methodResponse"]["fault"]["value"]["struct"]["member"] = array();
 432      $temp = &$array["methodResponse"]["fault"]["value"]["struct"]["member"];
 433      $temp[0]["name"] = "faultCode";
 434      $temp[0]["value"]["int"] = $faultCode;
 435      $temp[1]["name"] = "faultString";
 436      $temp[1]["value"]["string"] = $faultString;
 437  
 438      $return = XML_serialize($array);
 439  
 440      header("Connection: close");
 441      header("Content-Length: " . strlen($return));
 442      header("Content-Type: text/xml");
 443      header("Date: " . date("r"));
 444      if($server){
 445          header("Server: $server");
 446      }
 447      if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
 448          XMLRPC_debug('XMLRPC_error', "<p>Sent the following error response:</p>\n\n" . XMLRPC_show($return, 'print_r', true));
 449      }
 450      echo $return;
 451  }
 452  
 453  function XMLRPC_convert_timestamp_to_iso8601($timestamp){
 454      #takes a unix timestamp and converts it to iso8601 required by XMLRPC
 455      #an example iso8601 datetime is "20010822T03:14:33"
 456      return date("Ymd\TH:i:s", $timestamp);
 457  }
 458  
 459  function XMLRPC_convert_iso8601_to_timestamp($iso8601){
 460      return strtotime($iso8601);
 461  }
 462  
 463  function count_numeric_items(&$array){
 464      return is_array($array) ? count(array_filter(array_keys($array), 'is_numeric')) : 0;
 465  }
 466  
 467  function XMLRPC_debug($function_name, $debug_message){
 468      $GLOBALS['XMLRPC_DEBUG_INFO'][] = array($function_name, $debug_message);
 469  }
 470  
 471  function XMLRPC_debug_print(){
 472      if($GLOBALS['XMLRPC_DEBUG_INFO']){
 473          echo "<table border=\"1\" width=\"100%\">\n";
 474          foreach($GLOBALS['XMLRPC_DEBUG_INFO'] as $debug){
 475              echo "<tr><th style=\"vertical-align: top\">$debug[0]</th><td>$debug[1]</td></tr>\n";
 476          }
 477          echo "</table>\n";
 478          unset($GLOBALS['XMLRPC_DEBUG_INFO']);
 479      }else{
 480          echo "<p>No debugging information available yet.</p>";
 481      }
 482  }
 483  
 484  function XMLRPC_show($data, $func = "print_r", $return_str = false){
 485      ob_start();
 486      $func($data);
 487      $output = ob_get_contents();
 488      ob_end_clean();
 489      if($return_str){
 490          return "<pre>" . htmlspecialchars($output) . "</pre>\n";
 491      }else{
 492          echo "<pre>", htmlspecialchars($output), "</pre>\n";
 493      }
 494  }
 495  
 496  ?>


Généré le : Mon Nov 26 12:29:37 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics