You are here

function xmlrpc_message_parse in Drupal 6

Same name and namespace in other branches
  1. 4 includes/xmlrpc.inc \xmlrpc_message_parse()
  2. 5 includes/xmlrpc.inc \xmlrpc_message_parse()
  3. 7 includes/xmlrpc.inc \xmlrpc_message_parse()

Parse an XML-RPC message. If parsing fails, the faultCode and faultString will be added to the message object.

Parameters

$xmlrpc_message: Object generated by xmlrpc_message()

Return value

TRUE if parsing succeeded; FALSE otherwise

2 calls to xmlrpc_message_parse()
xmlrpc_server in includes/xmlrpcs.inc
The main entry point for XML-RPC requests.
_xmlrpc in includes/xmlrpc.inc
Execute an XML remote procedural call. This is private function; call xmlrpc() in common.inc instead of this function.

File

includes/xmlrpc.inc, line 158
Drupal XML-RPC library. Based on the IXR - The Incutio XML-RPC Library - (c) Incutio Ltd 2002-2005 Version 1.7 (beta) - Simon Willison, 23rd May 2005 Site: http://scripts.incutio.com/xmlrpc/ Manual: http://scripts.incutio.com/xmlrpc/manual.php This…

Code

function xmlrpc_message_parse(&$xmlrpc_message) {
  $xmlrpc_message->_parser = xml_parser_create();

  // Set XML parser to take the case of tags into account.
  xml_parser_set_option($xmlrpc_message->_parser, XML_OPTION_CASE_FOLDING, FALSE);

  // Set XML parser callback functions
  xml_set_element_handler($xmlrpc_message->_parser, 'xmlrpc_message_tag_open', 'xmlrpc_message_tag_close');
  xml_set_character_data_handler($xmlrpc_message->_parser, 'xmlrpc_message_cdata');
  xmlrpc_message_set($xmlrpc_message);

  // Strip XML declaration.
  $header = preg_replace('/<\\?xml.*?\\?' . '>/s', '', substr($xmlrpc_message->message, 0, 100), 1);
  $xml = trim(substr_replace($xmlrpc_message->message, $header, 0, 100));
  if ($xml == '') {
    return FALSE;
  }

  // Strip DTD.
  $header = preg_replace('/^<!DOCTYPE[^>]*+>/i', '', substr($xml, 0, 200), 1);
  $xml = trim(substr_replace($xml, $header, 0, 200));
  if ($xml == '') {
    return FALSE;
  }

  // Confirm the XML now starts with a valid root tag. A root tag can end in [> \t\r\n]
  $root_tag = substr($xml, 0, strcspn(substr($xml, 0, 20), "> \t\r\n"));

  // Reject a second DTD.
  if (strtoupper($root_tag) == '<!DOCTYPE') {
    return FALSE;
  }
  if (!in_array($root_tag, array(
    '<methodCall',
    '<methodResponse',
    '<fault',
  ))) {
    return FALSE;
  }

  // Skip parsing if there is an unreasonably large number of tags.
  // substr_count() has much better performance (compared to preg_match_all())
  // for large payloads but is less accurate, so we check for twice the desired
  // number of allowed tags (to take into account opening/closing tags as well
  // as false positives).
  if (substr_count($xml, '<') > 2 * variable_get('xmlrpc_message_maximum_tag_count', 30000)) {
    return FALSE;
  }
  if (!xml_parse($xmlrpc_message->_parser, $xml)) {
    return FALSE;
  }
  xml_parser_free($xmlrpc_message->_parser);

  // Grab the error messages, if any
  $xmlrpc_message = xmlrpc_message_get();
  if (!isset($xmlrpc_message->messagetype)) {
    return FALSE;
  }
  elseif ($xmlrpc_message->messagetype == 'fault') {
    $xmlrpc_message->fault_code = $xmlrpc_message->params[0]['faultCode'];
    $xmlrpc_message->fault_string = $xmlrpc_message->params[0]['faultString'];
  }
  return TRUE;
}