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