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