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