Title: IXR_Message
Published: July 6, 2022
Last modified: August 20, 2026

---

# class IXR_Message {}

## In this article

 * [Methods](https://developer.wordpress.org/reference/classes/IXR_Message/?output_format=md#methods)
 * [Source](https://developer.wordpress.org/reference/classes/IXR_Message/?output_format=md#source)
 * [Changelog](https://developer.wordpress.org/reference/classes/IXR_Message/?output_format=md#changelog)

[ Back to top](https://developer.wordpress.org/reference/classes/IXR_Message/?output_format=md#wp--skip-link--target)

IXR_MESSAGE

## 󠀁[Methods](https://developer.wordpress.org/reference/classes/IXR_Message/?output_format=md#methods)󠁿

| Name | Description | 
| [IXR_Message::__construct](https://developer.wordpress.org/reference/classes/ixr_message/__construct/) | PHP5 constructor. | 
| [IXR_Message::cdata](https://developer.wordpress.org/reference/classes/ixr_message/cdata/) | – | 
| [IXR_Message::IXR_Message](https://developer.wordpress.org/reference/classes/ixr_message/ixr_message/) | PHP4 constructor. | 
| [IXR_Message::parse](https://developer.wordpress.org/reference/classes/ixr_message/parse/) | – | 
| [IXR_Message::tag_close](https://developer.wordpress.org/reference/classes/ixr_message/tag_close/) | – | 
| [IXR_Message::tag_open](https://developer.wordpress.org/reference/classes/ixr_message/tag_open/) | – |

## 󠀁[Source](https://developer.wordpress.org/reference/classes/IXR_Message/?output_format=md#source)󠁿

    ```php
    class IXR_Message
    {
        var $message     = false;
        var $messageType = false;  // methodCall / methodResponse / fault
        var $faultCode   = false;
        var $faultString = false;
        var $methodName  = '';
        var $params      = array();

        // Current variable stacks
        var $_arraystructs = array();   // The stack used to keep track of the current array/struct
        var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array
        var $_currentStructName = array();  // A stack as well
        var $_param;
        var $_value;
        var $_currentTag;
        var $_currentTagContents;
        // The XML parser
        var $_parser;

    	/**
    	 * PHP5 constructor.
    	 */
        function __construct( $message )
        {
            $this->message =& $message;
        }

    	/**
    	 * PHP4 constructor.
    	 */
    	public function IXR_Message( $message ) {
    		self::__construct( $message );
    	}

        function parse()
        {
            if ( ! function_exists( 'xml_parser_create' ) ) {
                trigger_error( __( "PHP's XML extension is not available. Please contact your hosting provider to enable PHP's XML extension." ) );
                return false;
            }

            // first remove the XML declaration
            // merged from WP #10698 - this method avoids the RAM usage of preg_replace on very large messages
            $header = preg_replace( '/<\?xml.*?\?'.'>/s', '', substr( $this->message, 0, 100 ), 1 );
            $this->message = trim( substr_replace( $this->message, $header, 0, 100 ) );
            if ( '' == $this->message ) {
                return false;
            }

            // Then remove the DOCTYPE
            $header = preg_replace( '/^<!DOCTYPE[^>]*+>/i', '', substr( $this->message, 0, 200 ), 1 );
            $this->message = trim( substr_replace( $this->message, $header, 0, 200 ) );
            if ( '' == $this->message ) {
                return false;
            }

            // Check that the root tag is valid
            $root_tag = substr( $this->message, 0, strcspn( substr( $this->message, 0, 20 ), "> \t\r\n" ) );
            if ( '<!DOCTYPE' === strtoupper( $root_tag ) ) {
                return false;
            }
            if ( ! in_array( $root_tag, array( '<methodCall', '<methodResponse', '<fault' ) ) ) {
                return false;
            }

            // Bail if there are too many elements to parse
            $element_limit = 30000;
            if ( function_exists( 'apply_filters' ) ) {
                /**
                 * Filters the number of elements to parse in an XML-RPC response.
                 *
                 * @since 4.0.0
                 *
                 * @param int $element_limit Default elements limit.
                 */
                $element_limit = apply_filters( 'xmlrpc_element_limit', $element_limit );
            }
            if ( $element_limit && 2 * $element_limit < substr_count( $this->message, '<' ) ) {
                return false;
            }

            $this->_parser = xml_parser_create();
            // Set XML parser to take the case of tags in to account
            xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false);
            // Set XML parser callback functions
            xml_set_element_handler($this->_parser, array($this, 'tag_open'), array($this, 'tag_close'));
            xml_set_character_data_handler($this->_parser, array($this, 'cdata'));

            // 256Kb, parse in chunks to avoid the RAM usage on very large messages
            $chunk_size = 262144;

            /**
             * Filters the chunk size that can be used to parse an XML-RPC response message.
             *
             * @since 4.4.0
             *
             * @param int $chunk_size Chunk size to parse in bytes.
             */
            $chunk_size = apply_filters( 'xmlrpc_chunk_parsing_size', $chunk_size );

            $final = false;

            do {
                if (strlen($this->message) <= $chunk_size) {
                    $final = true;
                }

                $part = substr($this->message, 0, $chunk_size);
                $this->message = substr($this->message, $chunk_size);

                if (!xml_parse($this->_parser, $part, $final)) {
                    if (PHP_VERSION_ID < 80000) { // xml_parser_free() has no effect as of PHP 8.0.
                        xml_parser_free($this->_parser);
                    }

                    unset($this->_parser);
                    return false;
                }

                if ($final) {
                    break;
                }
            } while (true);

            if (PHP_VERSION_ID < 80000) { // xml_parser_free() has no effect as of PHP 8.0.
                xml_parser_free($this->_parser);
            }

            unset($this->_parser);

            // Grab the error messages, if any
            if ($this->messageType == 'fault') {
                $this->faultCode = $this->params[0]['faultCode'];
                $this->faultString = $this->params[0]['faultString'];
            }
            return true;
        }

        function tag_open($parser, $tag, $attr)
        {
            $this->_currentTagContents = '';
            $this->_currentTag = $tag;
            switch($tag) {
                case 'methodCall':
                case 'methodResponse':
                case 'fault':
                    $this->messageType = $tag;
                    break;
                    /* Deal with stacks of arrays and structs */
                case 'data':    // data is to all intents and puposes more interesting than array
                    $this->_arraystructstypes[] = 'array';
                    $this->_arraystructs[] = array();
                    break;
                case 'struct':
                    $this->_arraystructstypes[] = 'struct';
                    $this->_arraystructs[] = array();
                    break;
            }
        }

        function cdata($parser, $cdata)
        {
            $this->_currentTagContents .= $cdata;
        }

        function tag_close($parser, $tag)
        {
            $valueFlag = false;
            switch($tag) {
                case 'int':
                case 'i4':
                    $value = (int)trim($this->_currentTagContents);
                    $valueFlag = true;
                    break;
                case 'double':
                    $value = (float)trim($this->_currentTagContents);
                    $valueFlag = true;
                    break;
                case 'string':
                    $value = (string)trim($this->_currentTagContents);
                    $valueFlag = true;
                    break;
                case 'dateTime.iso8601':
                    $value = new IXR_Date(trim($this->_currentTagContents));
                    $valueFlag = true;
                    break;
                case 'value':
                    // "If no type is indicated, the type is string."
                    if (trim($this->_currentTagContents) != '') {
                        $value = (string)$this->_currentTagContents;
                        $valueFlag = true;
                    }
                    break;
                case 'boolean':
                    $value = (bool)trim($this->_currentTagContents);
                    $valueFlag = true;
                    break;
                case 'base64':
                    $value = base64_decode($this->_currentTagContents);
                    $valueFlag = true;
                    break;
                    /* Deal with stacks of arrays and structs */
                case 'data':
                case 'struct':
                    $value = array_pop($this->_arraystructs);
                    array_pop($this->_arraystructstypes);
                    $valueFlag = true;
                    break;
                case 'member':
                    array_pop($this->_currentStructName);
                    break;
                case 'name':
                    $this->_currentStructName[] = trim($this->_currentTagContents);
                    break;
                case 'methodName':
                    $this->methodName = trim($this->_currentTagContents);
                    break;
            }

            if ($valueFlag) {
                if (count($this->_arraystructs) > 0) {
                    // Add value to struct or array
                    if ($this->_arraystructstypes[count($this->_arraystructstypes)-1] == 'struct') {
                        // Add to struct
                        $this->_arraystructs[count($this->_arraystructs)-1][$this->_currentStructName[count($this->_currentStructName)-1]] = $value;
                    } else {
                        // Add to array
                        $this->_arraystructs[count($this->_arraystructs)-1][] = $value;
                    }
                } else {
                    // Just add as a parameter
                    $this->params[] = $value;
                }
            }
            $this->_currentTagContents = '';
        }
    }
    ```

[View all references](https://developer.wordpress.org/reference/files/wp-includes/ixr/class-ixr-message.php/)
[View on Trac](https://core.trac.wordpress.org/browser/tags/7.1/src/wp-includes/IXR/class-IXR-message.php#L10)
[View on GitHub](https://github.com/WordPress/wordpress-develop/blob/7.1/src/wp-includes/IXR/class-IXR-message.php#L10-L247)

## 󠀁[Changelog](https://developer.wordpress.org/reference/classes/IXR_Message/?output_format=md#changelog)󠁿

| Version | Description | 
| [1.5.0](https://developer.wordpress.org/reference/since/1.5.0/) | Introduced. |

## User Contributed Notes

You must [log in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Fclasses%2Fixr_message%2F)
before being able to contribute a note or feedback.