xmlrpcs.inc

  1. drupal
    1. 4.6 includes/xmlrpcs.inc
    2. 4.7 includes/xmlrpcs.inc
    3. 5 includes/xmlrpcs.inc
    4. 6 includes/xmlrpcs.inc
    5. 7 includes/xmlrpcs.inc
    6. 8 core/includes/xmlrpcs.inc

Functions & methods

NameDescription
xmlrpc_serverThe main entry point for XML-RPC requests.
xmlrpc_server_callDispatch the request and any parameters to the appropriate handler.
xmlrpc_server_errorThrow an XML-RPC error.
xmlrpc_server_get
xmlrpc_server_get_capabilitiesXML-RPC method system.getCapabilities maps to this function. See http://groups.yahoo.com/group/xml-rpc/message/2897
xmlrpc_server_list_methodsXML-RPC method system.listMethods maps to this function.
xmlrpc_server_method_helpXML-RPC method system.methodHelp maps to this function.
xmlrpc_server_method_signatureXML-RPC method system.methodSignature maps to this function.
xmlrpc_server_multicall
xmlrpc_server_output
xmlrpc_server_setStore a copy of the request temporarily.

File

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