1<?php
2
3/**
4 * IXR_IntrospectionServer
5 *
6 * @package IXR
7 * @since 1.5.0
8 */
9class IXR_IntrospectionServer extends IXR_Server
10{
11 var $signatures;
12 var $help;
13
14 /**
15 * PHP5 constructor.
16 */
17 function __construct()
18 {
19 $this->setCallbacks();
20 $this->setCapabilities();
21 $this->capabilities['introspection'] = array(
22 'specUrl' => 'https://web.archive.org/web/20050404090342/http://xmlrpc.usefulinc.com/doc/reserved.html',
23 'specVersion' => 1
24 );
25 $this->addCallback(
26 'system.methodSignature',
27 'this:methodSignature',
28 array('array', 'string'),
29 'Returns an array describing the return type and required parameters of a method'
30 );
31 $this->addCallback(
32 'system.getCapabilities',
33 'this:getCapabilities',
34 array('struct'),
35 'Returns a struct describing the XML-RPC specifications supported by this server'
36 );
37 $this->addCallback(
38 'system.listMethods',
39 'this:listMethods',
40 array('array'),
41 'Returns an array of available methods on this server'
42 );
43 $this->addCallback(
44 'system.methodHelp',
45 'this:methodHelp',
46 array('string', 'string'),
47 'Returns a documentation string for the specified method'
48 );
49 }
50
51 /**
52 * PHP4 constructor.
53 */
54 public function IXR_IntrospectionServer() {
55 self::__construct();
56 }
57
58 function addCallback($method, $callback, $args, $help)
59 {
60 $this->callbacks[$method] = $callback;
61 $this->signatures[$method] = $args;
62 $this->help[$method] = $help;
63 }
64
65 function call($methodname, $args)
66 {
67 // Make sure it's in an array
68 if ($args && !is_array($args)) {
69 $args = array($args);
70 }
71
72 // Over-rides default call method, adds signature check
73 if (!$this->hasMethod($methodname)) {
74 return new IXR_Error(-32601, 'server error. requested method "'.$this->message->methodName.'" not specified.');
75 }
76 $method = $this->callbacks[$methodname];
77 $signature = $this->signatures[$methodname];
78 $returnType = array_shift($signature);
79
80 // Check the number of arguments
81 if (count($args) != count($signature)) {
82 return new IXR_Error(-32602, 'server error. wrong number of method parameters');
83 }
84
85 // Check the argument types
86 $ok = true;
87 $argsbackup = $args;
88 for ($i = 0, $j = count($args); $i < $j; $i++) {
89 $arg = array_shift($args);
90 $type = array_shift($signature);
91 switch ($type) {
92 case 'int':
93 case 'i4':
94 if (is_array($arg) || !is_int($arg)) {
95 $ok = false;
96 }
97 break;
98 case 'base64':
99 case 'string':
100 if (!is_string($arg)) {
101 $ok = false;
102 }
103 break;
104 case 'boolean':
105 if ($arg !== false && $arg !== true) {
106 $ok = false;
107 }
108 break;
109 case 'float':
110 case 'double':
111 if (!is_float($arg)) {
112 $ok = false;
113 }
114 break;
115 case 'date':
116 case 'dateTime.iso8601':
117 if (!is_a($arg, 'IXR_Date')) {
118 $ok = false;
119 }
120 break;
121 }
122 if (!$ok) {
123 return new IXR_Error(-32602, 'server error. invalid method parameters');
124 }
125 }
126 // It passed the test - run the "real" method call
127 return parent::call($methodname, $argsbackup);
128 }
129
130 function methodSignature($method)
131 {
132 if (!$this->hasMethod($method)) {
133 return new IXR_Error(-32601, 'server error. requested method "'.$method.'" not specified.');
134 }
135 // We should be returning an array of types
136 $types = $this->signatures[$method];
137 $return = array();
138 foreach ($types as $type) {
139 switch ($type) {
140 case 'string':
141 $return[] = 'string';
142 break;
143 case 'int':
144 case 'i4':
145 $return[] = 42;
146 break;
147 case 'double':
148 $return[] = 3.1415;
149 break;
150 case 'dateTime.iso8601':
151 $return[] = new IXR_Date(time());
152 break;
153 case 'boolean':
154 $return[] = true;
155 break;
156 case 'base64':
157 $return[] = new IXR_Base64('base64');
158 break;
159 case 'array':
160 $return[] = array('array');
161 break;
162 case 'struct':
163 $return[] = array('struct' => 'struct');
164 break;
165 }
166 }
167 return $return;
168 }
169
170 function methodHelp($method)
171 {
172 return $this->help[$method];
173 }
174}
175