]> scripts.mit.edu Git - autoinstalls/wordpress.git/blobdiff - wp-includes/class-IXR.php
WordPress 4.6.3-scripts
[autoinstalls/wordpress.git] / wp-includes / class-IXR.php
index f27be3f9cf26f0dea5e1da88983e89718edcb907..a8e31983e880f24a0baf17d318d010ce07453086 100644 (file)
@@ -1,35 +1,66 @@
 <?php
 /**
- * IXR - The Inutio XML-RPC Library
+ * IXR - The Incutio XML-RPC Library
+ *
+ * Copyright (c) 2010, Incutio Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  - Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  - Neither the name of Incutio Ltd. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * @package IXR
- * @since 1.5
+ * @since 1.5.0
  *
- * @copyright Incutio Ltd 2002-2005
- * @version 1.7 (beta) 23rd May 2005
- * @author Simon Willison
- * @link http://scripts.incutio.com/xmlrpc/ Site
- * @link http://scripts.incutio.com/xmlrpc/manual.php Manual
- * @license BSD License http://www.opensource.org/licenses/bsd-license.php
+ * @copyright  Incutio Ltd 2010 (http://www.incutio.com)
+ * @version    1.7.4 7th September 2010
+ * @author     Simon Willison
+ * @link       http://scripts.incutio.com/xmlrpc/ Site/manual
+ * @license    http://www.opensource.org/licenses/bsd-license.php BSD
  */
 
 /**
  * IXR_Value
  *
  * @package IXR
- * @since 1.5
+ * @since 1.5.0
  */
 class IXR_Value {
     var $data;
     var $type;
-    function IXR_Value ($data, $type = false) {
+
+       /**
+        * PHP5 constructor.
+        */
+       function __construct( $data, $type = false )
+    {
         $this->data = $data;
         if (!$type) {
             $type = $this->calculateType();
         }
         $this->type = $type;
         if ($type == 'struct') {
-            /* Turn all the values in the array in to new IXR_Value objects */
+            // Turn all the values in the array in to new IXR_Value objects
             foreach ($this->data as $key => $value) {
                 $this->data[$key] = new IXR_Value($value);
             }
@@ -40,7 +71,16 @@ class IXR_Value {
             }
         }
     }
-    function calculateType() {
+
+       /**
+        * PHP4 constructor.
+        */
+       public function IXR_Value( $data, $type = false ) {
+               self::__construct( $data, $type );
+       }
+
+    function calculateType()
+    {
         if ($this->data === true || $this->data === false) {
             return 'boolean';
         }
@@ -50,6 +90,7 @@ class IXR_Value {
         if (is_double($this->data)) {
             return 'double';
         }
+
         // Deal with IXR object types base64 and date
         if (is_object($this->data) && is_a($this->data, 'IXR_Date')) {
             return 'date';
@@ -57,24 +98,27 @@ class IXR_Value {
         if (is_object($this->data) && is_a($this->data, 'IXR_Base64')) {
             return 'base64';
         }
+
         // If it is a normal PHP object convert it in to a struct
         if (is_object($this->data)) {
-
             $this->data = get_object_vars($this->data);
             return 'struct';
         }
         if (!is_array($this->data)) {
             return 'string';
         }
-        /* We have an array - is it an array or a struct ? */
+
+        // We have an array - is it an array or a struct?
         if ($this->isStruct($this->data)) {
             return 'struct';
         } else {
             return 'array';
         }
     }
-    function getXml() {
-        /* Return XML for this value */
+
+    function getXml()
+    {
+        // Return XML for this value
         switch ($this->type) {
             case 'boolean':
                 return '<boolean>'.(($this->data) ? '1' : '0').'</boolean>';
@@ -113,11 +157,18 @@ class IXR_Value {
         }
         return false;
     }
-    function isStruct($array) {
-        /* Nasty function to check if an array is a struct or not */
+
+    /**
+     * Checks whether or not the supplied array is a struct or not
+     *
+     * @param array $array
+     * @return bool
+     */
+    function isStruct($array)
+    {
         $expected = 0;
         foreach ($array as $key => $value) {
-            if ((string)$key != (string)$expected) {
+            if ((string)$key !== (string)$expected) {
                 return true;
             }
             $expected++;
@@ -127,18 +178,21 @@ class IXR_Value {
 }
 
 /**
- * IXR_Message
+ * IXR_MESSAGE
  *
  * @package IXR
- * @since 1.5
+ * @since 1.5.0
+ *
  */
-class IXR_Message {
+class IXR_Message
+{
     var $message;
     var $messageType;  // methodCall / methodResponse / fault
     var $faultCode;
     var $faultString;
     var $methodName;
     var $params;
+
     // 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
@@ -149,15 +203,64 @@ class IXR_Message {
     var $_currentTagContents;
     // The XML parser
     var $_parser;
-    function IXR_Message ($message) {
-        $this->message = $message;
+
+       /**
+        * PHP5 constructor.
+        */
+    function __construct( $message )
+    {
+        $this->message =& $message;
     }
-    function parse() {
+
+       /**
+        * PHP4 constructor.
+        */
+       public function IXR_Message( $message ) {
+               self::__construct( $message );
+       }
+
+    function parse()
+    {
         // first remove the XML declaration
-        $this->message = preg_replace('/<\?xml(.*)?\?'.'>/', '', $this->message);
-        if (trim($this->message) == '') {
+        // 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);
@@ -165,13 +268,35 @@ class IXR_Message {
         xml_set_object($this->_parser, $this);
         xml_set_element_handler($this->_parser, 'tag_open', 'tag_close');
         xml_set_character_data_handler($this->_parser, 'cdata');
-        if (!xml_parse($this->_parser, $this->message)) {
-            /* die(sprintf('XML error: %s at line %d',
-                xml_error_string(xml_get_error_code($this->_parser)),
-                xml_get_current_line_number($this->_parser))); */
-            return false;
-        }
+
+        // 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 reponse 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)) {
+                return false;
+            }
+            if ($final) {
+                break;
+            }
+        } while (true);
         xml_parser_free($this->_parser);
+
         // Grab the error messages, if any
         if ($this->messageType == 'fault') {
             $this->faultCode = $this->params[0]['faultCode'];
@@ -179,8 +304,10 @@ class IXR_Message {
         }
         return true;
     }
-    function tag_open($parser, $tag, $attr) {
-               $this->_currentTagContents = '';
+
+    function tag_open($parser, $tag, $attr)
+    {
+        $this->_currentTagContents = '';
         $this->currentTag = $tag;
         switch($tag) {
             case 'methodCall':
@@ -188,7 +315,7 @@ class IXR_Message {
             case 'fault':
                 $this->messageType = $tag;
                 break;
-            /* Deal with stacks of arrays and structs */
+                /* 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();
@@ -199,28 +326,31 @@ class IXR_Message {
                 break;
         }
     }
-    function cdata($parser, $cdata) {
+
+    function cdata($parser, $cdata)
+    {
         $this->_currentTagContents .= $cdata;
     }
-    function tag_close($parser, $tag) {
+
+    function tag_close($parser, $tag)
+    {
         $valueFlag = false;
         switch($tag) {
             case 'int':
             case 'i4':
-                $value = (int) trim($this->_currentTagContents);
+                $value = (int)trim($this->_currentTagContents);
                 $valueFlag = true;
                 break;
             case 'double':
-                $value = (double) trim($this->_currentTagContents);
+                $value = (double)trim($this->_currentTagContents);
                 $valueFlag = true;
                 break;
             case 'string':
-                $value = $this->_currentTagContents;
+                $value = (string)trim($this->_currentTagContents);
                 $valueFlag = true;
                 break;
             case 'dateTime.iso8601':
                 $value = new IXR_Date(trim($this->_currentTagContents));
-                // $value = $iso->getTimestamp();
                 $valueFlag = true;
                 break;
             case 'value':
@@ -231,14 +361,14 @@ class IXR_Message {
                 }
                 break;
             case 'boolean':
-                $value = (boolean) trim($this->_currentTagContents);
+                $value = (boolean)trim($this->_currentTagContents);
                 $valueFlag = true;
                 break;
             case 'base64':
-                $value = base64_decode( trim( $this->_currentTagContents ) );
+                $value = base64_decode($this->_currentTagContents);
                 $valueFlag = true;
                 break;
-            /* Deal with stacks of arrays and structs */
+                /* Deal with stacks of arrays and structs */
             case 'data':
             case 'struct':
                 $value = array_pop($this->_arraystructs);
@@ -255,6 +385,7 @@ class IXR_Message {
                 $this->methodName = trim($this->_currentTagContents);
                 break;
         }
+
         if ($valueFlag) {
             if (count($this->_arraystructs) > 0) {
                 // Add value to struct or array
@@ -266,11 +397,11 @@ class IXR_Message {
                     $this->_arraystructs[count($this->_arraystructs)-1][] = $value;
                 }
             } else {
-                // Just add as a paramater
+                // Just add as a parameter
                 $this->params[] = $value;
             }
         }
-               $this->_currentTagContents = '';
+        $this->_currentTagContents = '';
     }
 }
 
@@ -278,28 +409,56 @@ class IXR_Message {
  * IXR_Server
  *
  * @package IXR
- * @since 1.5
+ * @since 1.5.0
  */
-class IXR_Server {
+class IXR_Server
+{
     var $data;
     var $callbacks = array();
     var $message;
     var $capabilities;
-    function IXR_Server($callbacks = false, $data = false) {
+
+       /**
+        * PHP5 constructor.
+        */
+    function __construct( $callbacks = false, $data = false, $wait = false )
+    {
         $this->setCapabilities();
         if ($callbacks) {
             $this->callbacks = $callbacks;
         }
         $this->setCallbacks();
-        $this->serve($data);
+        if (!$wait) {
+            $this->serve($data);
+        }
     }
-    function serve($data = false) {
+
+       /**
+        * PHP4 constructor.
+        */
+       public function IXR_Server( $callbacks = false, $data = false, $wait = false ) {
+               self::__construct( $callbacks, $data, $wait );
+       }
+
+    function serve($data = false)
+    {
         if (!$data) {
+            if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] !== 'POST') {
+                if ( function_exists( 'status_header' ) ) {
+                    status_header( 405 ); // WP #20986
+                    header( 'Allow: POST' );
+                }
+                header('Content-Type: text/plain'); // merged from WP #9093
+                die('XML-RPC server accepts POST requests only.');
+            }
+
             global $HTTP_RAW_POST_DATA;
-            if (!$HTTP_RAW_POST_DATA) {
-               die('XML-RPC server accepts POST requests only.');
+            if (empty($HTTP_RAW_POST_DATA)) {
+                // workaround for a bug in PHP 5.2.2 - http://bugs.php.net/bug.php?id=41293
+                $data = file_get_contents('php://input');
+            } else {
+                $data =& $HTTP_RAW_POST_DATA;
             }
-            $data = $HTTP_RAW_POST_DATA;
         }
         $this->message = new IXR_Message($data);
         if (!$this->message->parse()) {
@@ -309,114 +468,144 @@ class IXR_Server {
             $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall');
         }
         $result = $this->call($this->message->methodName, $this->message->params);
+
         // Is the result an error?
         if (is_a($result, 'IXR_Error')) {
             $this->error($result);
         }
+
         // Encode the result
         $r = new IXR_Value($result);
         $resultxml = $r->getXml();
+
         // Create the XML
         $xml = <<<EOD
 <methodResponse>
   <params>
     <param>
       <value>
-        $resultxml
+      $resultxml
       </value>
     </param>
   </params>
 </methodResponse>
 
 EOD;
-        // Send it
-        $this->output($xml);
+      // Send it
+      $this->output($xml);
     }
-    function call($methodname, $args) {
+
+    function call($methodname, $args)
+    {
         if (!$this->hasMethod($methodname)) {
             return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.');
         }
         $method = $this->callbacks[$methodname];
+
         // Perform the callback and send the response
         if (count($args) == 1) {
-            // If only one paramater just send that instead of the whole array
+            // If only one parameter just send that instead of the whole array
             $args = $args[0];
         }
+
         // Are we dealing with a function or a method?
-        if (substr($method, 0, 5) == 'this:') {
+        if (is_string($method) && substr($method, 0, 5) == 'this:') {
             // It's a class method - check it exists
             $method = substr($method, 5);
             if (!method_exists($this, $method)) {
                 return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.');
             }
-            // Call the method
+
+            //Call the method
             $result = $this->$method($args);
         } else {
             // It's a function - does it exist?
             if (is_array($method)) {
-               if (!method_exists($method[0], $method[1])) {
-                return new IXR_Error(-32601, 'server error. requested object method "'.$method[1].'" does not exist.');
-               }
+                if (!is_callable(array($method[0], $method[1]))) {
+                    return new IXR_Error(-32601, 'server error. requested object method "'.$method[1].'" does not exist.');
+                }
             } else if (!function_exists($method)) {
                 return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.');
             }
+
             // Call the function
             $result = call_user_func($method, $args);
         }
         return $result;
     }
 
-    function error($error, $message = false) {
+    function error($error, $message = false)
+    {
         // Accepts either an error object or an error code and message
         if ($message && !is_object($error)) {
             $error = new IXR_Error($error, $message);
         }
         $this->output($error->getXml());
     }
-    function output($xml) {
-        $xml = '<?xml version="1.0"?>'."\n".$xml;
+
+    function output($xml)
+    {
+        $charset = function_exists('get_option') ? get_option('blog_charset') : '';
+        if ($charset)
+            $xml = '<?xml version="1.0" encoding="'.$charset.'"?>'."\n".$xml;
+        else
+            $xml = '<?xml version="1.0"?>'."\n".$xml;
         $length = strlen($xml);
         header('Connection: close');
-        header('Content-Length: '.$length);
-        header('Content-Type: text/xml');
+        if ($charset)
+            header('Content-Type: text/xml; charset='.$charset);
+        else
+            header('Content-Type: text/xml');
         header('Date: '.date('r'));
         echo $xml;
         exit;
     }
-    function hasMethod($method) {
+
+    function hasMethod($method)
+    {
         return in_array($method, array_keys($this->callbacks));
     }
-    function setCapabilities() {
+
+    function setCapabilities()
+    {
         // Initialises capabilities array
         $this->capabilities = array(
             'xmlrpc' => array(
                 'specUrl' => 'http://www.xmlrpc.com/spec',
                 'specVersion' => 1
-            ),
+        ),
             'faults_interop' => array(
                 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php',
                 'specVersion' => 20010516
-            ),
+        ),
             'system.multicall' => array(
                 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208',
                 'specVersion' => 1
-            ),
+        ),
         );
     }
-    function getCapabilities($args) {
+
+    function getCapabilities($args)
+    {
         return $this->capabilities;
     }
-    function setCallbacks() {
+
+    function setCallbacks()
+    {
         $this->callbacks['system.getCapabilities'] = 'this:getCapabilities';
         $this->callbacks['system.listMethods'] = 'this:listMethods';
         $this->callbacks['system.multicall'] = 'this:multiCall';
     }
-    function listMethods($args) {
+
+    function listMethods($args)
+    {
         // Returns a list of methods - uses array_reverse to ensure user defined
         // methods are listed before server defined methods
         return array_reverse(array_keys($this->callbacks));
     }
-    function multiCall($methodcalls) {
+
+    function multiCall($methodcalls)
+    {
         // See http://www.xmlrpc.com/discuss/msgReader$1208
         $return = array();
         foreach ($methodcalls as $call) {
@@ -444,13 +633,19 @@ EOD;
  * IXR_Request
  *
  * @package IXR
- * @since 1.5
+ * @since 1.5.0
  */
-class IXR_Request {
+class IXR_Request
+{
     var $method;
     var $args;
     var $xml;
-    function IXR_Request($method, $args) {
+
+       /**
+        * PHP5 constructor.
+        */
+    function __construct($method, $args)
+    {
         $this->method = $method;
         $this->args = $args;
         $this->xml = <<<EOD
@@ -468,10 +663,21 @@ EOD;
         }
         $this->xml .= '</params></methodCall>';
     }
-    function getLength() {
+
+       /**
+        * PHP4 constructor.
+        */
+       public function IXR_Request( $method, $args ) {
+               self::__construct( $method, $args );
+       }
+
+    function getLength()
+    {
         return strlen($this->xml);
     }
-    function getXml() {
+
+    function getXml()
+    {
         return $this->xml;
     }
 }
@@ -480,9 +686,11 @@ EOD;
  * IXR_Client
  *
  * @package IXR
- * @since 1.5
+ * @since 1.5.0
+ *
  */
-class IXR_Client {
+class IXR_Client
+{
     var $server;
     var $port;
     var $path;
@@ -490,29 +698,50 @@ class IXR_Client {
     var $response;
     var $message = false;
     var $debug = false;
-       var $timeout;
+    var $timeout;
+    var $headers = array();
+
     // Storage place for an error message
     var $error = false;
-    function IXR_Client($server, $path = false, $port = 80, $timeout = false) {
+
+       /**
+        * PHP5 constructor.
+        */
+    function __construct( $server, $path = false, $port = 80, $timeout = 15 )
+    {
         if (!$path) {
             // Assume we have been given a URL instead
             $bits = parse_url($server);
             $this->server = $bits['host'];
             $this->port = isset($bits['port']) ? $bits['port'] : 80;
             $this->path = isset($bits['path']) ? $bits['path'] : '/';
+
             // Make absolutely sure we have a path
             if (!$this->path) {
                 $this->path = '/';
             }
+
+            if ( ! empty( $bits['query'] ) ) {
+                $this->path .= '?' . $bits['query'];
+            }
         } else {
             $this->server = $server;
             $this->path = $path;
             $this->port = $port;
         }
-        $this->useragent = 'Incutio XML-RPC';
-               $this->timeout = $timeout;
+        $this->useragent = 'The Incutio XML-RPC PHP Library';
+        $this->timeout = $timeout;
     }
-    function query() {
+
+       /**
+        * PHP4 constructor.
+        */
+       public function IXR_Client( $server, $path = false, $port = 80, $timeout = 15 ) {
+               self::__construct( $server, $path, $port, $timeout );
+       }
+
+    function query()
+    {
         $args = func_get_args();
         $method = array_shift($args);
         $request = new IXR_Request($method, $args);
@@ -520,26 +749,37 @@ class IXR_Client {
         $xml = $request->getXml();
         $r = "\r\n";
         $request  = "POST {$this->path} HTTP/1.0$r";
-        $request .= "Host: {$this->server}$r";
-        $request .= "Content-Type: text/xml$r";
-        $request .= "User-Agent: {$this->useragent}$r";
-        $request .= "Content-length: {$length}$r$r";
+
+        // Merged from WP #8145 - allow custom headers
+        $this->headers['Host']          = $this->server;
+        $this->headers['Content-Type']  = 'text/xml';
+        $this->headers['User-Agent']    = $this->useragent;
+        $this->headers['Content-Length']= $length;
+
+        foreach( $this->headers as $header => $value ) {
+            $request .= "{$header}: {$value}{$r}";
+        }
+        $request .= $r;
+
         $request .= $xml;
+
         // Now send the request
         if ($this->debug) {
-            echo '<pre>'.htmlspecialchars($request)."\n</pre>\n\n";
+            echo '<pre class="ixr_request">'.htmlspecialchars($request)."\n</pre>\n\n";
         }
+
         if ($this->timeout) {
             $fp = @fsockopen($this->server, $this->port, $errno, $errstr, $this->timeout);
         } else {
             $fp = @fsockopen($this->server, $this->port, $errno, $errstr);
         }
         if (!$fp) {
-            $this->error = new IXR_Error(-32300, "transport error - could not open socket: $errno $errstr");
+            $this->error = new IXR_Error(-32300, 'transport error - could not open socket');
             return false;
         }
         fputs($fp, $request);
         $contents = '';
+        $debugContents = '';
         $gotFirstLine = false;
         $gettingHeaders = true;
         while (!feof($fp)) {
@@ -556,12 +796,17 @@ class IXR_Client {
                 $gettingHeaders = false;
             }
             if (!$gettingHeaders) {
-                $contents .= trim($line)."\n";
+               // merged from WP #12559 - remove trim
+                $contents .= $line;
+            }
+            if ($this->debug) {
+               $debugContents .= $line;
             }
         }
         if ($this->debug) {
-            echo '<pre>'.htmlspecialchars($contents)."\n</pre>\n\n";
+            echo '<pre class="ixr_response">'.htmlspecialchars($debugContents)."\n</pre>\n\n";
         }
+
         // Now parse what we've got back
         $this->message = new IXR_Message($contents);
         if (!$this->message->parse()) {
@@ -569,43 +814,69 @@ class IXR_Client {
             $this->error = new IXR_Error(-32700, 'parse error. not well formed');
             return false;
         }
+
         // Is the message a fault?
         if ($this->message->messageType == 'fault') {
             $this->error = new IXR_Error($this->message->faultCode, $this->message->faultString);
             return false;
         }
+
         // Message must be OK
         return true;
     }
-    function getResponse() {
+
+    function getResponse()
+    {
         // methodResponses can only have one param - return that
         return $this->message->params[0];
     }
-    function isError() {
+
+    function isError()
+    {
         return (is_object($this->error));
     }
-    function getErrorCode() {
+
+    function getErrorCode()
+    {
         return $this->error->code;
     }
-    function getErrorMessage() {
+
+    function getErrorMessage()
+    {
         return $this->error->message;
     }
 }
 
+
 /**
  * IXR_Error
  *
  * @package IXR
- * @since 1.5
+ * @since 1.5.0
  */
-class IXR_Error {
+class IXR_Error
+{
     var $code;
     var $message;
-    function IXR_Error($code, $message) {
+
+       /**
+        * PHP5 constructor.
+        */
+    function __construct( $code, $message )
+    {
         $this->code = $code;
         $this->message = htmlspecialchars($message);
     }
-    function getXml() {
+
+       /**
+        * PHP4 constructor.
+        */
+       public function IXR_Error( $code, $message ) {
+               self::__construct( $code, $message );
+       }
+
+    function getXml()
+    {
         $xml = <<<EOD
 <methodResponse>
   <fault>
@@ -633,7 +904,7 @@ EOD;
  * IXR_Date
  *
  * @package IXR
- * @since 1.5
+ * @since 1.5.0
  */
 class IXR_Date {
     var $year;
@@ -642,7 +913,13 @@ class IXR_Date {
     var $hour;
     var $minute;
     var $second;
-    function IXR_Date($time) {
+    var $timezone;
+
+       /**
+        * PHP5 constructor.
+        */
+    function __construct( $time )
+    {
         // $time can be a PHP timestamp or an ISO one
         if (is_numeric($time)) {
             $this->parseTimestamp($time);
@@ -650,15 +927,27 @@ class IXR_Date {
             $this->parseIso($time);
         }
     }
-    function parseTimestamp($timestamp) {
+
+       /**
+        * PHP4 constructor.
+        */
+       public function IXR_Date( $time ) {
+               self::__construct( $time );
+       }
+
+    function parseTimestamp($timestamp)
+    {
         $this->year = date('Y', $timestamp);
         $this->month = date('m', $timestamp);
         $this->day = date('d', $timestamp);
         $this->hour = date('H', $timestamp);
         $this->minute = date('i', $timestamp);
         $this->second = date('s', $timestamp);
+        $this->timezone = '';
     }
-    function parseIso($iso) {
+
+    function parseIso($iso)
+    {
         $this->year = substr($iso, 0, 4);
         $this->month = substr($iso, 4, 2);
         $this->day = substr($iso, 6, 2);
@@ -667,13 +956,19 @@ class IXR_Date {
         $this->second = substr($iso, 15, 2);
         $this->timezone = substr($iso, 17);
     }
-    function getIso() {
+
+    function getIso()
+    {
         return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second.$this->timezone;
     }
-    function getXml() {
+
+    function getXml()
+    {
         return '<dateTime.iso8601>'.$this->getIso().'</dateTime.iso8601>';
     }
-    function getTimestamp() {
+
+    function getTimestamp()
+    {
         return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year);
     }
 }
@@ -682,14 +977,29 @@ class IXR_Date {
  * IXR_Base64
  *
  * @package IXR
- * @since 1.5
+ * @since 1.5.0
  */
-class IXR_Base64 {
+class IXR_Base64
+{
     var $data;
-    function IXR_Base64($data) {
+
+       /**
+        * PHP5 constructor.
+        */
+    function __construct( $data )
+    {
         $this->data = $data;
     }
-    function getXml() {
+
+       /**
+        * PHP4 constructor.
+        */
+       public function IXR_Base64( $data ) {
+               self::__construct( $data );
+       }
+
+    function getXml()
+    {
         return '<base64>'.base64_encode($this->data).'</base64>';
     }
 }
@@ -698,12 +1008,18 @@ class IXR_Base64 {
  * IXR_IntrospectionServer
  *
  * @package IXR
- * @since 1.5
+ * @since 1.5.0
  */
-class IXR_IntrospectionServer extends IXR_Server {
+class IXR_IntrospectionServer extends IXR_Server
+{
     var $signatures;
     var $help;
-    function IXR_IntrospectionServer() {
+
+       /**
+        * PHP5 constructor.
+        */
+    function __construct()
+    {
         $this->setCallbacks();
         $this->setCapabilities();
         $this->capabilities['introspection'] = array(
@@ -735,16 +1051,28 @@ class IXR_IntrospectionServer extends IXR_Server {
             'Returns a documentation string for the specified method'
         );
     }
-    function addCallback($method, $callback, $args, $help) {
+
+       /**
+        * PHP4 constructor.
+        */
+       public function IXR_IntrospectionServer() {
+               self::__construct();
+       }
+
+    function addCallback($method, $callback, $args, $help)
+    {
         $this->callbacks[$method] = $callback;
         $this->signatures[$method] = $args;
         $this->help[$method] = $help;
     }
-    function call($methodname, $args) {
+
+    function call($methodname, $args)
+    {
         // Make sure it's in an array
         if ($args && !is_array($args)) {
             $args = array($args);
         }
+
         // Over-rides default call method, adds signature check
         if (!$this->hasMethod($methodname)) {
             return new IXR_Error(-32601, 'server error. requested method "'.$this->message->methodName.'" not specified.');
@@ -752,10 +1080,12 @@ class IXR_IntrospectionServer extends IXR_Server {
         $method = $this->callbacks[$methodname];
         $signature = $this->signatures[$methodname];
         $returnType = array_shift($signature);
+
         // Check the number of arguments
         if (count($args) != count($signature)) {
             return new IXR_Error(-32602, 'server error. wrong number of method parameters');
         }
+
         // Check the argument types
         $ok = true;
         $argsbackup = $args;
@@ -800,7 +1130,9 @@ class IXR_IntrospectionServer extends IXR_Server {
         // It passed the test - run the "real" method call
         return parent::call($methodname, $argsbackup);
     }
-    function methodSignature($method) {
+
+    function methodSignature($method)
+    {
         if (!$this->hasMethod($method)) {
             return new IXR_Error(-32601, 'server error. requested method "'.$method.'" not specified.');
         }
@@ -838,7 +1170,9 @@ class IXR_IntrospectionServer extends IXR_Server {
         }
         return $return;
     }
-    function methodHelp($method) {
+
+    function methodHelp($method)
+    {
         return $this->help[$method];
     }
 }
@@ -847,15 +1181,30 @@ class IXR_IntrospectionServer extends IXR_Server {
  * IXR_ClientMulticall
  *
  * @package IXR
- * @since 1.5
+ * @since 1.5.0
  */
-class IXR_ClientMulticall extends IXR_Client {
+class IXR_ClientMulticall extends IXR_Client
+{
     var $calls = array();
-    function IXR_ClientMulticall($server, $path = false, $port = 80) {
+
+       /**
+        * PHP5 constructor.
+        */
+    function __construct( $server, $path = false, $port = 80 )
+    {
         parent::IXR_Client($server, $path, $port);
         $this->useragent = 'The Incutio XML-RPC PHP Library (multicall client)';
     }
-    function addCall() {
+
+       /**
+        * PHP4 constructor.
+        */
+       public function IXR_ClientMulticall( $server, $path = false, $port = 80 ) {
+               self::__construct( $server, $path, $port );
+       }
+
+    function addCall()
+    {
         $args = func_get_args();
         $methodName = array_shift($args);
         $struct = array(
@@ -864,10 +1213,10 @@ class IXR_ClientMulticall extends IXR_Client {
         );
         $this->calls[] = $struct;
     }
-    function query() {
+
+    function query()
+    {
         // Prepare multicall, then call the parent::query() method
         return parent::query('system.multicall', $this->calls);
     }
 }
-
-?>