CodeIgniter PHP Cross Reference Developer Tools

Source: /system/libraries/Xmlrpc.php - 1423 lines - 33567 bytes - Summary - Text - Print

Description: CodeIgniter An open source application development framework for PHP 5.1.6 or newer

   1  <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
   2  /**
   3   * CodeIgniter
   4   *
   5   * An open source application development framework for PHP 5.1.6 or newer
   6   *
   7   * @package        CodeIgniter
   8   * @author        ExpressionEngine Dev Team
   9   * @copyright    Copyright (c) 2008 - 2011, EllisLab, Inc.
  10   * @license        http://codeigniter.com/user_guide/license.html
  11   * @link        http://codeigniter.com
  12   * @since        Version 1.0
  13   * @filesource
  14   */
  15  
  16  if ( ! function_exists('xml_parser_create'))
  17  {
  18      show_error('Your PHP installation does not support XML');
  19  }
  20  
  21  
  22  // ------------------------------------------------------------------------
  23  
  24  /**
  25   * XML-RPC request handler class
  26   *
  27   * @package        CodeIgniter
  28   * @subpackage    Libraries
  29   * @category    XML-RPC
  30   * @author        ExpressionEngine Dev Team
  31   * @link        http://codeigniter.com/user_guide/libraries/xmlrpc.html
  32   */
  33  class CI_Xmlrpc {
  34  
  35      var $debug            = FALSE;    // Debugging on or off
  36      var $xmlrpcI4        = 'i4';
  37      var $xmlrpcInt        = 'int';
  38      var $xmlrpcBoolean    = 'boolean';
  39      var $xmlrpcDouble    = 'double';
  40      var $xmlrpcString    = 'string';
  41      var $xmlrpcDateTime    = 'dateTime.iso8601';
  42      var $xmlrpcBase64    = 'base64';
  43      var $xmlrpcArray    = 'array';
  44      var $xmlrpcStruct    = 'struct';
  45  
  46      var $xmlrpcTypes    = array();
  47      var $valid_parents    = array();
  48      var $xmlrpcerr        = array();    // Response numbers
  49      var $xmlrpcstr        = array();  // Response strings
  50  
  51      var $xmlrpc_defencoding = 'UTF-8';
  52      var $xmlrpcName            = 'XML-RPC for CodeIgniter';
  53      var $xmlrpcVersion        = '1.1';
  54      var $xmlrpcerruser        = 800; // Start of user errors
  55      var $xmlrpcerrxml        = 100; // Start of XML Parse errors
  56      var $xmlrpc_backslash    = ''; // formulate backslashes for escaping regexp
  57  
  58      var $client;
  59      var $method;
  60      var $data;
  61      var $message            = '';
  62      var $error                = '';        // Error string for request
  63      var $result;
  64      var $response            = array();  // Response from remote server
  65  
  66      var $xss_clean            = TRUE;
  67  
  68      //-------------------------------------
  69      //  VALUES THAT MULTIPLE CLASSES NEED
  70      //-------------------------------------
  71  
  72  	public function __construct($config = array())
  73      {
  74          $this->xmlrpcName        = $this->xmlrpcName;
  75          $this->xmlrpc_backslash = chr(92).chr(92);
  76  
  77          // Types for info sent back and forth
  78          $this->xmlrpcTypes = array(
  79              $this->xmlrpcI4             => '1',
  80              $this->xmlrpcInt        => '1',
  81              $this->xmlrpcBoolean    => '1',
  82              $this->xmlrpcString        => '1',
  83              $this->xmlrpcDouble        => '1',
  84              $this->xmlrpcDateTime    => '1',
  85              $this->xmlrpcBase64        => '1',
  86              $this->xmlrpcArray        => '2',
  87              $this->xmlrpcStruct        => '3'
  88              );
  89  
  90          // Array of Valid Parents for Various XML-RPC elements
  91          $this->valid_parents = array('BOOLEAN'            => array('VALUE'),
  92                                       'I4'                => array('VALUE'),
  93                                       'INT'                => array('VALUE'),
  94                                       'STRING'            => array('VALUE'),
  95                                       'DOUBLE'            => array('VALUE'),
  96                                       'DATETIME.ISO8601'    => array('VALUE'),
  97                                       'BASE64'            => array('VALUE'),
  98                                       'ARRAY'            => array('VALUE'),
  99                                       'STRUCT'            => array('VALUE'),
 100                                       'PARAM'            => array('PARAMS'),
 101                                       'METHODNAME'        => array('METHODCALL'),
 102                                       'PARAMS'            => array('METHODCALL', 'METHODRESPONSE'),
 103                                       'MEMBER'            => array('STRUCT'),
 104                                       'NAME'                => array('MEMBER'),
 105                                       'DATA'                => array('ARRAY'),
 106                                       'FAULT'            => array('METHODRESPONSE'),
 107                                       'VALUE'            => array('MEMBER', 'DATA', 'PARAM', 'FAULT')
 108                                       );
 109  
 110  
 111          // XML-RPC Responses
 112          $this->xmlrpcerr['unknown_method'] = '1';
 113          $this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server';
 114          $this->xmlrpcerr['invalid_return'] = '2';
 115          $this->xmlrpcstr['invalid_return'] = 'The XML data received was either invalid or not in the correct form for XML-RPC.  Turn on debugging to examine the XML data further.';
 116          $this->xmlrpcerr['incorrect_params'] = '3';
 117          $this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method';
 118          $this->xmlrpcerr['introspect_unknown'] = '4';
 119          $this->xmlrpcstr['introspect_unknown'] = "Cannot inspect signature for request: method unknown";
 120          $this->xmlrpcerr['http_error'] = '5';
 121          $this->xmlrpcstr['http_error'] = "Did not receive a '200 OK' response from remote server.";
 122          $this->xmlrpcerr['no_data'] = '6';
 123          $this->xmlrpcstr['no_data'] ='No data received from server.';
 124  
 125          $this->initialize($config);
 126  
 127          log_message('debug', "XML-RPC Class Initialized");
 128      }
 129  
 130  
 131      //-------------------------------------
 132      //  Initialize Prefs
 133      //-------------------------------------
 134  
 135  	function initialize($config = array())
 136      {
 137          if (count($config) > 0)
 138          {
 139              foreach ($config as $key => $val)
 140              {
 141                  if (isset($this->$key))
 142                  {
 143                      $this->$key = $val;
 144                  }
 145              }
 146          }
 147      }
 148      // END
 149  
 150      //-------------------------------------
 151      //  Take URL and parse it
 152      //-------------------------------------
 153  
 154  	function server($url, $port=80)
 155      {
 156          if (substr($url, 0, 4) != "http")
 157          {
 158              $url = "http://".$url;
 159          }
 160  
 161          $parts = parse_url($url);
 162  
 163          $path = ( ! isset($parts['path'])) ? '/' : $parts['path'];
 164  
 165          if (isset($parts['query']) && $parts['query'] != '')
 166          {
 167              $path .= '?'.$parts['query'];
 168          }
 169  
 170          $this->client = new XML_RPC_Client($path, $parts['host'], $port);
 171      }
 172      // END
 173  
 174      //-------------------------------------
 175      //  Set Timeout
 176      //-------------------------------------
 177  
 178  	function timeout($seconds=5)
 179      {
 180          if ( ! is_null($this->client) && is_int($seconds))
 181          {
 182              $this->client->timeout = $seconds;
 183          }
 184      }
 185      // END
 186  
 187      //-------------------------------------
 188      //  Set Methods
 189      //-------------------------------------
 190  
 191  	function method($function)
 192      {
 193          $this->method = $function;
 194      }
 195      // END
 196  
 197      //-------------------------------------
 198      //  Take Array of Data and Create Objects
 199      //-------------------------------------
 200  
 201  	function request($incoming)
 202      {
 203          if ( ! is_array($incoming))
 204          {
 205              // Send Error
 206          }
 207  
 208          $this->data = array();
 209  
 210          foreach ($incoming as $key => $value)
 211          {
 212              $this->data[$key] = $this->values_parsing($value);
 213          }
 214      }
 215      // END
 216  
 217  
 218      //-------------------------------------
 219      //  Set Debug
 220      //-------------------------------------
 221  
 222  	function set_debug($flag = TRUE)
 223      {
 224          $this->debug = ($flag == TRUE) ? TRUE : FALSE;
 225      }
 226  
 227      //-------------------------------------
 228      //  Values Parsing
 229      //-------------------------------------
 230  
 231  	function values_parsing($value, $return = FALSE)
 232      {
 233          if (is_array($value) && array_key_exists(0, $value))
 234          {
 235              if ( ! isset($value['1']) OR ( ! isset($this->xmlrpcTypes[$value['1']])))
 236              {
 237                  if (is_array($value[0]))
 238                  {
 239                      $temp = new XML_RPC_Values($value['0'], 'array');
 240                  }
 241                  else
 242                  {
 243                      $temp = new XML_RPC_Values($value['0'], 'string');
 244                  }
 245              }
 246              elseif (is_array($value['0']) && ($value['1'] == 'struct' OR $value['1'] == 'array'))
 247              {
 248                  while (list($k) = each($value['0']))
 249                  {
 250                      $value['0'][$k] = $this->values_parsing($value['0'][$k], TRUE);
 251                  }
 252  
 253                  $temp = new XML_RPC_Values($value['0'], $value['1']);
 254              }
 255              else
 256              {
 257                  $temp = new XML_RPC_Values($value['0'], $value['1']);
 258              }
 259          }
 260          else
 261          {
 262              $temp = new XML_RPC_Values($value, 'string');
 263          }
 264  
 265          return $temp;
 266      }
 267      // END
 268  
 269  
 270      //-------------------------------------
 271      //  Sends XML-RPC Request
 272      //-------------------------------------
 273  
 274  	function send_request()
 275      {
 276          $this->message = new XML_RPC_Message($this->method,$this->data);
 277          $this->message->debug = $this->debug;
 278  
 279          if ( ! $this->result = $this->client->send($this->message))
 280          {
 281              $this->error = $this->result->errstr;
 282              return FALSE;
 283          }
 284          elseif ( ! is_object($this->result->val))
 285          {
 286              $this->error = $this->result->errstr;
 287              return FALSE;
 288          }
 289  
 290          $this->response = $this->result->decode();
 291  
 292          return TRUE;
 293      }
 294      // END
 295  
 296      //-------------------------------------
 297      //  Returns Error
 298      //-------------------------------------
 299  
 300  	function display_error()
 301      {
 302          return $this->error;
 303      }
 304      // END
 305  
 306      //-------------------------------------
 307      //  Returns Remote Server Response
 308      //-------------------------------------
 309  
 310  	function display_response()
 311      {
 312          return $this->response;
 313      }
 314      // END
 315  
 316      //-------------------------------------
 317      //  Sends an Error Message for Server Request
 318      //-------------------------------------
 319  
 320  	function send_error_message($number, $message)
 321      {
 322          return new XML_RPC_Response('0',$number, $message);
 323      }
 324      // END
 325  
 326  
 327      //-------------------------------------
 328      //  Send Response for Server Request
 329      //-------------------------------------
 330  
 331  	function send_response($response)
 332      {
 333          // $response should be array of values, which will be parsed
 334          // based on their data and type into a valid group of XML-RPC values
 335  
 336          $response = $this->values_parsing($response);
 337  
 338          return new XML_RPC_Response($response);
 339      }
 340      // END
 341  
 342  } // END XML_RPC Class
 343  
 344  
 345  
 346  /**
 347   * XML-RPC Client class
 348   *
 349   * @category    XML-RPC
 350   * @author        ExpressionEngine Dev Team
 351   * @link        http://codeigniter.com/user_guide/libraries/xmlrpc.html
 352   */
 353  class XML_RPC_Client extends CI_Xmlrpc
 354  {
 355      var $path            = '';
 356      var $server            = '';
 357      var $port            = 80;
 358      var $errno            = '';
 359      var $errstring        = '';
 360      var $timeout        = 5;
 361      var $no_multicall    = FALSE;
 362  
 363  	public function __construct($path, $server, $port=80)
 364      {
 365          parent::__construct();
 366  
 367          $this->port = $port;
 368          $this->server = $server;
 369          $this->path = $path;
 370      }
 371  
 372  	function send($msg)
 373      {
 374          if (is_array($msg))
 375          {
 376              // Multi-call disabled
 377              $r = new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'],$this->xmlrpcstr['multicall_recursion']);
 378              return $r;
 379          }
 380  
 381          return $this->sendPayload($msg);
 382      }
 383  
 384  	function sendPayload($msg)
 385      {
 386          $fp = @fsockopen($this->server, $this->port,$this->errno, $this->errstr, $this->timeout);
 387  
 388          if ( ! is_resource($fp))
 389          {
 390              error_log($this->xmlrpcstr['http_error']);
 391              $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'],$this->xmlrpcstr['http_error']);
 392              return $r;
 393          }
 394  
 395          if (empty($msg->payload))
 396          {
 397              // $msg = XML_RPC_Messages
 398              $msg->createPayload();
 399          }
 400  
 401          $r = "\r\n";
 402          $op  = "POST {$this->path} HTTP/1.0$r";
 403          $op .= "Host: {$this->server}$r";
 404          $op .= "Content-Type: text/xml$r";
 405          $op .= "User-Agent: {$this->xmlrpcName}$r";
 406          $op .= "Content-Length: ".strlen($msg->payload). "$r$r";
 407          $op .= $msg->payload;
 408  
 409  
 410          if ( ! fputs($fp, $op, strlen($op)))
 411          {
 412              error_log($this->xmlrpcstr['http_error']);
 413              $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
 414              return $r;
 415          }
 416          $resp = $msg->parseResponse($fp);
 417          fclose($fp);
 418          return $resp;
 419      }
 420  
 421  } // end class XML_RPC_Client
 422  
 423  
 424  /**
 425   * XML-RPC Response class
 426   *
 427   * @category    XML-RPC
 428   * @author        ExpressionEngine Dev Team
 429   * @link        http://codeigniter.com/user_guide/libraries/xmlrpc.html
 430   */
 431  class XML_RPC_Response
 432  {
 433      var $val = 0;
 434      var $errno = 0;
 435      var $errstr = '';
 436      var $headers = array();
 437      var $xss_clean = TRUE;
 438  
 439  	public function __construct($val, $code = 0, $fstr = '')
 440      {
 441          if ($code != 0)
 442          {
 443              // error
 444              $this->errno = $code;
 445              $this->errstr = htmlentities($fstr);
 446          }
 447          else if ( ! is_object($val))
 448          {
 449              // programmer error, not an object
 450              error_log("Invalid type '" . gettype($val) . "' (value: $val) passed to XML_RPC_Response.  Defaulting to empty value.");
 451              $this->val = new XML_RPC_Values();
 452          }
 453          else
 454          {
 455              $this->val = $val;
 456          }
 457      }
 458  
 459  	function faultCode()
 460      {
 461          return $this->errno;
 462      }
 463  
 464  	function faultString()
 465      {
 466          return $this->errstr;
 467      }
 468  
 469  	function value()
 470      {
 471          return $this->val;
 472      }
 473  
 474  	function prepare_response()
 475      {
 476          $result = "<methodResponse>\n";
 477          if ($this->errno)
 478          {
 479              $result .= '<fault>
 480      <value>
 481          <struct>
 482              <member>
 483                  <name>faultCode</name>
 484                  <value><int>' . $this->errno . '</int></value>
 485              </member>
 486              <member>
 487                  <name>faultString</name>
 488                  <value><string>' . $this->errstr . '</string></value>
 489              </member>
 490          </struct>
 491      </value>
 492  </fault>';
 493          }
 494          else
 495          {
 496              $result .= "<params>\n<param>\n" .
 497                      $this->val->serialize_class() .
 498                      "</param>\n</params>";
 499          }
 500          $result .= "\n</methodResponse>";
 501          return $result;
 502      }
 503  
 504  	function decode($array=FALSE)
 505      {
 506          $CI =& get_instance();
 507          
 508          if ($array !== FALSE && is_array($array))
 509          {
 510              while (list($key) = each($array))
 511              {
 512                  if (is_array($array[$key]))
 513                  {
 514                      $array[$key] = $this->decode($array[$key]);
 515                  }
 516                  else
 517                  {
 518                      $array[$key] = ($this->xss_clean) ? $CI->security->xss_clean($array[$key]) : $array[$key];
 519                  }
 520              }
 521  
 522              $result = $array;
 523          }
 524          else
 525          {
 526              $result = $this->xmlrpc_decoder($this->val);
 527  
 528              if (is_array($result))
 529              {
 530                  $result = $this->decode($result);
 531              }
 532              else
 533              {
 534                  $result = ($this->xss_clean) ? $CI->security->xss_clean($result) : $result;
 535              }
 536          }
 537  
 538          return $result;
 539      }
 540  
 541  
 542  
 543      //-------------------------------------
 544      //  XML-RPC Object to PHP Types
 545      //-------------------------------------
 546  
 547  	function xmlrpc_decoder($xmlrpc_val)
 548      {
 549          $kind = $xmlrpc_val->kindOf();
 550  
 551          if ($kind == 'scalar')
 552          {
 553              return $xmlrpc_val->scalarval();
 554          }
 555          elseif ($kind == 'array')
 556          {
 557              reset($xmlrpc_val->me);
 558              list($a,$b) = each($xmlrpc_val->me);
 559              $size = count($b);
 560  
 561              $arr = array();
 562  
 563              for ($i = 0; $i < $size; $i++)
 564              {
 565                  $arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);
 566              }
 567              return $arr;
 568          }
 569          elseif ($kind == 'struct')
 570          {
 571              reset($xmlrpc_val->me['struct']);
 572              $arr = array();
 573  
 574              while (list($key,$value) = each($xmlrpc_val->me['struct']))
 575              {
 576                  $arr[$key] = $this->xmlrpc_decoder($value);
 577              }
 578              return $arr;
 579          }
 580      }
 581  
 582  
 583      //-------------------------------------
 584      //  ISO-8601 time to server or UTC time
 585      //-------------------------------------
 586  
 587  	function iso8601_decode($time, $utc=0)
 588      {
 589          // return a timet in the localtime, or UTC
 590          $t = 0;
 591          if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))
 592          {
 593              $fnc = ($utc == 1) ? 'gmmktime' : 'mktime';
 594              $t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
 595          }
 596          return $t;
 597      }
 598  
 599  } // End Response Class
 600  
 601  
 602  
 603  /**
 604   * XML-RPC Message class
 605   *
 606   * @category    XML-RPC
 607   * @author        ExpressionEngine Dev Team
 608   * @link        http://codeigniter.com/user_guide/libraries/xmlrpc.html
 609   */
 610  class XML_RPC_Message extends CI_Xmlrpc
 611  {
 612      var $payload;
 613      var $method_name;
 614      var $params            = array();
 615      var $xh                = array();
 616  
 617  	public function __construct($method, $pars=0)
 618      {
 619          parent::__construct();
 620  
 621          $this->method_name = $method;
 622          if (is_array($pars) && count($pars) > 0)
 623          {
 624              for ($i=0; $i<count($pars); $i++)
 625              {
 626                  // $pars[$i] = XML_RPC_Values
 627                  $this->params[] = $pars[$i];
 628              }
 629          }
 630      }
 631  
 632      //-------------------------------------
 633      //  Create Payload to Send
 634      //-------------------------------------
 635  
 636  	function createPayload()
 637      {
 638          $this->payload = "<?xml version=\"1.0\"?".">\r\n<methodCall>\r\n";
 639          $this->payload .= '<methodName>' . $this->method_name . "</methodName>\r\n";
 640          $this->payload .= "<params>\r\n";
 641  
 642          for ($i=0; $i<count($this->params); $i++)
 643          {
 644              // $p = XML_RPC_Values
 645              $p = $this->params[$i];
 646              $this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n";
 647          }
 648  
 649          $this->payload .= "</params>\r\n</methodCall>\r\n";
 650      }
 651  
 652      //-------------------------------------
 653      //  Parse External XML-RPC Server's Response
 654      //-------------------------------------
 655  
 656  	function parseResponse($fp)
 657      {
 658          $data = '';
 659  
 660          while ($datum = fread($fp, 4096))
 661          {
 662              $data .= $datum;
 663          }
 664  
 665          //-------------------------------------
 666          //  DISPLAY HTTP CONTENT for DEBUGGING
 667          //-------------------------------------
 668  
 669          if ($this->debug === TRUE)
 670          {
 671              echo "<pre>";
 672              echo "---DATA---\n" . htmlspecialchars($data) . "\n---END DATA---\n\n";
 673              echo "</pre>";
 674          }
 675  
 676          //-------------------------------------
 677          //  Check for data
 678          //-------------------------------------
 679  
 680          if ($data == "")
 681          {
 682              error_log($this->xmlrpcstr['no_data']);
 683              $r = new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
 684              return $r;
 685          }
 686  
 687  
 688          //-------------------------------------
 689          //  Check for HTTP 200 Response
 690          //-------------------------------------
 691  
 692          if (strncmp($data, 'HTTP', 4) == 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
 693          {
 694              $errstr= substr($data, 0, strpos($data, "\n")-1);
 695              $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']. ' (' . $errstr . ')');
 696              return $r;
 697          }
 698  
 699          //-------------------------------------
 700          //  Create and Set Up XML Parser
 701          //-------------------------------------
 702  
 703          $parser = xml_parser_create($this->xmlrpc_defencoding);
 704  
 705          $this->xh[$parser]                    = array();
 706          $this->xh[$parser]['isf']            = 0;
 707          $this->xh[$parser]['ac']            = '';
 708          $this->xh[$parser]['headers']        = array();
 709          $this->xh[$parser]['stack']            = array();
 710          $this->xh[$parser]['valuestack']    = array();
 711          $this->xh[$parser]['isf_reason']    = 0;
 712  
 713          xml_set_object($parser, $this);
 714          xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
 715          xml_set_element_handler($parser, 'open_tag', 'closing_tag');
 716          xml_set_character_data_handler($parser, 'character_data');
 717          //xml_set_default_handler($parser, 'default_handler');
 718  
 719  
 720          //-------------------------------------
 721          //  GET HEADERS
 722          //-------------------------------------
 723  
 724          $lines = explode("\r\n", $data);
 725          while (($line = array_shift($lines)))
 726          {
 727              if (strlen($line) < 1)
 728              {
 729                  break;
 730              }
 731              $this->xh[$parser]['headers'][] = $line;
 732          }
 733          $data = implode("\r\n", $lines);
 734  
 735  
 736          //-------------------------------------
 737          //  PARSE XML DATA
 738          //-------------------------------------
 739  
 740          if ( ! xml_parse($parser, $data, count($data)))
 741          {
 742              $errstr = sprintf('XML error: %s at line %d',
 743                      xml_error_string(xml_get_error_code($parser)),
 744                      xml_get_current_line_number($parser));
 745              //error_log($errstr);
 746              $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
 747              xml_parser_free($parser);
 748              return $r;
 749          }
 750          xml_parser_free($parser);
 751  
 752          // ---------------------------------------
 753          //  Got Ourselves Some Badness, It Seems
 754          // ---------------------------------------
 755  
 756          if ($this->xh[$parser]['isf'] > 1)
 757          {
 758              if ($this->debug === TRUE)
 759              {
 760                  echo "---Invalid Return---\n";
 761                  echo $this->xh[$parser]['isf_reason'];
 762                  echo "---Invalid Return---\n\n";
 763              }
 764  
 765              $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'],$this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
 766              return $r;
 767          }
 768          elseif ( ! is_object($this->xh[$parser]['value']))
 769          {
 770              $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'],$this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
 771              return $r;
 772          }
 773  
 774          //-------------------------------------
 775          //  DISPLAY XML CONTENT for DEBUGGING
 776          //-------------------------------------
 777  
 778          if ($this->debug === TRUE)
 779          {
 780              echo "<pre>";
 781  
 782              if (count($this->xh[$parser]['headers'] > 0))
 783              {
 784                  echo "---HEADERS---\n";
 785                  foreach ($this->xh[$parser]['headers'] as $header)
 786                  {
 787                      echo "$header\n";
 788                  }
 789                  echo "---END HEADERS---\n\n";
 790              }
 791  
 792              echo "---DATA---\n" . htmlspecialchars($data) . "\n---END DATA---\n\n";
 793  
 794              echo "---PARSED---\n" ;
 795              var_dump($this->xh[$parser]['value']);
 796              echo "\n---END PARSED---</pre>";
 797          }
 798  
 799          //-------------------------------------
 800          //  SEND RESPONSE
 801          //-------------------------------------
 802  
 803          $v = $this->xh[$parser]['value'];
 804  
 805          if ($this->xh[$parser]['isf'])
 806          {
 807              $errno_v = $v->me['struct']['faultCode'];
 808              $errstr_v = $v->me['struct']['faultString'];
 809              $errno = $errno_v->scalarval();
 810  
 811              if ($errno == 0)
 812              {
 813                  // FAULT returned, errno needs to reflect that
 814                  $errno = -1;
 815              }
 816  
 817              $r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
 818          }
 819          else
 820          {
 821              $r = new XML_RPC_Response($v);
 822          }
 823  
 824          $r->headers = $this->xh[$parser]['headers'];
 825          return $r;
 826      }
 827  
 828      // ------------------------------------
 829      //  Begin Return Message Parsing section
 830      // ------------------------------------
 831  
 832      // quick explanation of components:
 833      //   ac - used to accumulate values
 834      //   isf - used to indicate a fault
 835      //   lv - used to indicate "looking for a value": implements
 836      //        the logic to allow values with no types to be strings
 837      //   params - used to store parameters in method calls
 838      //   method - used to store method name
 839      //     stack - array with parent tree of the xml element,
 840      //             used to validate the nesting of elements
 841  
 842      //-------------------------------------
 843      //  Start Element Handler
 844      //-------------------------------------
 845  
 846  	function open_tag($the_parser, $name, $attrs)
 847      {
 848          // If invalid nesting, then return
 849          if ($this->xh[$the_parser]['isf'] > 1) return;
 850  
 851          // Evaluate and check for correct nesting of XML elements
 852  
 853          if (count($this->xh[$the_parser]['stack']) == 0)
 854          {
 855              if ($name != 'METHODRESPONSE' && $name != 'METHODCALL')
 856              {
 857                  $this->xh[$the_parser]['isf'] = 2;
 858                  $this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
 859                  return;
 860              }
 861          }
 862          else
 863          {
 864              // not top level element: see if parent is OK
 865              if ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
 866              {
 867                  $this->xh[$the_parser]['isf'] = 2;
 868                  $this->xh[$the_parser]['isf_reason'] = "XML-RPC element $name cannot be child of ".$this->xh[$the_parser]['stack'][0];
 869                  return;
 870              }
 871          }
 872  
 873          switch($name)
 874          {
 875              case 'STRUCT':
 876              case 'ARRAY':
 877                  // Creates array for child elements
 878  
 879                  $cur_val = array('value' => array(),
 880                                   'type'     => $name);
 881  
 882                  array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
 883              break;
 884              case 'METHODNAME':
 885              case 'NAME':
 886                  $this->xh[$the_parser]['ac'] = '';
 887              break;
 888              case 'FAULT':
 889                  $this->xh[$the_parser]['isf'] = 1;
 890              break;
 891              case 'PARAM':
 892                  $this->xh[$the_parser]['value'] = NULL;
 893              break;
 894              case 'VALUE':
 895                  $this->xh[$the_parser]['vt'] = 'value';
 896                  $this->xh[$the_parser]['ac'] = '';
 897                  $this->xh[$the_parser]['lv'] = 1;
 898              break;
 899              case 'I4':
 900              case 'INT':
 901              case 'STRING':
 902              case 'BOOLEAN':
 903              case 'DOUBLE':
 904              case 'DATETIME.ISO8601':
 905              case 'BASE64':
 906                  if ($this->xh[$the_parser]['vt'] != 'value')
 907                  {
 908                      //two data elements inside a value: an error occurred!
 909                      $this->xh[$the_parser]['isf'] = 2;
 910                      $this->xh[$the_parser]['isf_reason'] = "'Twas a $name element following a ".$this->xh[$the_parser]['vt']." element inside a single value";
 911                      return;
 912                  }
 913  
 914                  $this->xh[$the_parser]['ac'] = '';
 915              break;
 916              case 'MEMBER':
 917                  // Set name of <member> to nothing to prevent errors later if no <name> is found
 918                  $this->xh[$the_parser]['valuestack'][0]['name'] = '';
 919  
 920                  // Set NULL value to check to see if value passed for this param/member
 921                  $this->xh[$the_parser]['value'] = NULL;
 922              break;
 923              case 'DATA':
 924              case 'METHODCALL':
 925              case 'METHODRESPONSE':
 926              case 'PARAMS':
 927                  // valid elements that add little to processing
 928              break;
 929              default:
 930                  /// An Invalid Element is Found, so we have trouble
 931                  $this->xh[$the_parser]['isf'] = 2;
 932                  $this->xh[$the_parser]['isf_reason'] = "Invalid XML-RPC element found: $name";
 933              break;
 934          }
 935  
 936          // Add current element name to stack, to allow validation of nesting
 937          array_unshift($this->xh[$the_parser]['stack'], $name);
 938  
 939          if ($name != 'VALUE') $this->xh[$the_parser]['lv'] = 0;
 940      }
 941      // END
 942  
 943  
 944      //-------------------------------------
 945      //  End Element Handler
 946      //-------------------------------------
 947  
 948  	function closing_tag($the_parser, $name)
 949      {
 950          if ($this->xh[$the_parser]['isf'] > 1) return;
 951  
 952          // Remove current element from stack and set variable
 953          // NOTE: If the XML validates, then we do not have to worry about
 954          // the opening and closing of elements.  Nesting is checked on the opening
 955          // tag so we be safe there as well.
 956  
 957          $curr_elem = array_shift($this->xh[$the_parser]['stack']);
 958  
 959          switch($name)
 960          {
 961              case 'STRUCT':
 962              case 'ARRAY':
 963                  $cur_val = array_shift($this->xh[$the_parser]['valuestack']);
 964                  $this->xh[$the_parser]['value'] = ( ! isset($cur_val['values'])) ? array() : $cur_val['values'];
 965                  $this->xh[$the_parser]['vt']    = strtolower($name);
 966              break;
 967              case 'NAME':
 968                  $this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
 969              break;
 970              case 'BOOLEAN':
 971              case 'I4':
 972              case 'INT':
 973              case 'STRING':
 974              case 'DOUBLE':
 975              case 'DATETIME.ISO8601':
 976              case 'BASE64':
 977                  $this->xh[$the_parser]['vt'] = strtolower($name);
 978  
 979                  if ($name == 'STRING')
 980                  {
 981                      $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
 982                  }
 983                  elseif ($name=='DATETIME.ISO8601')
 984                  {
 985                      $this->xh[$the_parser]['vt']    = $this->xmlrpcDateTime;
 986                      $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
 987                  }
 988                  elseif ($name=='BASE64')
 989                  {
 990                      $this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
 991                  }
 992                  elseif ($name=='BOOLEAN')
 993                  {
 994                      // Translated BOOLEAN values to TRUE AND FALSE
 995                      if ($this->xh[$the_parser]['ac'] == '1')
 996                      {
 997                          $this->xh[$the_parser]['value'] = TRUE;
 998                      }
 999                      else
1000                      {
1001                          $this->xh[$the_parser]['value'] = FALSE;
1002                      }
1003                  }
1004                  elseif ($name=='DOUBLE')
1005                  {
1006                      // we have a DOUBLE
1007                      // we must check that only 0123456789-.<space> are characters here
1008                      if ( ! preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac']))
1009                      {
1010                          $this->xh[$the_parser]['value'] = 'ERROR_NON_NUMERIC_FOUND';
1011                      }
1012                      else
1013                      {
1014                          $this->xh[$the_parser]['value'] = (double)$this->xh[$the_parser]['ac'];
1015                      }
1016                  }
1017                  else
1018                  {
1019                      // we have an I4/INT
1020                      // we must check that only 0123456789-<space> are characters here
1021                      if ( ! preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac']))
1022                      {
1023                          $this->xh[$the_parser]['value'] = 'ERROR_NON_NUMERIC_FOUND';
1024                      }
1025                      else
1026                      {
1027                          $this->xh[$the_parser]['value'] = (int)$this->xh[$the_parser]['ac'];
1028                      }
1029                  }
1030                  $this->xh[$the_parser]['ac'] = '';
1031                  $this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
1032              break;
1033              case 'VALUE':
1034                  // This if() detects if no scalar was inside <VALUE></VALUE>
1035                  if ($this->xh[$the_parser]['vt']=='value')
1036                  {
1037                      $this->xh[$the_parser]['value']    = $this->xh[$the_parser]['ac'];
1038                      $this->xh[$the_parser]['vt']    = $this->xmlrpcString;
1039                  }
1040  
1041                  // build the XML-RPC value out of the data received, and substitute it
1042                  $temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
1043  
1044                  if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] == 'ARRAY')
1045                  {
1046                      // Array
1047                      $this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
1048                  }
1049                  else
1050                  {
1051                      // Struct
1052                      $this->xh[$the_parser]['value'] = $temp;
1053                  }
1054              break;
1055              case 'MEMBER':
1056                  $this->xh[$the_parser]['ac']='';
1057  
1058                  // If value add to array in the stack for the last element built
1059                  if ($this->xh[$the_parser]['value'])
1060                  {
1061                      $this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
1062                  }
1063              break;
1064              case 'DATA':
1065                  $this->xh[$the_parser]['ac']='';
1066              break;
1067              case 'PARAM':
1068                  if ($this->xh[$the_parser]['value'])
1069                  {
1070                      $this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
1071                  }
1072              break;
1073              case 'METHODNAME':
1074                  $this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
1075              break;
1076              case 'PARAMS':
1077              case 'FAULT':
1078              case 'METHODCALL':
1079              case 'METHORESPONSE':
1080                  // We're all good kids with nuthin' to do
1081              break;
1082              default:
1083                  // End of an Invalid Element.  Taken care of during the opening tag though
1084              break;
1085          }
1086      }
1087  
1088      //-------------------------------------
1089      //  Parses Character Data
1090      //-------------------------------------
1091  
1092  	function character_data($the_parser, $data)
1093      {
1094          if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
1095  
1096          // If a value has not been found
1097          if ($this->xh[$the_parser]['lv'] != 3)
1098          {
1099              if ($this->xh[$the_parser]['lv'] == 1)
1100              {
1101                  $this->xh[$the_parser]['lv'] = 2; // Found a value
1102              }
1103  
1104              if ( ! @isset($this->xh[$the_parser]['ac']))
1105              {
1106                  $this->xh[$the_parser]['ac'] = '';
1107              }
1108  
1109              $this->xh[$the_parser]['ac'] .= $data;
1110          }
1111      }
1112  
1113  
1114  	function addParam($par) { $this->params[]=$par; }
1115  
1116  	function output_parameters($array=FALSE)
1117      {
1118          $CI =& get_instance();
1119          
1120          if ($array !== FALSE && is_array($array))
1121          {
1122              while (list($key) = each($array))
1123              {
1124                  if (is_array($array[$key]))
1125                  {
1126                      $array[$key] = $this->output_parameters($array[$key]);
1127                  }
1128                  else
1129                  {
1130                      // 'bits' is for the MetaWeblog API image bits
1131                      // @todo - this needs to be made more general purpose
1132                      $array[$key] = ($key == 'bits' OR $this->xss_clean == FALSE) ? $array[$key] : $CI->security->xss_clean($array[$key]);
1133                  }
1134              }
1135  
1136              $parameters = $array;
1137          }
1138          else
1139          {
1140              $parameters = array();
1141  
1142              for ($i = 0; $i < count($this->params); $i++)
1143              {
1144                  $a_param = $this->decode_message($this->params[$i]);
1145  
1146                  if (is_array($a_param))
1147                  {
1148                      $parameters[] = $this->output_parameters($a_param);
1149                  }
1150                  else
1151                  {
1152                      $parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;
1153                  }
1154              }
1155          }
1156  
1157          return $parameters;
1158      }
1159  
1160  
1161  	function decode_message($param)
1162      {
1163          $kind = $param->kindOf();
1164  
1165          if ($kind == 'scalar')
1166          {
1167              return $param->scalarval();
1168          }
1169          elseif ($kind == 'array')
1170          {
1171              reset($param->me);
1172              list($a,$b) = each($param->me);
1173  
1174              $arr = array();
1175  
1176              for($i = 0; $i < count($b); $i++)
1177              {
1178                  $arr[] = $this->decode_message($param->me['array'][$i]);
1179              }
1180  
1181              return $arr;
1182          }
1183          elseif ($kind == 'struct')
1184          {
1185              reset($param->me['struct']);
1186  
1187              $arr = array();
1188  
1189              while (list($key,$value) = each($param->me['struct']))
1190              {
1191                  $arr[$key] = $this->decode_message($value);
1192              }
1193  
1194              return $arr;
1195          }
1196      }
1197  
1198  } // End XML_RPC_Messages class
1199  
1200  
1201  
1202  /**
1203   * XML-RPC Values class
1204   *
1205   * @category    XML-RPC
1206   * @author        ExpressionEngine Dev Team
1207   * @link        http://codeigniter.com/user_guide/libraries/xmlrpc.html
1208   */
1209  class XML_RPC_Values extends CI_Xmlrpc
1210  {
1211      var $me        = array();
1212      var $mytype    = 0;
1213  
1214  	public function __construct($val=-1, $type='')
1215      {
1216          parent::__construct();
1217  
1218          if ($val != -1 OR $type != '')
1219          {
1220              $type = $type == '' ? 'string' : $type;
1221  
1222              if ($this->xmlrpcTypes[$type] == 1)
1223              {
1224                  $this->addScalar($val,$type);
1225              }
1226              elseif ($this->xmlrpcTypes[$type] == 2)
1227              {
1228                  $this->addArray($val);
1229              }
1230              elseif ($this->xmlrpcTypes[$type] == 3)
1231              {
1232                  $this->addStruct($val);
1233              }
1234          }
1235      }
1236  
1237  	function addScalar($val, $type='string')
1238      {
1239          $typeof = $this->xmlrpcTypes[$type];
1240  
1241          if ($this->mytype==1)
1242          {
1243              echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
1244              return 0;
1245          }
1246  
1247          if ($typeof != 1)
1248          {
1249              echo '<strong>XML_RPC_Values</strong>: not a scalar type ($typeof})<br />';
1250              return 0;
1251          }
1252  
1253          if ($type == $this->xmlrpcBoolean)
1254          {
1255              if (strcasecmp($val,'true')==0 OR $val==1 OR ($val==true && strcasecmp($val,'false')))
1256              {
1257                  $val = 1;
1258              }
1259              else
1260              {
1261                  $val=0;
1262              }
1263          }
1264  
1265          if ($this->mytype == 2)
1266          {
1267              // adding to an array here
1268              $ar = $this->me['array'];
1269              $ar[] = new XML_RPC_Values($val, $type);
1270              $this->me['array'] = $ar;
1271          }
1272          else
1273          {
1274              // a scalar, so set the value and remember we're scalar
1275              $this->me[$type] = $val;
1276              $this->mytype = $typeof;
1277          }
1278          return 1;
1279      }
1280  
1281  	function addArray($vals)
1282      {
1283          if ($this->mytype != 0)
1284          {
1285              echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
1286              return 0;
1287          }
1288  
1289          $this->mytype = $this->xmlrpcTypes['array'];
1290          $this->me['array'] = $vals;
1291          return 1;
1292      }
1293  
1294  	function addStruct($vals)
1295      {
1296          if ($this->mytype != 0)
1297          {
1298              echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
1299              return 0;
1300          }
1301          $this->mytype = $this->xmlrpcTypes['struct'];
1302          $this->me['struct'] = $vals;
1303          return 1;
1304      }
1305  
1306  	function kindOf()
1307      {
1308          switch($this->mytype)
1309          {
1310              case 3:
1311                  return 'struct';
1312                  break;
1313              case 2:
1314                  return 'array';
1315                  break;
1316              case 1:
1317                  return 'scalar';
1318                  break;
1319              default:
1320                  return 'undef';
1321          }
1322      }
1323  
1324  	function serializedata($typ, $val)
1325      {
1326          $rs = '';
1327  
1328          switch($this->xmlrpcTypes[$typ])
1329          {
1330              case 3:
1331                  // struct
1332                  $rs .= "<struct>\n";
1333                  reset($val);
1334                  while (list($key2, $val2) = each($val))
1335                  {
1336                      $rs .= "<member>\n<name>{$key2}</name>\n";
1337                      $rs .= $this->serializeval($val2);
1338                      $rs .= "</member>\n";
1339                  }
1340                  $rs .= '</struct>';
1341              break;
1342              case 2:
1343                  // array
1344                  $rs .= "<array>\n<data>\n";
1345                  for($i=0; $i < count($val); $i++)
1346                  {
1347                      $rs .= $this->serializeval($val[$i]);
1348                  }
1349                  $rs.="</data>\n</array>\n";
1350                  break;
1351              case 1:
1352                  // others
1353                  switch ($typ)
1354                  {
1355                      case $this->xmlrpcBase64:
1356                          $rs .= "<{$typ}>" . base64_encode((string)$val) . "</{$typ}>\n";
1357                      break;
1358                      case $this->xmlrpcBoolean:
1359                          $rs .= "<{$typ}>" . ((bool)$val ? '1' : '0') . "</{$typ}>\n";
1360                      break;
1361                      case $this->xmlrpcString:
1362                          $rs .= "<{$typ}>" . htmlspecialchars((string)$val). "</{$typ}>\n";
1363                      break;
1364                      default:
1365                          $rs .= "<{$typ}>{$val}</{$typ}>\n";
1366                      break;
1367                  }
1368              default:
1369              break;
1370          }
1371          return $rs;
1372      }
1373  
1374  	function serialize_class()
1375      {
1376          return $this->serializeval($this);
1377      }
1378  
1379  	function serializeval($o)
1380      {
1381          $ar = $o->me;
1382          reset($ar);
1383  
1384          list($typ, $val) = each($ar);
1385          $rs = "<value>\n".$this->serializedata($typ, $val)."</value>\n";
1386          return $rs;
1387      }
1388  
1389  	function scalarval()
1390      {
1391          reset($this->me);
1392          list($a,$b) = each($this->me);
1393          return $b;
1394      }
1395  
1396  
1397      //-------------------------------------
1398      // Encode time in ISO-8601 form.
1399      //-------------------------------------
1400  
1401      // Useful for sending time in XML-RPC
1402  
1403  	function iso8601_encode($time, $utc=0)
1404      {
1405          if ($utc == 1)
1406          {
1407              $t = strftime("%Y%m%dT%H:%i:%s", $time);
1408          }
1409          else
1410          {
1411              if (function_exists('gmstrftime'))
1412                  $t = gmstrftime("%Y%m%dT%H:%i:%s", $time);
1413              else
1414                  $t = strftime("%Y%m%dT%H:%i:%s", $time - date('Z'));
1415          }
1416          return $t;
1417      }
1418  
1419  }
1420  // END XML_RPC_Values Class
1421  
1422  /* End of file Xmlrpc.php */
1423  /* Location: ./system/libraries/Xmlrpc.php */

title

Description

title

Description

title

Description

title

title

Body