home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / CMS / drupal-6.0.exe / drupal-6.0 / includes / xmlrpcs.inc < prev   
Encoding:
Text File  |  2007-12-31  |  9.1 KB  |  314 lines

  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. }
  314.