| [ Index ] |
PHP Cross Reference of Wordpress 2.9.1 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * IXR - The Inutio XML-RPC Library 4 * 5 * @package IXR 6 * @since 1.5 7 * 8 * @copyright Incutio Ltd 2002-2005 9 * @version 1.7 (beta) 23rd May 2005 10 * @author Simon Willison 11 * @link http://scripts.incutio.com/xmlrpc/ Site 12 * @link http://scripts.incutio.com/xmlrpc/manual.php Manual 13 * @license BSD License http://www.opensource.org/licenses/bsd-license.php 14 */ 15 16 /** 17 * IXR_Value 18 * 19 * @package IXR 20 * @since 1.5 21 */ 22 class IXR_Value { 23 var $data; 24 var $type; 25 26 function IXR_Value ($data, $type = false) { 27 $this->data = $data; 28 if (!$type) { 29 $type = $this->calculateType(); 30 } 31 $this->type = $type; 32 if ($type == 'struct') { 33 /* Turn all the values in the array in to new IXR_Value objects */ 34 foreach ($this->data as $key => $value) { 35 $this->data[$key] = new IXR_Value($value); 36 } 37 } 38 if ($type == 'array') { 39 for ($i = 0, $j = count($this->data); $i < $j; $i++) { 40 $this->data[$i] = new IXR_Value($this->data[$i]); 41 } 42 } 43 } 44 45 function calculateType() { 46 if ($this->data === true || $this->data === false) { 47 return 'boolean'; 48 } 49 if (is_integer($this->data)) { 50 return 'int'; 51 } 52 if (is_double($this->data)) { 53 return 'double'; 54 } 55 // Deal with IXR object types base64 and date 56 if (is_object($this->data) && is_a($this->data, 'IXR_Date')) { 57 return 'date'; 58 } 59 if (is_object($this->data) && is_a($this->data, 'IXR_Base64')) { 60 return 'base64'; 61 } 62 // If it is a normal PHP object convert it in to a struct 63 if (is_object($this->data)) { 64 65 $this->data = get_object_vars($this->data); 66 return 'struct'; 67 } 68 if (!is_array($this->data)) { 69 return 'string'; 70 } 71 /* We have an array - is it an array or a struct ? */ 72 if ($this->isStruct($this->data)) { 73 return 'struct'; 74 } else { 75 return 'array'; 76 } 77 } 78 79 function getXml() { 80 /* Return XML for this value */ 81 switch ($this->type) { 82 case 'boolean': 83 return '<boolean>'.(($this->data) ? '1' : '0').'</boolean>'; 84 break; 85 case 'int': 86 return '<int>'.$this->data.'</int>'; 87 break; 88 case 'double': 89 return '<double>'.$this->data.'</double>'; 90 break; 91 case 'string': 92 return '<string>'.htmlspecialchars($this->data).'</string>'; 93 break; 94 case 'array': 95 $return = '<array><data>'."\n"; 96 foreach ($this->data as $item) { 97 $return .= ' <value>'.$item->getXml()."</value>\n"; 98 } 99 $return .= '</data></array>'; 100 return $return; 101 break; 102 case 'struct': 103 $return = '<struct>'."\n"; 104 foreach ($this->data as $name => $value) { 105 $name = htmlspecialchars($name); 106 $return .= " <member><name>$name</name><value>"; 107 $return .= $value->getXml()."</value></member>\n"; 108 } 109 $return .= '</struct>'; 110 return $return; 111 break; 112 case 'date': 113 case 'base64': 114 return $this->data->getXml(); 115 break; 116 } 117 return false; 118 } 119 120 function isStruct($array) { 121 /* Nasty function to check if an array is a struct or not */ 122 $expected = 0; 123 foreach ($array as $key => $value) { 124 if ((string)$key != (string)$expected) { 125 return true; 126 } 127 $expected++; 128 } 129 return false; 130 } 131 } 132 133 /** 134 * IXR_Message 135 * 136 * @package IXR 137 * @since 1.5 138 */ 139 class IXR_Message { 140 var $message; 141 var $messageType; // methodCall / methodResponse / fault 142 var $faultCode; 143 var $faultString; 144 var $methodName; 145 var $params; 146 // Current variable stacks 147 var $_arraystructs = array(); // The stack used to keep track of the current array/struct 148 var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array 149 var $_currentStructName = array(); // A stack as well 150 var $_param; 151 var $_value; 152 var $_currentTag; 153 var $_currentTagContents; 154 // The XML parser 155 var $_parser; 156 function IXR_Message (&$message) { 157 $this->message = &$message; 158 } 159 function parse() { 160 // first remove the XML declaration 161 // this method avoids the RAM usage of preg_replace on very large messages 162 $header = preg_replace( '/<\?xml.*?\?'.'>/', '', substr( $this->message, 0, 100 ), 1 ); 163 $this->message = substr_replace($this->message, $header, 0, 100); 164 if (trim($this->message) == '') { 165 return false; 166 } 167 $this->_parser = xml_parser_create(); 168 // Set XML parser to take the case of tags in to account 169 xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false); 170 // Set XML parser callback functions 171 xml_set_object($this->_parser, $this); 172 xml_set_element_handler($this->_parser, 'tag_open', 'tag_close'); 173 xml_set_character_data_handler($this->_parser, 'cdata'); 174 $chunk_size = 262144; // 256Kb, parse in chunks to avoid the RAM usage on very large messages 175 do { 176 if ( strlen($this->message) <= $chunk_size ) 177 $final=true; 178 $part = substr( $this->message, 0, $chunk_size ); 179 $this->message = substr( $this->message, $chunk_size ); 180 if ( !xml_parse( $this->_parser, $part, $final ) ) 181 return false; 182 if ( $final ) 183 break; 184 } while ( true ); 185 xml_parser_free($this->_parser); 186 // Grab the error messages, if any 187 if ($this->messageType == 'fault') { 188 $this->faultCode = $this->params[0]['faultCode']; 189 $this->faultString = $this->params[0]['faultString']; 190 } 191 return true; 192 } 193 function tag_open($parser, $tag, $attr) { 194 $this->_currentTagContents = ''; 195 $this->currentTag = $tag; 196 switch($tag) { 197 case 'methodCall': 198 case 'methodResponse': 199 case 'fault': 200 $this->messageType = $tag; 201 break; 202 /* Deal with stacks of arrays and structs */ 203 case 'data': // data is to all intents and puposes more interesting than array 204 $this->_arraystructstypes[] = 'array'; 205 $this->_arraystructs[] = array(); 206 break; 207 case 'struct': 208 $this->_arraystructstypes[] = 'struct'; 209 $this->_arraystructs[] = array(); 210 break; 211 } 212 } 213 function cdata($parser, $cdata) { 214 $this->_currentTagContents .= $cdata; 215 } 216 function tag_close($parser, $tag) { 217 $valueFlag = false; 218 switch($tag) { 219 case 'int': 220 case 'i4': 221 $value = (int) trim($this->_currentTagContents); 222 $valueFlag = true; 223 break; 224 case 'double': 225 $value = (double) trim($this->_currentTagContents); 226 $valueFlag = true; 227 break; 228 case 'string': 229 $value = $this->_currentTagContents; 230 $valueFlag = true; 231 break; 232 case 'dateTime.iso8601': 233 $value = new IXR_Date(trim($this->_currentTagContents)); 234 // $value = $iso->getTimestamp(); 235 $valueFlag = true; 236 break; 237 case 'value': 238 // "If no type is indicated, the type is string." 239 if (trim($this->_currentTagContents) != '') { 240 $value = (string)$this->_currentTagContents; 241 $valueFlag = true; 242 } 243 break; 244 case 'boolean': 245 $value = (boolean) trim($this->_currentTagContents); 246 $valueFlag = true; 247 break; 248 case 'base64': 249 $value = base64_decode( trim( $this->_currentTagContents ) ); 250 $valueFlag = true; 251 break; 252 /* Deal with stacks of arrays and structs */ 253 case 'data': 254 case 'struct': 255 $value = array_pop($this->_arraystructs); 256 array_pop($this->_arraystructstypes); 257 $valueFlag = true; 258 break; 259 case 'member': 260 array_pop($this->_currentStructName); 261 break; 262 case 'name': 263 $this->_currentStructName[] = trim($this->_currentTagContents); 264 break; 265 case 'methodName': 266 $this->methodName = trim($this->_currentTagContents); 267 break; 268 } 269 if ($valueFlag) { 270 if (count($this->_arraystructs) > 0) { 271 // Add value to struct or array 272 if ($this->_arraystructstypes[count($this->_arraystructstypes)-1] == 'struct') { 273 // Add to struct 274 $this->_arraystructs[count($this->_arraystructs)-1][$this->_currentStructName[count($this->_currentStructName)-1]] = $value; 275 } else { 276 // Add to array 277 $this->_arraystructs[count($this->_arraystructs)-1][] = $value; 278 } 279 } else { 280 // Just add as a paramater 281 $this->params[] = $value; 282 } 283 } 284 $this->_currentTagContents = ''; 285 } 286 } 287 288 /** 289 * IXR_Server 290 * 291 * @package IXR 292 * @since 1.5 293 */ 294 class IXR_Server { 295 var $data; 296 var $callbacks = array(); 297 var $message; 298 var $capabilities; 299 function IXR_Server($callbacks = false, $data = false) { 300 $this->setCapabilities(); 301 if ($callbacks) { 302 $this->callbacks = $callbacks; 303 } 304 $this->setCallbacks(); 305 $this->serve($data); 306 } 307 function serve($data = false) { 308 if (!$data) { 309 global $HTTP_RAW_POST_DATA; 310 if (!$HTTP_RAW_POST_DATA) { 311 header( 'Content-Type: text/plain' ); 312 die('XML-RPC server accepts POST requests only.'); 313 } 314 $data = &$HTTP_RAW_POST_DATA; 315 } 316 $this->message = new IXR_Message($data); 317 if (!$this->message->parse()) { 318 $this->error(-32700, 'parse error. not well formed'); 319 } 320 if ($this->message->messageType != 'methodCall') { 321 $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall'); 322 } 323 $result = $this->call($this->message->methodName, $this->message->params); 324 // Is the result an error? 325 if (is_a($result, 'IXR_Error')) { 326 $this->error($result); 327 } 328 // Encode the result 329 $r = new IXR_Value($result); 330 $resultxml = $r->getXml(); 331 // Create the XML 332 $xml = <<<EOD 333 <methodResponse> 334 <params> 335 <param> 336 <value> 337 $resultxml 338 </value> 339 </param> 340 </params> 341 </methodResponse> 342 343 EOD; 344 // Send it 345 $this->output($xml); 346 } 347 function call($methodname, $args) { 348 if (!$this->hasMethod($methodname)) { 349 return new IXR_Error(-32601, 'server error. requested method '. 350 $methodname.' does not exist.'); 351 } 352 $method = $this->callbacks[$methodname]; 353 // Perform the callback and send the response 354 if (count($args) == 1) { 355 // If only one paramater just send that instead of the whole array 356 $args = $args[0]; 357 } 358 // Are we dealing with a function or a method? 359 if (substr($method, 0, 5) == 'this:') { 360 // It's a class method - check it exists 361 $method = substr($method, 5); 362 if (!method_exists($this, $method)) { 363 return new IXR_Error(-32601, 'server error. requested class method "'. 364 $method.'" does not exist.'); 365 } 366 // Call the method 367 $result = $this->$method($args); 368 } else { 369 // It's a function - does it exist? 370 if (is_array($method)) { 371 if (!method_exists($method[0], $method[1])) { 372 return new IXR_Error(-32601, 'server error. requested object method "'. 373 $method[1].'" does not exist.'); 374 } 375 } else if (!function_exists($method)) { 376 return new IXR_Error(-32601, 'server error. requested function "'. 377 $method.'" does not exist.'); 378 } 379 // Call the function 380 $result = call_user_func($method, $args); 381 } 382 return $result; 383 } 384 385 function error($error, $message = false) { 386 // Accepts either an error object or an error code and message 387 if ($message && !is_object($error)) { 388 $error = new IXR_Error($error, $message); 389 } 390 $this->output($error->getXml()); 391 } 392 function output($xml) { 393 $xml = '<?xml version="1.0"?>'."\n".$xml; 394 $length = strlen($xml); 395 header('Connection: close'); 396 header('Content-Length: '.$length); 397 header('Content-Type: text/xml'); 398 header('Date: '.date('r')); 399 echo $xml; 400 exit; 401 } 402 function hasMethod($method) { 403 return in_array($method, array_keys($this->callbacks)); 404 } 405 function setCapabilities() { 406 // Initialises capabilities array 407 $this->capabilities = array( 408 'xmlrpc' => array( 409 'specUrl' => 'http://www.xmlrpc.com/spec', 410 'specVersion' => 1 411 ), 412 'faults_interop' => array( 413 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php', 414 'specVersion' => 20010516 415 ), 416 'system.multicall' => array( 417 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208', 418 'specVersion' => 1 419 ), 420 ); 421 } 422 function getCapabilities($args) { 423 return $this->capabilities; 424 } 425 function setCallbacks() { 426 $this->callbacks['system.getCapabilities'] = 'this:getCapabilities'; 427 $this->callbacks['system.listMethods'] = 'this:listMethods'; 428 $this->callbacks['system.multicall'] = 'this:multiCall'; 429 } 430 function listMethods($args) { 431 // Returns a list of methods - uses array_reverse to ensure user defined 432 // methods are listed before server defined methods 433 return array_reverse(array_keys($this->callbacks)); 434 } 435 function multiCall($methodcalls) { 436 // See http://www.xmlrpc.com/discuss/msgReader$1208 437 $return = array(); 438 foreach ($methodcalls as $call) { 439 $method = $call['methodName']; 440 $params = $call['params']; 441 if ($method == 'system.multicall') { 442 $result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden'); 443 } else { 444 $result = $this->call($method, $params); 445 } 446 if (is_a($result, 'IXR_Error')) { 447 $return[] = array( 448 'faultCode' => $result->code, 449 'faultString' => $result->message 450 ); 451 } else { 452 $return[] = array($result); 453 } 454 } 455 return $return; 456 } 457 } 458 459 /** 460 * IXR_Request 461 * 462 * @package IXR 463 * @since 1.5 464 */ 465 class IXR_Request { 466 var $method; 467 var $args; 468 var $xml; 469 function IXR_Request($method, $args) { 470 $this->method = $method; 471 $this->args = $args; 472 $this->xml = <<<EOD 473 <?xml version="1.0"?> 474 <methodCall> 475 <methodName>{$this->method}</methodName> 476 <params> 477 478 EOD; 479 foreach ($this->args as $arg) { 480 $this->xml .= '<param><value>'; 481 $v = new IXR_Value($arg); 482 $this->xml .= $v->getXml(); 483 $this->xml .= "</value></param>\n"; 484 } 485 $this->xml .= '</params></methodCall>'; 486 } 487 function getLength() { 488 return strlen($this->xml); 489 } 490 function getXml() { 491 return $this->xml; 492 } 493 } 494 495 /** 496 * IXR_Client 497 * 498 * @package IXR 499 * @since 1.5 500 */ 501 class IXR_Client { 502 var $server; 503 var $port; 504 var $path; 505 var $useragent; 506 var $headers; 507 var $response; 508 var $message = false; 509 var $debug = false; 510 var $timeout; 511 // Storage place for an error message 512 var $error = false; 513 function IXR_Client($server, $path = false, $port = 80, $timeout = false) { 514 if (!$path) { 515 // Assume we have been given a URL instead 516 $bits = parse_url($server); 517 $this->server = $bits['host']; 518 $this->port = isset($bits['port']) ? $bits['port'] : 80; 519 $this->path = isset($bits['path']) ? $bits['path'] : '/'; 520 // Make absolutely sure we have a path 521 if (!$this->path) { 522 $this->path = '/'; 523 } 524 } else { 525 $this->server = $server; 526 $this->path = $path; 527 $this->port = $port; 528 } 529 $this->useragent = 'The Incutio XML-RPC PHP Library'; 530 $this->timeout = $timeout; 531 } 532 function query() { 533 $args = func_get_args(); 534 $method = array_shift($args); 535 $request = new IXR_Request($method, $args); 536 $length = $request->getLength(); 537 $xml = $request->getXml(); 538 $r = "\r\n"; 539 $request = "POST {$this->path} HTTP/1.0$r"; 540 541 $this->headers['Host'] = $this->server; 542 $this->headers['Content-Type'] = 'text/xml'; 543 $this->headers['User-Agent'] = $this->useragent; 544 $this->headers['Content-Length']= $length; 545 546 foreach( $this->headers as $header => $value ) { 547 $request .= "{$header}: {$value}{$r}"; 548 } 549 $request .= $r; 550 551 $request .= $xml; 552 // Now send the request 553 if ($this->debug) { 554 echo '<pre class="ixr_request">'.htmlspecialchars($request)."\n</pre>\n\n"; 555 } 556 if ($this->timeout) { 557 $fp = @fsockopen($this->server, $this->port, $errno, $errstr, $this->timeout); 558 } else { 559 $fp = @fsockopen($this->server, $this->port, $errno, $errstr); 560 } 561 if (!$fp) { 562 $this->error = new IXR_Error(-32300, "transport error - could not open socket: $errno $errstr"); 563 return false; 564 } 565 fputs($fp, $request); 566 $contents = ''; 567 $debug_contents = ''; 568 $gotFirstLine = false; 569 $gettingHeaders = true; 570 while (!feof($fp)) { 571 $line = fgets($fp, 4096); 572 if (!$gotFirstLine) { 573 // Check line for '200' 574 if (strstr($line, '200') === false) { 575 $this->error = new IXR_Error(-32301, 'transport error - HTTP status code was not 200'); 576 return false; 577 } 578 $gotFirstLine = true; 579 } 580 if (trim($line) == '') { 581 $gettingHeaders = false; 582 } 583 if (!$gettingHeaders) { 584 $contents .= trim($line); 585 } 586 if ($this->debug) { 587 $debug_contents .= $line; 588 } 589 } 590 if ($this->debug) { 591 echo '<pre class="ixr_response">'.htmlspecialchars($debug_contents)."\n</pre>\n\n"; 592 } 593 // Now parse what we've got back 594 $this->message = new IXR_Message($contents); 595 if (!$this->message->parse()) { 596 // XML error 597 $this->error = new IXR_Error(-32700, 'parse error. not well formed'); 598 return false; 599 } 600 // Is the message a fault? 601 if ($this->message->messageType == 'fault') { 602 $this->error = new IXR_Error($this->message->faultCode, $this->message->faultString); 603 return false; 604 } 605 // Message must be OK 606 return true; 607 } 608 function getResponse() { 609 // methodResponses can only have one param - return that 610 return $this->message->params[0]; 611 } 612 function isError() { 613 return (is_object($this->error)); 614 } 615 function getErrorCode() { 616 return $this->error->code; 617 } 618 function getErrorMessage() { 619 return $this->error->message; 620 } 621 } 622 623 /** 624 * IXR_Error 625 * 626 * @package IXR 627 * @since 1.5 628 */ 629 class IXR_Error { 630 var $code; 631 var $message; 632 function IXR_Error($code, $message) { 633 $this->code = $code; 634 // WP adds htmlspecialchars(). See #5666 635 $this->message = htmlspecialchars($message); 636 } 637 function getXml() { 638 $xml = <<<EOD 639 <methodResponse> 640 <fault> 641 <value> 642 <struct> 643 <member> 644 <name>faultCode</name> 645 <value><int>{$this->code}</int></value> 646 </member> 647 <member> 648 <name>faultString</name> 649 <value><string>{$this->message}</string></value> 650 </member> 651 </struct> 652 </value> 653 </fault> 654 </methodResponse> 655 656 EOD; 657 return $xml; 658 } 659 } 660 661 /** 662 * IXR_Date 663 * 664 * @package IXR 665 * @since 1.5 666 */ 667 class IXR_Date { 668 var $year; 669 var $month; 670 var $day; 671 var $hour; 672 var $minute; 673 var $second; 674 var $timezone; 675 function IXR_Date($time) { 676 // $time can be a PHP timestamp or an ISO one 677 if (is_numeric($time)) { 678 $this->parseTimestamp($time); 679 } else { 680 $this->parseIso($time); 681 } 682 } 683 function parseTimestamp($timestamp) { 684 $this->year = date('Y', $timestamp); 685 $this->month = date('m', $timestamp); 686 $this->day = date('d', $timestamp); 687 $this->hour = date('H', $timestamp); 688 $this->minute = date('i', $timestamp); 689 $this->second = date('s', $timestamp); 690 // WP adds timezone. See #2036 691 $this->timezone = ''; 692 } 693 function parseIso($iso) { 694 $this->year = substr($iso, 0, 4); 695 $this->month = substr($iso, 4, 2); 696 $this->day = substr($iso, 6, 2); 697 $this->hour = substr($iso, 9, 2); 698 $this->minute = substr($iso, 12, 2); 699 $this->second = substr($iso, 15, 2); 700 // WP adds timezone. See #2036 701 $this->timezone = substr($iso, 17); 702 } 703 function getIso() { 704 // WP adds timezone. See #2036 705 return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second.$this->timezone; 706 } 707 function getXml() { 708 return '<dateTime.iso8601>'.$this->getIso().'</dateTime.iso8601>'; 709 } 710 function getTimestamp() { 711 return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year); 712 } 713 } 714 715 /** 716 * IXR_Base64 717 * 718 * @package IXR 719 * @since 1.5 720 */ 721 class IXR_Base64 { 722 var $data; 723 function IXR_Base64($data) { 724 $this->data = $data; 725 } 726 function getXml() { 727 return '<base64>'.base64_encode($this->data).'</base64>'; 728 } 729 } 730 731 /** 732 * IXR_IntrospectionServer 733 * 734 * @package IXR 735 * @since 1.5 736 */ 737 class IXR_IntrospectionServer extends IXR_Server { 738 var $signatures; 739 var $help; 740 function IXR_IntrospectionServer() { 741 $this->setCallbacks(); 742 $this->setCapabilities(); 743 $this->capabilities['introspection'] = array( 744 'specUrl' => 'http://xmlrpc.usefulinc.com/doc/reserved.html', 745 'specVersion' => 1 746 ); 747 $this->addCallback( 748 'system.methodSignature', 749 'this:methodSignature', 750 array('array', 'string'), 751 'Returns an array describing the return type and required parameters of a method' 752 ); 753 $this->addCallback( 754 'system.getCapabilities', 755 'this:getCapabilities', 756 array('struct'), 757 'Returns a struct describing the XML-RPC specifications supported by this server' 758 ); 759 $this->addCallback( 760 'system.listMethods', 761 'this:listMethods', 762 array('array'), 763 'Returns an array of available methods on this server' 764 ); 765 $this->addCallback( 766 'system.methodHelp', 767 'this:methodHelp', 768 array('string', 'string'), 769 'Returns a documentation string for the specified method' 770 ); 771 } 772 function addCallback($method, $callback, $args, $help) { 773 $this->callbacks[$method] = $callback; 774 $this->signatures[$method] = $args; 775 $this->help[$method] = $help; 776 } 777 function call($methodname, $args) { 778 // Make sure it's in an array 779 if ($args && !is_array($args)) { 780 $args = array($args); 781 } 782 // Over-rides default call method, adds signature check 783 if (!$this->hasMethod($methodname)) { 784 return new IXR_Error(-32601, 'server error. requested method "'.$this->message->methodName.'" not specified.'); 785 } 786 $method = $this->callbacks[$methodname]; 787 $signature = $this->signatures[$methodname]; 788 $returnType = array_shift($signature); 789 // Check the number of arguments 790 if (count($args) != count($signature)) { 791 return new IXR_Error(-32602, 'server error. wrong number of method parameters'); 792 } 793 // Check the argument types 794 $ok = true; 795 $argsbackup = $args; 796 for ($i = 0, $j = count($args); $i < $j; $i++) { 797 $arg = array_shift($args); 798 $type = array_shift($signature); 799 switch ($type) { 800 case 'int': 801 case 'i4': 802 if (is_array($arg) || !is_int($arg)) { 803 $ok = false; 804 } 805 break; 806 case 'base64': 807 case 'string': 808 if (!is_string($arg)) { 809 $ok = false; 810 } 811 break; 812 case 'boolean': 813 if ($arg !== false && $arg !== true) { 814 $ok = false; 815 } 816 break; 817 case 'float': 818 case 'double': 819 if (!is_float($arg)) { 820 $ok = false; 821 } 822 break; 823 case 'date': 824 case 'dateTime.iso8601': 825 if (!is_a($arg, 'IXR_Date')) { 826 $ok = false; 827 } 828 break; 829 } 830 if (!$ok) { 831 return new IXR_Error(-32602, 'server error. invalid method parameters'); 832 } 833 } 834 // It passed the test - run the "real" method call 835 return parent::call($methodname, $argsbackup); 836 } 837 function methodSignature($method) { 838 if (!$this->hasMethod($method)) { 839 return new IXR_Error(-32601, 'server error. requested method "'.$method.'" not specified.'); 840 } 841 // We should be returning an array of types 842 $types = $this->signatures[$method]; 843 $return = array(); 844 foreach ($types as $type) { 845 switch ($type) { 846 case 'string': 847 $return[] = 'string'; 848 break; 849 case 'int': 850 case 'i4': 851 $return[] = 42; 852 break; 853 case 'double': 854 $return[] = 3.1415; 855 break; 856 case 'dateTime.iso8601': 857 $return[] = new IXR_Date(time()); 858 break; 859 case 'boolean': 860 $return[] = true; 861 break; 862 case 'base64': 863 $return[] = new IXR_Base64('base64'); 864 break; 865 case 'array': 866 $return[] = array('array'); 867 break; 868 case 'struct': 869 $return[] = array('struct' => 'struct'); 870 break; 871 } 872 } 873 return $return; 874 } 875 function methodHelp($method) { 876 return $this->help[$method]; 877 } 878 } 879 880 /** 881 * IXR_ClientMulticall 882 * 883 * @package IXR 884 * @since 1.5 885 */ 886 class IXR_ClientMulticall extends IXR_Client { 887 var $calls = array(); 888 function IXR_ClientMulticall($server, $path = false, $port = 80) { 889 parent::IXR_Client($server, $path, $port); 890 $this->useragent = 'The Incutio XML-RPC PHP Library (multicall client)'; 891 } 892 function addCall() { 893 $args = func_get_args(); 894 $methodName = array_shift($args); 895 $struct = array( 896 'methodName' => $methodName, 897 'params' => $args 898 ); 899 $this->calls[] = $struct; 900 } 901 function query() { 902 // Prepare multicall, then call the parent::query() method 903 return parent::query('system.multicall', $this->calls); 904 } 905 } 906 907 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Fri Jan 8 00:19:48 2010 | Cross-referenced by PHPXref 0.7 |