[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * IXR_MESSAGE 5 * 6 * @package IXR 7 * @since 1.5.0 8 * 9 */ 10 class IXR_Message 11 { 12 var $message = false; 13 var $messageType = false; // methodCall / methodResponse / fault 14 var $faultCode = false; 15 var $faultString = false; 16 var $methodName = ''; 17 var $params = array(); 18 19 // Current variable stacks 20 var $_arraystructs = array(); // The stack used to keep track of the current array/struct 21 var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array 22 var $_currentStructName = array(); // A stack as well 23 var $_param; 24 var $_value; 25 var $_currentTag; 26 var $_currentTagContents; 27 // The XML parser 28 var $_parser; 29 30 /** 31 * PHP5 constructor. 32 */ 33 function __construct( $message ) 34 { 35 $this->message =& $message; 36 } 37 38 /** 39 * PHP4 constructor. 40 */ 41 public function IXR_Message( $message ) { 42 self::__construct( $message ); 43 } 44 45 function parse() 46 { 47 if ( ! function_exists( 'xml_parser_create' ) ) { 48 trigger_error( __( "PHP's XML extension is not available. Please contact your hosting provider to enable PHP's XML extension." ) ); 49 return false; 50 } 51 52 // first remove the XML declaration 53 // merged from WP #10698 - this method avoids the RAM usage of preg_replace on very large messages 54 $header = preg_replace( '/<\?xml.*?\?'.'>/s', '', substr( $this->message, 0, 100 ), 1 ); 55 $this->message = trim( substr_replace( $this->message, $header, 0, 100 ) ); 56 if ( '' == $this->message ) { 57 return false; 58 } 59 60 // Then remove the DOCTYPE 61 $header = preg_replace( '/^<!DOCTYPE[^>]*+>/i', '', substr( $this->message, 0, 200 ), 1 ); 62 $this->message = trim( substr_replace( $this->message, $header, 0, 200 ) ); 63 if ( '' == $this->message ) { 64 return false; 65 } 66 67 // Check that the root tag is valid 68 $root_tag = substr( $this->message, 0, strcspn( substr( $this->message, 0, 20 ), "> \t\r\n" ) ); 69 if ( '<!DOCTYPE' === strtoupper( $root_tag ) ) { 70 return false; 71 } 72 if ( ! in_array( $root_tag, array( '<methodCall', '<methodResponse', '<fault' ) ) ) { 73 return false; 74 } 75 76 // Bail if there are too many elements to parse 77 $element_limit = 30000; 78 if ( function_exists( 'apply_filters' ) ) { 79 /** 80 * Filters the number of elements to parse in an XML-RPC response. 81 * 82 * @since 4.0.0 83 * 84 * @param int $element_limit Default elements limit. 85 */ 86 $element_limit = apply_filters( 'xmlrpc_element_limit', $element_limit ); 87 } 88 if ( $element_limit && 2 * $element_limit < substr_count( $this->message, '<' ) ) { 89 return false; 90 } 91 92 $this->_parser = xml_parser_create(); 93 // Set XML parser to take the case of tags in to account 94 xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false); 95 // Set XML parser callback functions 96 xml_set_element_handler($this->_parser, array($this, 'tag_open'), array($this, 'tag_close')); 97 xml_set_character_data_handler($this->_parser, array($this, 'cdata')); 98 99 // 256Kb, parse in chunks to avoid the RAM usage on very large messages 100 $chunk_size = 262144; 101 102 /** 103 * Filters the chunk size that can be used to parse an XML-RPC response message. 104 * 105 * @since 4.4.0 106 * 107 * @param int $chunk_size Chunk size to parse in bytes. 108 */ 109 $chunk_size = apply_filters( 'xmlrpc_chunk_parsing_size', $chunk_size ); 110 111 $final = false; 112 113 do { 114 if (strlen($this->message) <= $chunk_size) { 115 $final = true; 116 } 117 118 $part = substr($this->message, 0, $chunk_size); 119 $this->message = substr($this->message, $chunk_size); 120 121 if (!xml_parse($this->_parser, $part, $final)) { 122 xml_parser_free($this->_parser); 123 unset($this->_parser); 124 return false; 125 } 126 127 if ($final) { 128 break; 129 } 130 } while (true); 131 132 xml_parser_free($this->_parser); 133 unset($this->_parser); 134 135 // Grab the error messages, if any 136 if ($this->messageType == 'fault') { 137 $this->faultCode = $this->params[0]['faultCode']; 138 $this->faultString = $this->params[0]['faultString']; 139 } 140 return true; 141 } 142 143 function tag_open($parser, $tag, $attr) 144 { 145 $this->_currentTagContents = ''; 146 $this->_currentTag = $tag; 147 switch($tag) { 148 case 'methodCall': 149 case 'methodResponse': 150 case 'fault': 151 $this->messageType = $tag; 152 break; 153 /* Deal with stacks of arrays and structs */ 154 case 'data': // data is to all intents and puposes more interesting than array 155 $this->_arraystructstypes[] = 'array'; 156 $this->_arraystructs[] = array(); 157 break; 158 case 'struct': 159 $this->_arraystructstypes[] = 'struct'; 160 $this->_arraystructs[] = array(); 161 break; 162 } 163 } 164 165 function cdata($parser, $cdata) 166 { 167 $this->_currentTagContents .= $cdata; 168 } 169 170 function tag_close($parser, $tag) 171 { 172 $valueFlag = false; 173 switch($tag) { 174 case 'int': 175 case 'i4': 176 $value = (int)trim($this->_currentTagContents); 177 $valueFlag = true; 178 break; 179 case 'double': 180 $value = (double)trim($this->_currentTagContents); 181 $valueFlag = true; 182 break; 183 case 'string': 184 $value = (string)trim($this->_currentTagContents); 185 $valueFlag = true; 186 break; 187 case 'dateTime.iso8601': 188 $value = new IXR_Date(trim($this->_currentTagContents)); 189 $valueFlag = true; 190 break; 191 case 'value': 192 // "If no type is indicated, the type is string." 193 if (trim($this->_currentTagContents) != '') { 194 $value = (string)$this->_currentTagContents; 195 $valueFlag = true; 196 } 197 break; 198 case 'boolean': 199 $value = (boolean)trim($this->_currentTagContents); 200 $valueFlag = true; 201 break; 202 case 'base64': 203 $value = base64_decode($this->_currentTagContents); 204 $valueFlag = true; 205 break; 206 /* Deal with stacks of arrays and structs */ 207 case 'data': 208 case 'struct': 209 $value = array_pop($this->_arraystructs); 210 array_pop($this->_arraystructstypes); 211 $valueFlag = true; 212 break; 213 case 'member': 214 array_pop($this->_currentStructName); 215 break; 216 case 'name': 217 $this->_currentStructName[] = trim($this->_currentTagContents); 218 break; 219 case 'methodName': 220 $this->methodName = trim($this->_currentTagContents); 221 break; 222 } 223 224 if ($valueFlag) { 225 if (count($this->_arraystructs) > 0) { 226 // Add value to struct or array 227 if ($this->_arraystructstypes[count($this->_arraystructstypes)-1] == 'struct') { 228 // Add to struct 229 $this->_arraystructs[count($this->_arraystructs)-1][$this->_currentStructName[count($this->_currentStructName)-1]] = $value; 230 } else { 231 // Add to array 232 $this->_arraystructs[count($this->_arraystructs)-1][] = $value; 233 } 234 } else { 235 // Just add as a parameter 236 $this->params[] = $value; 237 } 238 } 239 $this->_currentTagContents = ''; 240 } 241 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Thu Nov 21 08:20:01 2024 | Cross-referenced by PHPXref |