source: trunk/www.guidonia.net/wp/wp-includes/class-IXR.php@ 44

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