Mercurial > defr > drupal > core
comparison includes/xmlrpcs.inc @ 1:c1f4ac30525a 6.0
Drupal 6.0
author | Franck Deroche <webmaster@defr.org> |
---|---|
date | Tue, 23 Dec 2008 14:28:28 +0100 |
parents | |
children | fff6d4c8c043 |
comparison
equal
deleted
inserted
replaced
0:5a113a1c4740 | 1:c1f4ac30525a |
---|---|
1 <?php | |
2 // $Id: xmlrpcs.inc,v 1.24 2007/12/31 08:54:36 dries Exp $ | |
3 | |
4 /** | |
5 * The main entry point for XML-RPC requests. | |
6 * | |
7 * @param $callbacks | |
8 * Array of external XML-RPC method names with the callbacks they map to. | |
9 */ | |
10 function xmlrpc_server($callbacks) { | |
11 $xmlrpc_server = new stdClass(); | |
12 // Define built-in XML-RPC method names | |
13 $defaults = array( | |
14 'system.multicall' => 'xmlrpc_server_multicall', | |
15 array( | |
16 'system.methodSignature', | |
17 'xmlrpc_server_method_signature', | |
18 array('array', 'string'), | |
19 'Returns an array describing the return type and required parameters of a method.' | |
20 ), | |
21 array( | |
22 'system.getCapabilities', | |
23 'xmlrpc_server_get_capabilities', | |
24 array('struct'), | |
25 'Returns a struct describing the XML-RPC specifications supported by this server.' | |
26 ), | |
27 array( | |
28 'system.listMethods', | |
29 'xmlrpc_server_list_methods', | |
30 array('array'), | |
31 'Returns an array of available methods on this server.'), | |
32 array( | |
33 'system.methodHelp', | |
34 'xmlrpc_server_method_help', | |
35 array('string', 'string'), | |
36 'Returns a documentation string for the specified method.') | |
37 ); | |
38 // We build an array of all method names by combining the built-ins | |
39 // with those defined by modules implementing the _xmlrpc hook. | |
40 // Built-in methods are overridable. | |
41 foreach (array_merge($defaults, (array)$callbacks) as $key => $callback) { | |
42 // we could check for is_array($callback) | |
43 if (is_int($key)) { | |
44 $method = $callback[0]; | |
45 $xmlrpc_server->callbacks[$method] = $callback[1]; | |
46 $xmlrpc_server->signatures[$method] = $callback[2]; | |
47 $xmlrpc_server->help[$method] = $callback[3]; | |
48 } | |
49 else { | |
50 $xmlrpc_server->callbacks[$key] = $callback; | |
51 $xmlrpc_server->signatures[$key] = ''; | |
52 $xmlrpc_server->help[$key] = ''; | |
53 } | |
54 } | |
55 | |
56 $data = file_get_contents('php://input'); | |
57 if (!$data) { | |
58 die('XML-RPC server accepts POST requests only.'); | |
59 } | |
60 $xmlrpc_server->message = xmlrpc_message($data); | |
61 if (!xmlrpc_message_parse($xmlrpc_server->message)) { | |
62 xmlrpc_server_error(-32700, t('Parse error. Request not well formed.')); | |
63 } | |
64 if ($xmlrpc_server->message->messagetype != 'methodCall') { | |
65 xmlrpc_server_error(-32600, t('Server error. Invalid XML-RPC. Request must be a methodCall.')); | |
66 } | |
67 xmlrpc_server_set($xmlrpc_server); | |
68 $result = xmlrpc_server_call($xmlrpc_server, $xmlrpc_server->message->methodname, $xmlrpc_server->message->params); | |
69 | |
70 if ($result->is_error) { | |
71 xmlrpc_server_error($result); | |
72 } | |
73 // Encode the result | |
74 $r = xmlrpc_value($result); | |
75 // Create the XML | |
76 $xml = ' | |
77 <methodResponse> | |
78 <params> | |
79 <param> | |
80 <value>'. | |
81 xmlrpc_value_get_xml($r) | |
82 .'</value> | |
83 </param> | |
84 </params> | |
85 </methodResponse> | |
86 | |
87 '; | |
88 // Send it | |
89 xmlrpc_server_output($xml); | |
90 } | |
91 | |
92 /** | |
93 * Throw an XML-RPC error. | |
94 * | |
95 * @param $error | |
96 * an error object OR integer error code | |
97 * @param $message | |
98 * description of error, used only if integer error code was passed | |
99 */ | |
100 function xmlrpc_server_error($error, $message = FALSE) { | |
101 if ($message && !is_object($error)) { | |
102 $error = xmlrpc_error($error, $message); | |
103 } | |
104 xmlrpc_server_output(xmlrpc_error_get_xml($error)); | |
105 } | |
106 | |
107 function xmlrpc_server_output($xml) { | |
108 $xml = '<?xml version="1.0"?>'."\n". $xml; | |
109 header('Connection: close'); | |
110 header('Content-Length: '. strlen($xml)); | |
111 header('Content-Type: text/xml'); | |
112 header('Date: '. date('r')); | |
113 echo $xml; | |
114 exit; | |
115 } | |
116 | |
117 /** | |
118 * Store a copy of the request temporarily. | |
119 * | |
120 * @param $xmlrpc_server | |
121 * Request object created by xmlrpc_server(). | |
122 */ | |
123 function xmlrpc_server_set($xmlrpc_server = NULL) { | |
124 static $server; | |
125 if (!isset($server)) { | |
126 $server = $xmlrpc_server; | |
127 } | |
128 return $server; | |
129 } | |
130 | |
131 // Retrieve the stored request. | |
132 function xmlrpc_server_get() { | |
133 return xmlrpc_server_set(); | |
134 } | |
135 | |
136 /** | |
137 * Dispatch the request and any parameters to the appropriate handler. | |
138 * | |
139 * @param $xmlrpc_server | |
140 * @param $methodname | |
141 * The external XML-RPC method name, e.g. 'system.methodHelp' | |
142 * @param $args | |
143 * Array containing any parameters that were sent along with the request. | |
144 */ | |
145 function xmlrpc_server_call($xmlrpc_server, $methodname, $args) { | |
146 // Make sure parameters are in an array | |
147 if ($args && !is_array($args)) { | |
148 $args = array($args); | |
149 } | |
150 // Has this method been mapped to a Drupal function by us or by modules? | |
151 if (!isset($xmlrpc_server->callbacks[$methodname])) { | |
152 return xmlrpc_error(-32601, t('Server error. Requested method %methodname not specified.', array("%methodname" => $xmlrpc_server->message->methodname))); | |
153 } | |
154 $method = $xmlrpc_server->callbacks[$methodname]; | |
155 $signature = $xmlrpc_server->signatures[$methodname]; | |
156 | |
157 // If the method has a signature, validate the request against the signature | |
158 if (is_array($signature)) { | |
159 $ok = TRUE; | |
160 $return_type = array_shift($signature); | |
161 // Check the number of arguments | |
162 if (count($args) != count($signature)) { | |
163 return xmlrpc_error(-32602, t('Server error. Wrong number of method parameters.')); | |
164 } | |
165 // Check the argument types | |
166 foreach ($signature as $key => $type) { | |
167 $arg = $args[$key]; | |
168 switch ($type) { | |
169 case 'int': | |
170 case 'i4': | |
171 if (is_array($arg) || !is_int($arg)) { | |
172 $ok = FALSE; | |
173 } | |
174 break; | |
175 case 'base64': | |
176 case 'string': | |
177 if (!is_string($arg)) { | |
178 $ok = FALSE; | |
179 } | |
180 break; | |
181 case 'boolean': | |
182 if ($arg !== FALSE && $arg !== TRUE) { | |
183 $ok = FALSE; | |
184 } | |
185 break; | |
186 case 'float': | |
187 case 'double': | |
188 if (!is_float($arg)) { | |
189 $ok = FALSE; | |
190 } | |
191 break; | |
192 case 'date': | |
193 case 'dateTime.iso8601': | |
194 if (!$arg->is_date) { | |
195 $ok = FALSE; | |
196 } | |
197 break; | |
198 } | |
199 if (!$ok) { | |
200 return xmlrpc_error(-32602, t('Server error. Invalid method parameters.')); | |
201 } | |
202 } | |
203 } | |
204 | |
205 if (!function_exists($method)) { | |
206 return xmlrpc_error(-32601, t('Server error. Requested function %method does not exist.', array("%method" => $method))); | |
207 } | |
208 // Call the mapped function | |
209 return call_user_func_array($method, $args); | |
210 } | |
211 | |
212 function xmlrpc_server_multicall($methodcalls) { | |
213 // See http://www.xmlrpc.com/discuss/msgReader$1208 | |
214 $return = array(); | |
215 $xmlrpc_server = xmlrpc_server_get(); | |
216 foreach ($methodcalls as $call) { | |
217 $ok = TRUE; | |
218 if (!isset($call['methodName']) || !isset($call['params'])) { | |
219 $result = xmlrpc_error(3, t('Invalid syntax for system.multicall.')); | |
220 $ok = FALSE; | |
221 } | |
222 $method = $call['methodName']; | |
223 $params = $call['params']; | |
224 if ($method == 'system.multicall') { | |
225 $result = xmlrpc_error(-32600, t('Recursive calls to system.multicall are forbidden.')); | |
226 } | |
227 elseif ($ok) { | |
228 $result = xmlrpc_server_call($xmlrpc_server, $method, $params); | |
229 } | |
230 if ($result->is_error) { | |
231 $return[] = array( | |
232 'faultCode' => $result->code, | |
233 'faultString' => $result->message | |
234 ); | |
235 } | |
236 else { | |
237 $return[] = $result; | |
238 } | |
239 } | |
240 return $return; | |
241 } | |
242 | |
243 | |
244 /** | |
245 * XML-RPC method system.listMethods maps to this function. | |
246 */ | |
247 function xmlrpc_server_list_methods() { | |
248 $xmlrpc_server = xmlrpc_server_get(); | |
249 return array_keys($xmlrpc_server->callbacks); | |
250 } | |
251 | |
252 /** | |
253 * XML-RPC method system.getCapabilities maps to this function. | |
254 * See http://groups.yahoo.com/group/xml-rpc/message/2897 | |
255 */ | |
256 function xmlrpc_server_get_capabilities() { | |
257 return array( | |
258 'xmlrpc' => array( | |
259 'specUrl' => 'http://www.xmlrpc.com/spec', | |
260 'specVersion' => 1 | |
261 ), | |
262 'faults_interop' => array( | |
263 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php', | |
264 'specVersion' => 20010516 | |
265 ), | |
266 'system.multicall' => array( | |
267 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208', | |
268 'specVersion' => 1 | |
269 ), | |
270 'introspection' => array( | |
271 'specUrl' => 'http://scripts.incutio.com/xmlrpc/introspection.html', | |
272 'specVersion' => 1 | |
273 ) | |
274 ); | |
275 } | |
276 | |
277 /** | |
278 * XML-RPC method system.methodSignature maps to this function. | |
279 * | |
280 * @param $methodname | |
281 * Name of method for which we return a method signature. | |
282 * @return array | |
283 * An array of types representing the method signature of the | |
284 * function that the methodname maps to. The methodSignature of | |
285 * this function is 'array', 'string' because it takes an array | |
286 * and returns a string. | |
287 */ | |
288 function xmlrpc_server_method_signature($methodname) { | |
289 $xmlrpc_server = xmlrpc_server_get(); | |
290 if (!isset($xmlrpc_server->callbacks[$methodname])) { | |
291 return xmlrpc_error(-32601, t('Server error. Requested method %methodname not specified.', array("%methodname" => $methodname))); | |
292 } | |
293 if (!is_array($xmlrpc_server->signatures[$methodname])) { | |
294 return xmlrpc_error(-32601, t('Server error. Requested method %methodname signature not specified.', array("%methodname" => $methodname))); | |
295 } | |
296 // We array of types | |
297 $return = array(); | |
298 foreach ($xmlrpc_server->signatures[$methodname] as $type) { | |
299 $return[] = $type; | |
300 } | |
301 return $return; | |
302 } | |
303 | |
304 /** | |
305 * XML-RPC method system.methodHelp maps to this function. | |
306 * | |
307 * @param $method | |
308 * Name of method for which we return a help string. | |
309 */ | |
310 function xmlrpc_server_method_help($method) { | |
311 $xmlrpc_server = xmlrpc_server_get(); | |
312 return $xmlrpc_server->help[$method]; | |
313 } |