-
+ B90E008830428E57DAB2F13259769BCCC29A4A06F2329857EA5980F8ABF376713CEDE8522F05B6D817BD93D800DEC47BB18C822BC8FA1997FD44A635D22D9574
mp-wp/wp-includes/class-IXR.php
(0 . 0)(1 . 887)
75504 <?php
75505 /**
75506 * IXR - The Inutio XML-RPC Library
75507 *
75508 * @package IXR
75509 * @since 1.5
75510 *
75511 * @copyright Incutio Ltd 2002-2005
75512 * @version 1.7 (beta) 23rd May 2005
75513 * @author Simon Willison
75514 * @link http://scripts.incutio.com/xmlrpc/ Site
75515 * @link http://scripts.incutio.com/xmlrpc/manual.php Manual
75516 * @license BSD License http://www.opensource.org/licenses/bsd-license.php
75517 */
75518
75519 /**
75520 * IXR_Value
75521 *
75522 * @package IXR
75523 * @since 1.5
75524 */
75525 class IXR_Value {
75526 var $data;
75527 var $type;
75528
75529 function IXR_Value ($data, $type = false) {
75530 $this->data = $data;
75531 if (!$type) {
75532 $type = $this->calculateType();
75533 }
75534 $this->type = $type;
75535 if ($type == 'struct') {
75536 /* Turn all the values in the array in to new IXR_Value objects */
75537 foreach ($this->data as $key => $value) {
75538 $this->data[$key] = new IXR_Value($value);
75539 }
75540 }
75541 if ($type == 'array') {
75542 for ($i = 0, $j = count($this->data); $i < $j; $i++) {
75543 $this->data[$i] = new IXR_Value($this->data[$i]);
75544 }
75545 }
75546 }
75547
75548 function calculateType() {
75549 if ($this->data === true || $this->data === false) {
75550 return 'boolean';
75551 }
75552 if (is_integer($this->data)) {
75553 return 'int';
75554 }
75555 if (is_double($this->data)) {
75556 return 'double';
75557 }
75558 // Deal with IXR object types base64 and date
75559 if (is_object($this->data) && is_a($this->data, 'IXR_Date')) {
75560 return 'date';
75561 }
75562 if (is_object($this->data) && is_a($this->data, 'IXR_Base64')) {
75563 return 'base64';
75564 }
75565 // If it is a normal PHP object convert it in to a struct
75566 if (is_object($this->data)) {
75567
75568 $this->data = get_object_vars($this->data);
75569 return 'struct';
75570 }
75571 if (!is_array($this->data)) {
75572 return 'string';
75573 }
75574 /* We have an array - is it an array or a struct ? */
75575 if ($this->isStruct($this->data)) {
75576 return 'struct';
75577 } else {
75578 return 'array';
75579 }
75580 }
75581
75582 function getXml() {
75583 /* Return XML for this value */
75584 switch ($this->type) {
75585 case 'boolean':
75586 return '<boolean>'.(($this->data) ? '1' : '0').'</boolean>';
75587 break;
75588 case 'int':
75589 return '<int>'.$this->data.'</int>';
75590 break;
75591 case 'double':
75592 return '<double>'.$this->data.'</double>';
75593 break;
75594 case 'string':
75595 return '<string>'.htmlspecialchars($this->data).'</string>';
75596 break;
75597 case 'array':
75598 $return = '<array><data>'."\n";
75599 foreach ($this->data as $item) {
75600 $return .= ' <value>'.$item->getXml()."</value>\n";
75601 }
75602 $return .= '</data></array>';
75603 return $return;
75604 break;
75605 case 'struct':
75606 $return = '<struct>'."\n";
75607 foreach ($this->data as $name => $value) {
75608 $name = htmlspecialchars($name);
75609 $return .= " <member><name>$name</name><value>";
75610 $return .= $value->getXml()."</value></member>\n";
75611 }
75612 $return .= '</struct>';
75613 return $return;
75614 break;
75615 case 'date':
75616 case 'base64':
75617 return $this->data->getXml();
75618 break;
75619 }
75620 return false;
75621 }
75622
75623 function isStruct($array) {
75624 /* Nasty function to check if an array is a struct or not */
75625 $expected = 0;
75626 foreach ($array as $key => $value) {
75627 if ((string)$key != (string)$expected) {
75628 return true;
75629 }
75630 $expected++;
75631 }
75632 return false;
75633 }
75634 }
75635
75636 /**
75637 * IXR_Message
75638 *
75639 * @package IXR
75640 * @since 1.5
75641 */
75642 class IXR_Message {
75643 var $message;
75644 var $messageType; // methodCall / methodResponse / fault
75645 var $faultCode;
75646 var $faultString;
75647 var $methodName;
75648 var $params;
75649 // Current variable stacks
75650 var $_arraystructs = array(); // The stack used to keep track of the current array/struct
75651 var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array
75652 var $_currentStructName = array(); // A stack as well
75653 var $_param;
75654 var $_value;
75655 var $_currentTag;
75656 var $_currentTagContents;
75657 // The XML parser
75658 var $_parser;
75659 function IXR_Message ($message) {
75660 $this->message = $message;
75661 }
75662 function parse() {
75663 // first remove the XML declaration
75664 $this->message = preg_replace('/<\?xml(.*)?\?'.'>/', '', $this->message);
75665 if (trim($this->message) == '') {
75666 return false;
75667 }
75668 $this->_parser = xml_parser_create();
75669 // Set XML parser to take the case of tags in to account
75670 xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false);
75671 // Set XML parser callback functions
75672 xml_set_object($this->_parser, $this);
75673 xml_set_element_handler($this->_parser, 'tag_open', 'tag_close');
75674 xml_set_character_data_handler($this->_parser, 'cdata');
75675 if (!xml_parse($this->_parser, $this->message)) {
75676 /* die(sprintf('XML error: %s at line %d',
75677 xml_error_string(xml_get_error_code($this->_parser)),
75678 xml_get_current_line_number($this->_parser))); */
75679 return false;
75680 }
75681 xml_parser_free($this->_parser);
75682 // Grab the error messages, if any
75683 if ($this->messageType == 'fault') {
75684 $this->faultCode = $this->params[0]['faultCode'];
75685 $this->faultString = $this->params[0]['faultString'];
75686 }
75687 return true;
75688 }
75689 function tag_open($parser, $tag, $attr) {
75690 $this->_currentTagContents = '';
75691 $this->currentTag = $tag;
75692 switch($tag) {
75693 case 'methodCall':
75694 case 'methodResponse':
75695 case 'fault':
75696 $this->messageType = $tag;
75697 break;
75698 /* Deal with stacks of arrays and structs */
75699 case 'data': // data is to all intents and puposes more interesting than array
75700 $this->_arraystructstypes[] = 'array';
75701 $this->_arraystructs[] = array();
75702 break;
75703 case 'struct':
75704 $this->_arraystructstypes[] = 'struct';
75705 $this->_arraystructs[] = array();
75706 break;
75707 }
75708 }
75709 function cdata($parser, $cdata) {
75710 $this->_currentTagContents .= $cdata;
75711 }
75712 function tag_close($parser, $tag) {
75713 $valueFlag = false;
75714 switch($tag) {
75715 case 'int':
75716 case 'i4':
75717 $value = (int) trim($this->_currentTagContents);
75718 $valueFlag = true;
75719 break;
75720 case 'double':
75721 $value = (double) trim($this->_currentTagContents);
75722 $valueFlag = true;
75723 break;
75724 case 'string':
75725 $value = $this->_currentTagContents;
75726 $valueFlag = true;
75727 break;
75728 case 'dateTime.iso8601':
75729 $value = new IXR_Date(trim($this->_currentTagContents));
75730 // $value = $iso->getTimestamp();
75731 $valueFlag = true;
75732 break;
75733 case 'value':
75734 // "If no type is indicated, the type is string."
75735 if (trim($this->_currentTagContents) != '') {
75736 $value = (string)$this->_currentTagContents;
75737 $valueFlag = true;
75738 }
75739 break;
75740 case 'boolean':
75741 $value = (boolean) trim($this->_currentTagContents);
75742 $valueFlag = true;
75743 break;
75744 case 'base64':
75745 $value = base64_decode( trim( $this->_currentTagContents ) );
75746 $valueFlag = true;
75747 break;
75748 /* Deal with stacks of arrays and structs */
75749 case 'data':
75750 case 'struct':
75751 $value = array_pop($this->_arraystructs);
75752 array_pop($this->_arraystructstypes);
75753 $valueFlag = true;
75754 break;
75755 case 'member':
75756 array_pop($this->_currentStructName);
75757 break;
75758 case 'name':
75759 $this->_currentStructName[] = trim($this->_currentTagContents);
75760 break;
75761 case 'methodName':
75762 $this->methodName = trim($this->_currentTagContents);
75763 break;
75764 }
75765 if ($valueFlag) {
75766 if (count($this->_arraystructs) > 0) {
75767 // Add value to struct or array
75768 if ($this->_arraystructstypes[count($this->_arraystructstypes)-1] == 'struct') {
75769 // Add to struct
75770 $this->_arraystructs[count($this->_arraystructs)-1][$this->_currentStructName[count($this->_currentStructName)-1]] = $value;
75771 } else {
75772 // Add to array
75773 $this->_arraystructs[count($this->_arraystructs)-1][] = $value;
75774 }
75775 } else {
75776 // Just add as a paramater
75777 $this->params[] = $value;
75778 }
75779 }
75780 $this->_currentTagContents = '';
75781 }
75782 }
75783
75784 /**
75785 * IXR_Server
75786 *
75787 * @package IXR
75788 * @since 1.5
75789 */
75790 class IXR_Server {
75791 var $data;
75792 var $callbacks = array();
75793 var $message;
75794 var $capabilities;
75795 function IXR_Server($callbacks = false, $data = false) {
75796 $this->setCapabilities();
75797 if ($callbacks) {
75798 $this->callbacks = $callbacks;
75799 }
75800 $this->setCallbacks();
75801 $this->serve($data);
75802 }
75803 function serve($data = false) {
75804 if (!$data) {
75805 global $HTTP_RAW_POST_DATA;
75806 if (!$HTTP_RAW_POST_DATA) {
75807 die('XML-RPC server accepts POST requests only.');
75808 }
75809 $data = $HTTP_RAW_POST_DATA;
75810 }
75811 $this->message = new IXR_Message($data);
75812 if (!$this->message->parse()) {
75813 $this->error(-32700, 'parse error. not well formed');
75814 }
75815 if ($this->message->messageType != 'methodCall') {
75816 $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall');
75817 }
75818 $result = $this->call($this->message->methodName, $this->message->params);
75819 // Is the result an error?
75820 if (is_a($result, 'IXR_Error')) {
75821 $this->error($result);
75822 }
75823 // Encode the result
75824 $r = new IXR_Value($result);
75825 $resultxml = $r->getXml();
75826 // Create the XML
75827 $xml = <<<EOD
75828 <methodResponse>
75829 <params>
75830 <param>
75831 <value>
75832 $resultxml
75833 </value>
75834 </param>
75835 </params>
75836 </methodResponse>
75837
75838 EOD;
75839 // Send it
75840 $this->output($xml);
75841 }
75842 function call($methodname, $args) {
75843 if (!$this->hasMethod($methodname)) {
75844 return new IXR_Error(-32601, 'server error. requested method '.
75845 $methodname.' does not exist.');
75846 }
75847 $method = $this->callbacks[$methodname];
75848 // Perform the callback and send the response
75849 if (count($args) == 1) {
75850 // If only one paramater just send that instead of the whole array
75851 $args = $args[0];
75852 }
75853 // Are we dealing with a function or a method?
75854 if (substr($method, 0, 5) == 'this:') {
75855 // It's a class method - check it exists
75856 $method = substr($method, 5);
75857 if (!method_exists($this, $method)) {
75858 return new IXR_Error(-32601, 'server error. requested class method "'.
75859 $method.'" does not exist.');
75860 }
75861 // Call the method
75862 $result = $this->$method($args);
75863 } else {
75864 // It's a function - does it exist?
75865 if (is_array($method)) {
75866 if (!method_exists($method[0], $method[1])) {
75867 return new IXR_Error(-32601, 'server error. requested object method "'.
75868 $method[1].'" does not exist.');
75869 }
75870 } else if (!function_exists($method)) {
75871 return new IXR_Error(-32601, 'server error. requested function "'.
75872 $method.'" does not exist.');
75873 }
75874 // Call the function
75875 $result = call_user_func($method, $args);
75876 }
75877 return $result;
75878 }
75879
75880 function error($error, $message = false) {
75881 // Accepts either an error object or an error code and message
75882 if ($message && !is_object($error)) {
75883 $error = new IXR_Error($error, $message);
75884 }
75885 $this->output($error->getXml());
75886 }
75887 function output($xml) {
75888 $xml = '<?xml version="1.0"?>'."\n".$xml;
75889 $length = strlen($xml);
75890 header('Connection: close');
75891 header('Content-Length: '.$length);
75892 header('Content-Type: text/xml');
75893 header('Date: '.date('r'));
75894 echo $xml;
75895 exit;
75896 }
75897 function hasMethod($method) {
75898 return in_array($method, array_keys($this->callbacks));
75899 }
75900 function setCapabilities() {
75901 // Initialises capabilities array
75902 $this->capabilities = array(
75903 'xmlrpc' => array(
75904 'specUrl' => 'http://www.xmlrpc.com/spec',
75905 'specVersion' => 1
75906 ),
75907 'faults_interop' => array(
75908 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php',
75909 'specVersion' => 20010516
75910 ),
75911 'system.multicall' => array(
75912 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208',
75913 'specVersion' => 1
75914 ),
75915 );
75916 }
75917 function getCapabilities($args) {
75918 return $this->capabilities;
75919 }
75920 function setCallbacks() {
75921 $this->callbacks['system.getCapabilities'] = 'this:getCapabilities';
75922 $this->callbacks['system.listMethods'] = 'this:listMethods';
75923 $this->callbacks['system.multicall'] = 'this:multiCall';
75924 }
75925 function listMethods($args) {
75926 // Returns a list of methods - uses array_reverse to ensure user defined
75927 // methods are listed before server defined methods
75928 return array_reverse(array_keys($this->callbacks));
75929 }
75930 function multiCall($methodcalls) {
75931 // See http://www.xmlrpc.com/discuss/msgReader$1208
75932 $return = array();
75933 foreach ($methodcalls as $call) {
75934 $method = $call['methodName'];
75935 $params = $call['params'];
75936 if ($method == 'system.multicall') {
75937 $result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden');
75938 } else {
75939 $result = $this->call($method, $params);
75940 }
75941 if (is_a($result, 'IXR_Error')) {
75942 $return[] = array(
75943 'faultCode' => $result->code,
75944 'faultString' => $result->message
75945 );
75946 } else {
75947 $return[] = array($result);
75948 }
75949 }
75950 return $return;
75951 }
75952 }
75953
75954 /**
75955 * IXR_Request
75956 *
75957 * @package IXR
75958 * @since 1.5
75959 */
75960 class IXR_Request {
75961 var $method;
75962 var $args;
75963 var $xml;
75964 function IXR_Request($method, $args) {
75965 $this->method = $method;
75966 $this->args = $args;
75967 $this->xml = <<<EOD
75968 <?xml version="1.0"?>
75969 <methodCall>
75970 <methodName>{$this->method}</methodName>
75971 <params>
75972
75973 EOD;
75974 foreach ($this->args as $arg) {
75975 $this->xml .= '<param><value>';
75976 $v = new IXR_Value($arg);
75977 $this->xml .= $v->getXml();
75978 $this->xml .= "</value></param>\n";
75979 }
75980 $this->xml .= '</params></methodCall>';
75981 }
75982 function getLength() {
75983 return strlen($this->xml);
75984 }
75985 function getXml() {
75986 return $this->xml;
75987 }
75988 }
75989
75990 /**
75991 * IXR_Client
75992 *
75993 * @package IXR
75994 * @since 1.5
75995 */
75996 class IXR_Client {
75997 var $server;
75998 var $port;
75999 var $path;
76000 var $useragent;
76001 var $response;
76002 var $message = false;
76003 var $debug = false;
76004 var $timeout;
76005 // Storage place for an error message
76006 var $error = false;
76007 function IXR_Client($server, $path = false, $port = 80, $timeout = false) {
76008 if (!$path) {
76009 // Assume we have been given a URL instead
76010 $bits = parse_url($server);
76011 $this->server = $bits['host'];
76012 $this->port = isset($bits['port']) ? $bits['port'] : 80;
76013 $this->path = isset($bits['path']) ? $bits['path'] : '/';
76014 // Make absolutely sure we have a path
76015 if (!$this->path) {
76016 $this->path = '/';
76017 }
76018 } else {
76019 $this->server = $server;
76020 $this->path = $path;
76021 $this->port = $port;
76022 }
76023 $this->useragent = 'The Incutio XML-RPC PHP Library';
76024 $this->timeout = $timeout;
76025 }
76026 function query() {
76027 $args = func_get_args();
76028 $method = array_shift($args);
76029 $request = new IXR_Request($method, $args);
76030 $length = $request->getLength();
76031 $xml = $request->getXml();
76032 $r = "\r\n";
76033 $request = "POST {$this->path} HTTP/1.0$r";
76034 $request .= "Host: {$this->server}$r";
76035 $request .= "Content-Type: text/xml$r";
76036 $request .= "User-Agent: {$this->useragent}$r";
76037 $request .= "Content-length: {$length}$r$r";
76038 $request .= $xml;
76039 // Now send the request
76040 if ($this->debug) {
76041 echo '<pre>'.htmlspecialchars($request)."\n</pre>\n\n";
76042 }
76043 if ($this->timeout) {
76044 $fp = @fsockopen($this->server, $this->port, $errno, $errstr, $this->timeout);
76045 } else {
76046 $fp = @fsockopen($this->server, $this->port, $errno, $errstr);
76047 }
76048 if (!$fp) {
76049 $this->error = new IXR_Error(-32300, "transport error - could not open socket: $errno $errstr");
76050 return false;
76051 }
76052 fputs($fp, $request);
76053 $contents = '';
76054 $gotFirstLine = false;
76055 $gettingHeaders = true;
76056 while (!feof($fp)) {
76057 $line = fgets($fp, 4096);
76058 if (!$gotFirstLine) {
76059 // Check line for '200'
76060 if (strstr($line, '200') === false) {
76061 $this->error = new IXR_Error(-32300, 'transport error - HTTP status code was not 200');
76062 return false;
76063 }
76064 $gotFirstLine = true;
76065 }
76066 if (trim($line) == '') {
76067 $gettingHeaders = false;
76068 }
76069 if (!$gettingHeaders) {
76070 $contents .= trim($line);
76071 }
76072 }
76073 if ($this->debug) {
76074 echo '<pre>'.htmlspecialchars($contents)."\n</pre>\n\n";
76075 }
76076 // Now parse what we've got back
76077 $this->message = new IXR_Message($contents);
76078 if (!$this->message->parse()) {
76079 // XML error
76080 $this->error = new IXR_Error(-32700, 'parse error. not well formed');
76081 return false;
76082 }
76083 // Is the message a fault?
76084 if ($this->message->messageType == 'fault') {
76085 $this->error = new IXR_Error($this->message->faultCode, $this->message->faultString);
76086 return false;
76087 }
76088 // Message must be OK
76089 return true;
76090 }
76091 function getResponse() {
76092 // methodResponses can only have one param - return that
76093 return $this->message->params[0];
76094 }
76095 function isError() {
76096 return (is_object($this->error));
76097 }
76098 function getErrorCode() {
76099 return $this->error->code;
76100 }
76101 function getErrorMessage() {
76102 return $this->error->message;
76103 }
76104 }
76105
76106 /**
76107 * IXR_Error
76108 *
76109 * @package IXR
76110 * @since 1.5
76111 */
76112 class IXR_Error {
76113 var $code;
76114 var $message;
76115 function IXR_Error($code, $message) {
76116 $this->code = $code;
76117 // WP adds htmlspecialchars(). See #5666
76118 $this->message = htmlspecialchars($message);
76119 }
76120 function getXml() {
76121 $xml = <<<EOD
76122 <methodResponse>
76123 <fault>
76124 <value>
76125 <struct>
76126 <member>
76127 <name>faultCode</name>
76128 <value><int>{$this->code}</int></value>
76129 </member>
76130 <member>
76131 <name>faultString</name>
76132 <value><string>{$this->message}</string></value>
76133 </member>
76134 </struct>
76135 </value>
76136 </fault>
76137 </methodResponse>
76138
76139 EOD;
76140 return $xml;
76141 }
76142 }
76143
76144 /**
76145 * IXR_Date
76146 *
76147 * @package IXR
76148 * @since 1.5
76149 */
76150 class IXR_Date {
76151 var $year;
76152 var $month;
76153 var $day;
76154 var $hour;
76155 var $minute;
76156 var $second;
76157 var $timezone;
76158 function IXR_Date($time) {
76159 // $time can be a PHP timestamp or an ISO one
76160 if (is_numeric($time)) {
76161 $this->parseTimestamp($time);
76162 } else {
76163 $this->parseIso($time);
76164 }
76165 }
76166 function parseTimestamp($timestamp) {
76167 $this->year = date('Y', $timestamp);
76168 $this->month = date('m', $timestamp);
76169 $this->day = date('d', $timestamp);
76170 $this->hour = date('H', $timestamp);
76171 $this->minute = date('i', $timestamp);
76172 $this->second = date('s', $timestamp);
76173 // WP adds timezone. See #2036
76174 $this->timezone = '';
76175 }
76176 function parseIso($iso) {
76177 $this->year = substr($iso, 0, 4);
76178 $this->month = substr($iso, 4, 2);
76179 $this->day = substr($iso, 6, 2);
76180 $this->hour = substr($iso, 9, 2);
76181 $this->minute = substr($iso, 12, 2);
76182 $this->second = substr($iso, 15, 2);
76183 // WP adds timezone. See #2036
76184 $this->timezone = substr($iso, 17);
76185 }
76186 function getIso() {
76187 // WP adds timezone. See #2036
76188 return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second.$this->timezone;
76189 }
76190 function getXml() {
76191 return '<dateTime.iso8601>'.$this->getIso().'</dateTime.iso8601>';
76192 }
76193 function getTimestamp() {
76194 return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year);
76195 }
76196 }
76197
76198 /**
76199 * IXR_Base64
76200 *
76201 * @package IXR
76202 * @since 1.5
76203 */
76204 class IXR_Base64 {
76205 var $data;
76206 function IXR_Base64($data) {
76207 $this->data = $data;
76208 }
76209 function getXml() {
76210 return '<base64>'.base64_encode($this->data).'</base64>';
76211 }
76212 }
76213
76214 /**
76215 * IXR_IntrospectionServer
76216 *
76217 * @package IXR
76218 * @since 1.5
76219 */
76220 class IXR_IntrospectionServer extends IXR_Server {
76221 var $signatures;
76222 var $help;
76223 function IXR_IntrospectionServer() {
76224 $this->setCallbacks();
76225 $this->setCapabilities();
76226 $this->capabilities['introspection'] = array(
76227 'specUrl' => 'http://xmlrpc.usefulinc.com/doc/reserved.html',
76228 'specVersion' => 1
76229 );
76230 $this->addCallback(
76231 'system.methodSignature',
76232 'this:methodSignature',
76233 array('array', 'string'),
76234 'Returns an array describing the return type and required parameters of a method'
76235 );
76236 $this->addCallback(
76237 'system.getCapabilities',
76238 'this:getCapabilities',
76239 array('struct'),
76240 'Returns a struct describing the XML-RPC specifications supported by this server'
76241 );
76242 $this->addCallback(
76243 'system.listMethods',
76244 'this:listMethods',
76245 array('array'),
76246 'Returns an array of available methods on this server'
76247 );
76248 $this->addCallback(
76249 'system.methodHelp',
76250 'this:methodHelp',
76251 array('string', 'string'),
76252 'Returns a documentation string for the specified method'
76253 );
76254 }
76255 function addCallback($method, $callback, $args, $help) {
76256 $this->callbacks[$method] = $callback;
76257 $this->signatures[$method] = $args;
76258 $this->help[$method] = $help;
76259 }
76260 function call($methodname, $args) {
76261 // Make sure it's in an array
76262 if ($args && !is_array($args)) {
76263 $args = array($args);
76264 }
76265 // Over-rides default call method, adds signature check
76266 if (!$this->hasMethod($methodname)) {
76267 return new IXR_Error(-32601, 'server error. requested method "'.$this->message->methodName.'" not specified.');
76268 }
76269 $method = $this->callbacks[$methodname];
76270 $signature = $this->signatures[$methodname];
76271 $returnType = array_shift($signature);
76272 // Check the number of arguments
76273 if (count($args) != count($signature)) {
76274 return new IXR_Error(-32602, 'server error. wrong number of method parameters');
76275 }
76276 // Check the argument types
76277 $ok = true;
76278 $argsbackup = $args;
76279 for ($i = 0, $j = count($args); $i < $j; $i++) {
76280 $arg = array_shift($args);
76281 $type = array_shift($signature);
76282 switch ($type) {
76283 case 'int':
76284 case 'i4':
76285 if (is_array($arg) || !is_int($arg)) {
76286 $ok = false;
76287 }
76288 break;
76289 case 'base64':
76290 case 'string':
76291 if (!is_string($arg)) {
76292 $ok = false;
76293 }
76294 break;
76295 case 'boolean':
76296 if ($arg !== false && $arg !== true) {
76297 $ok = false;
76298 }
76299 break;
76300 case 'float':
76301 case 'double':
76302 if (!is_float($arg)) {
76303 $ok = false;
76304 }
76305 break;
76306 case 'date':
76307 case 'dateTime.iso8601':
76308 if (!is_a($arg, 'IXR_Date')) {
76309 $ok = false;
76310 }
76311 break;
76312 }
76313 if (!$ok) {
76314 return new IXR_Error(-32602, 'server error. invalid method parameters');
76315 }
76316 }
76317 // It passed the test - run the "real" method call
76318 return parent::call($methodname, $argsbackup);
76319 }
76320 function methodSignature($method) {
76321 if (!$this->hasMethod($method)) {
76322 return new IXR_Error(-32601, 'server error. requested method "'.$method.'" not specified.');
76323 }
76324 // We should be returning an array of types
76325 $types = $this->signatures[$method];
76326 $return = array();
76327 foreach ($types as $type) {
76328 switch ($type) {
76329 case 'string':
76330 $return[] = 'string';
76331 break;
76332 case 'int':
76333 case 'i4':
76334 $return[] = 42;
76335 break;
76336 case 'double':
76337 $return[] = 3.1415;
76338 break;
76339 case 'dateTime.iso8601':
76340 $return[] = new IXR_Date(time());
76341 break;
76342 case 'boolean':
76343 $return[] = true;
76344 break;
76345 case 'base64':
76346 $return[] = new IXR_Base64('base64');
76347 break;
76348 case 'array':
76349 $return[] = array('array');
76350 break;
76351 case 'struct':
76352 $return[] = array('struct' => 'struct');
76353 break;
76354 }
76355 }
76356 return $return;
76357 }
76358 function methodHelp($method) {
76359 return $this->help[$method];
76360 }
76361 }
76362
76363 /**
76364 * IXR_ClientMulticall
76365 *
76366 * @package IXR
76367 * @since 1.5
76368 */
76369 class IXR_ClientMulticall extends IXR_Client {
76370 var $calls = array();
76371 function IXR_ClientMulticall($server, $path = false, $port = 80) {
76372 parent::IXR_Client($server, $path, $port);
76373 $this->useragent = 'The Incutio XML-RPC PHP Library (multicall client)';
76374 }
76375 function addCall() {
76376 $args = func_get_args();
76377 $methodName = array_shift($args);
76378 $struct = array(
76379 'methodName' => $methodName,
76380 'params' => $args
76381 );
76382 $this->calls[] = $struct;
76383 }
76384 function query() {
76385 // Prepare multicall, then call the parent::query() method
76386 return parent::query('system.multicall', $this->calls);
76387 }
76388 }
76389
76390 ?>