| 1 | Index: wp-includes/class-IXR.php |
|---|
| 2 | =================================================================== |
|---|
| 3 | --- wp-includes/class-IXR.php (revision 11893) |
|---|
| 4 | +++ wp-includes/class-IXR.php (working copy) |
|---|
| 5 | @@ -153,34 +153,41 @@ |
|---|
| 6 | var $_currentTagContents; |
|---|
| 7 | // The XML parser |
|---|
| 8 | var $_parser; |
|---|
| 9 | - function IXR_Message ($message) { |
|---|
| 10 | - $this->message = $message; |
|---|
| 11 | + function IXR_Message (&$message) { |
|---|
| 12 | + $this->message = &$message; |
|---|
| 13 | } |
|---|
| 14 | function parse() { |
|---|
| 15 | - // first remove the XML declaration |
|---|
| 16 | - $this->message = preg_replace('/<\?xml.*?\?'.'>/', '', $this->message); |
|---|
| 17 | + // first remove the XML declaration |
|---|
| 18 | + // this method avoids the RAM usage of preg_replace on very large messages |
|---|
| 19 | + $header = preg_replace( '/<\?xml.*?\?'.'>/', '', substr( $this->message, 0, 100 ), 1 ); |
|---|
| 20 | + $this->message = substr_replace($this->message, $header, 0, 100); |
|---|
| 21 | if (trim($this->message) == '') { |
|---|
| 22 | return false; |
|---|
| 23 | - } |
|---|
| 24 | + } |
|---|
| 25 | $this->_parser = xml_parser_create(); |
|---|
| 26 | // Set XML parser to take the case of tags in to account |
|---|
| 27 | xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false); |
|---|
| 28 | // Set XML parser callback functions |
|---|
| 29 | xml_set_object($this->_parser, $this); |
|---|
| 30 | xml_set_element_handler($this->_parser, 'tag_open', 'tag_close'); |
|---|
| 31 | - xml_set_character_data_handler($this->_parser, 'cdata'); |
|---|
| 32 | - if (!xml_parse($this->_parser, $this->message)) { |
|---|
| 33 | - /* die(sprintf('XML error: %s at line %d', |
|---|
| 34 | - xml_error_string(xml_get_error_code($this->_parser)), |
|---|
| 35 | - xml_get_current_line_number($this->_parser))); */ |
|---|
| 36 | - return false; |
|---|
| 37 | - } |
|---|
| 38 | - xml_parser_free($this->_parser); |
|---|
| 39 | + xml_set_character_data_handler($this->_parser, 'cdata'); |
|---|
| 40 | + $chunk_size = 262144; // 256Kb, parse in chunks to avoid the RAM usage on very large messages |
|---|
| 41 | + do { |
|---|
| 42 | + if ( strlen($this->message) <= $chunk_size ) |
|---|
| 43 | + $final=true; |
|---|
| 44 | + $part = substr( $this->message, 0, $chunk_size ); |
|---|
| 45 | + $this->message = substr( $this->message, $chunk_size ); |
|---|
| 46 | + if ( !xml_parse( $this->_parser, $part, $final ) ) |
|---|
| 47 | + return false; |
|---|
| 48 | + if ( $final ) |
|---|
| 49 | + break; |
|---|
| 50 | + } while ( true ); |
|---|
| 51 | + xml_parser_free($this->_parser); |
|---|
| 52 | // Grab the error messages, if any |
|---|
| 53 | if ($this->messageType == 'fault') { |
|---|
| 54 | $this->faultCode = $this->params[0]['faultCode']; |
|---|
| 55 | $this->faultString = $this->params[0]['faultString']; |
|---|
| 56 | - } |
|---|
| 57 | + } |
|---|
| 58 | return true; |
|---|
| 59 | } |
|---|
| 60 | function tag_open($parser, $tag, $attr) { |
|---|
| 61 | @@ -304,7 +311,7 @@ |
|---|
| 62 | header( 'Content-Type: text/plain' ); |
|---|
| 63 | die('XML-RPC server accepts POST requests only.'); |
|---|
| 64 | } |
|---|
| 65 | - $data = $HTTP_RAW_POST_DATA; |
|---|
| 66 | + $data = &$HTTP_RAW_POST_DATA; |
|---|
| 67 | } |
|---|
| 68 | $this->message = new IXR_Message($data); |
|---|
| 69 | if (!$this->message->parse()) { |
|---|