| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: xmlrpcs.inc,v 1.24.2.4 2010/06/02 12:52:07 goba 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 if (!isset($xmlrpc_server->message->params)) { 68 $xmlrpc_server->message->params = array(); 69 } 70 xmlrpc_server_set($xmlrpc_server); 71 $result = xmlrpc_server_call($xmlrpc_server, $xmlrpc_server->message->methodname, $xmlrpc_server->message->params); 72 73 if (is_object($result) && !empty($result->is_error)) { 74 xmlrpc_server_error($result); 75 } 76 // Encode the result 77 $r = xmlrpc_value($result); 78 // Create the XML 79 $xml = ' 80 <methodResponse> 81 <params> 82 <param> 83 <value>'. 84 xmlrpc_value_get_xml($r) 85 .'</value> 86 </param> 87 </params> 88 </methodResponse> 89 90 '; 91 // Send it 92 xmlrpc_server_output($xml); 93 } 94 95 /** 96 * Throw an XML-RPC error. 97 * 98 * @param $error 99 * an error object OR integer error code 100 * @param $message 101 * description of error, used only if integer error code was passed 102 */ 103 function xmlrpc_server_error($error, $message = FALSE) { 104 if ($message && !is_object($error)) { 105 $error = xmlrpc_error($error, $message); 106 } 107 xmlrpc_server_output(xmlrpc_error_get_xml($error)); 108 } 109 110 function xmlrpc_server_output($xml) { 111 $xml = '<?xml version="1.0"?>'."\n". $xml; 112 header('Connection: close'); 113 header('Content-Length: '. strlen($xml)); 114 header('Content-Type: text/xml'); 115 header('Date: '. date('r')); 116 echo $xml; 117 exit; 118 } 119 120 /** 121 * Store a copy of the request temporarily. 122 * 123 * @param $xmlrpc_server 124 * Request object created by xmlrpc_server(). 125 */ 126 function xmlrpc_server_set($xmlrpc_server = NULL) { 127 static $server; 128 if (!isset($server)) { 129 $server = $xmlrpc_server; 130 } 131 return $server; 132 } 133 134 // Retrieve the stored request. 135 function xmlrpc_server_get() { 136 return xmlrpc_server_set(); 137 } 138 139 /** 140 * Dispatch the request and any parameters to the appropriate handler. 141 * 142 * @param $xmlrpc_server 143 * @param $methodname 144 * The external XML-RPC method name, e.g. 'system.methodHelp' 145 * @param $args 146 * Array containing any parameters that were sent along with the request. 147 */ 148 function xmlrpc_server_call($xmlrpc_server, $methodname, $args) { 149 // Make sure parameters are in an array 150 if ($args && !is_array($args)) { 151 $args = array($args); 152 } 153 // Has this method been mapped to a Drupal function by us or by modules? 154 if (!isset($xmlrpc_server->callbacks[$methodname])) { 155 return xmlrpc_error(-32601, t('Server error. Requested method @methodname not specified.', array("@methodname" => $xmlrpc_server->message->methodname))); 156 } 157 $method = $xmlrpc_server->callbacks[$methodname]; 158 $signature = $xmlrpc_server->signatures[$methodname]; 159 160 // If the method has a signature, validate the request against the signature 161 if (is_array($signature)) { 162 $ok = TRUE; 163 $return_type = array_shift($signature); 164 // Check the number of arguments 165 if (count($args) != count($signature)) { 166 return xmlrpc_error(-32602, t('Server error. Wrong number of method parameters.')); 167 } 168 // Check the argument types 169 foreach ($signature as $key => $type) { 170 $arg = $args[$key]; 171 switch ($type) { 172 case 'int': 173 case 'i4': 174 if (is_array($arg) || !is_int($arg)) { 175 $ok = FALSE; 176 } 177 break; 178 case 'base64': 179 case 'string': 180 if (!is_string($arg)) { 181 $ok = FALSE; 182 } 183 break; 184 case 'boolean': 185 if ($arg !== FALSE && $arg !== TRUE) { 186 $ok = FALSE; 187 } 188 break; 189 case 'float': 190 case 'double': 191 if (!is_float($arg)) { 192 $ok = FALSE; 193 } 194 break; 195 case 'date': 196 case 'dateTime.iso8601': 197 if (!$arg->is_date) { 198 $ok = FALSE; 199 } 200 break; 201 } 202 if (!$ok) { 203 return xmlrpc_error(-32602, t('Server error. Invalid method parameters.')); 204 } 205 } 206 } 207 208 if (!function_exists($method)) { 209 return xmlrpc_error(-32601, t('Server error. Requested function @method does not exist.', array("@method" => $method))); 210 } 211 // Call the mapped function 212 return call_user_func_array($method, $args); 213 } 214 215 function xmlrpc_server_multicall($methodcalls) { 216 // See http://www.xmlrpc.com/discuss/msgReader$1208 217 $return = array(); 218 $xmlrpc_server = xmlrpc_server_get(); 219 foreach ($methodcalls as $call) { 220 $ok = TRUE; 221 if (!isset($call['methodName']) || !isset($call['params'])) { 222 $result = xmlrpc_error(3, t('Invalid syntax for system.multicall.')); 223 $ok = FALSE; 224 } 225 $method = $call['methodName']; 226 $params = $call['params']; 227 if ($method == 'system.multicall') { 228 $result = xmlrpc_error(-32600, t('Recursive calls to system.multicall are forbidden.')); 229 } 230 elseif ($ok) { 231 $result = xmlrpc_server_call($xmlrpc_server, $method, $params); 232 } 233 if (is_object($result) && !empty($result->is_error)) { 234 $return[] = array( 235 'faultCode' => $result->code, 236 'faultString' => $result->message 237 ); 238 } 239 else { 240 $return[] = $result; 241 } 242 } 243 return $return; 244 } 245 246 247 /** 248 * XML-RPC method system.listMethods maps to this function. 249 */ 250 function xmlrpc_server_list_methods() { 251 $xmlrpc_server = xmlrpc_server_get(); 252 return array_keys($xmlrpc_server->callbacks); 253 } 254 255 /** 256 * XML-RPC method system.getCapabilities maps to this function. 257 * See http://groups.yahoo.com/group/xml-rpc/message/2897 258 */ 259 function xmlrpc_server_get_capabilities() { 260 return array( 261 'xmlrpc' => array( 262 'specUrl' => 'http://www.xmlrpc.com/spec', 263 'specVersion' => 1 264 ), 265 'faults_interop' => array( 266 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php', 267 'specVersion' => 20010516 268 ), 269 'system.multicall' => array( 270 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208', 271 'specVersion' => 1 272 ), 273 'introspection' => array( 274 'specUrl' => 'http://scripts.incutio.com/xmlrpc/introspection.html', 275 'specVersion' => 1 276 ) 277 ); 278 } 279 280 /** 281 * XML-RPC method system.methodSignature maps to this function. 282 * 283 * @param $methodname 284 * Name of method for which we return a method signature. 285 * @return array 286 * An array of types representing the method signature of the 287 * function that the methodname maps to. The methodSignature of 288 * this function is 'array', 'string' because it takes an array 289 * and returns a string. 290 */ 291 function xmlrpc_server_method_signature($methodname) { 292 $xmlrpc_server = xmlrpc_server_get(); 293 if (!isset($xmlrpc_server->callbacks[$methodname])) { 294 return xmlrpc_error(-32601, t('Server error. Requested method @methodname not specified.', array("@methodname" => $methodname))); 295 } 296 if (!is_array($xmlrpc_server->signatures[$methodname])) { 297 return xmlrpc_error(-32601, t('Server error. Requested method @methodname signature not specified.', array("@methodname" => $methodname))); 298 } 299 // We array of types 300 $return = array(); 301 foreach ($xmlrpc_server->signatures[$methodname] as $type) { 302 $return[] = $type; 303 } 304 return $return; 305 } 306 307 /** 308 * XML-RPC method system.methodHelp maps to this function. 309 * 310 * @param $method 311 * Name of method for which we return a help string. 312 */ 313 function xmlrpc_server_method_help($method) { 314 $xmlrpc_server = xmlrpc_server_get(); 315 return $xmlrpc_server->help[$method]; 316 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |