<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul, pre { overflow: auto; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<title>[15612] trunk/wp-includes/class-IXR.php:
  Update Incutio XML-RPC Library to latest version (1.7.4).</title>
</head>
<body>
<div id="msg">
<dl>
<dt>Revision</dt> <dd><a href="http://trac.wordpress.org/changeset/15612">15612</a></dd>
<dt>Author</dt> <dd>scribu</dd>
<dt>Date</dt> <dd>2010-09-13 16:36:08 +0000 (Mon, 13 Sep 2010)</dd>
</dl>
<h3>Log Message</h3>
<pre>Update Incutio XML-RPC Library to latest version (1.7.4). Props hakre. Fixes <a href="http://trac.wordpress.org/ticket/14703">#14703</a></pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpincludesclassIXRphp">trunk/wp-includes/class-IXR.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpincludesclassIXRphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/class-IXR.php (15611 => 15612)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/class-IXR.php        2010-09-12 18:46:18 UTC (rev 15611)
+++ trunk/wp-includes/class-IXR.php        2010-09-13 16:36:08 UTC (rev 15612)
</span><span class="lines">@@ -1,16 +1,42 @@
</span><span class="cx"> <?php
</span><span class="cx"> /**
</span><del>- * IXR - The Inutio XML-RPC Library
</del><ins>+ * IXR - The Incutio XML-RPC Library
</ins><span class="cx">  *
</span><ins>+ * 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.
+ *
</ins><span class="cx">  * @package IXR
</span><span class="cx">  * @since 1.5
</span><span class="cx">  *
</span><del>- * @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
</del><ins>+ * @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
</ins><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> /**
</span><span class="lines">@@ -23,14 +49,15 @@
</span><span class="cx">     var $data;
</span><span class="cx">     var $type;
</span><span class="cx"> 
</span><del>-    function IXR_Value ($data, $type = false) {
</del><ins>+    function IXR_Value($data, $type = false)
+    {
</ins><span class="cx">         $this->data = $data;
</span><span class="cx">         if (!$type) {
</span><span class="cx">             $type = $this->calculateType();
</span><span class="cx">         }
</span><span class="cx">         $this->type = $type;
</span><span class="cx">         if ($type == 'struct') {
</span><del>-            /* Turn all the values in the array in to new IXR_Value objects */
</del><ins>+            // Turn all the values in the array in to new IXR_Value objects
</ins><span class="cx">             foreach ($this->data as $key => $value) {
</span><span class="cx">                 $this->data[$key] = new IXR_Value($value);
</span><span class="cx">             }
</span><span class="lines">@@ -42,7 +69,8 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function calculateType() {
</del><ins>+    function calculateType()
+    {
</ins><span class="cx">         if ($this->data === true || $this->data === false) {
</span><span class="cx">             return 'boolean';
</span><span class="cx">         }
</span><span class="lines">@@ -52,6 +80,7 @@
</span><span class="cx">         if (is_double($this->data)) {
</span><span class="cx">             return 'double';
</span><span class="cx">         }
</span><ins>+
</ins><span class="cx">         // Deal with IXR object types base64 and date
</span><span class="cx">         if (is_object($this->data) && is_a($this->data, 'IXR_Date')) {
</span><span class="cx">             return 'date';
</span><span class="lines">@@ -59,16 +88,17 @@
</span><span class="cx">         if (is_object($this->data) && is_a($this->data, 'IXR_Base64')) {
</span><span class="cx">             return 'base64';
</span><span class="cx">         }
</span><ins>+
</ins><span class="cx">         // If it is a normal PHP object convert it in to a struct
</span><span class="cx">         if (is_object($this->data)) {
</span><del>-
</del><span class="cx">             $this->data = get_object_vars($this->data);
</span><span class="cx">             return 'struct';
</span><span class="cx">         }
</span><span class="cx">         if (!is_array($this->data)) {
</span><span class="cx">             return 'string';
</span><span class="cx">         }
</span><del>-        /* We have an array - is it an array or a struct ? */
</del><ins>+
+        // We have an array - is it an array or a struct?
</ins><span class="cx">         if ($this->isStruct($this->data)) {
</span><span class="cx">             return 'struct';
</span><span class="cx">         } else {
</span><span class="lines">@@ -76,8 +106,9 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function getXml() {
-        /* Return XML for this value */
</del><ins>+    function getXml()
+    {
+        // Return XML for this value
</ins><span class="cx">         switch ($this->type) {
</span><span class="cx">             case 'boolean':
</span><span class="cx">                 return '<boolean>'.(($this->data) ? '1' : '0').'</boolean>';
</span><span class="lines">@@ -117,8 +148,14 @@
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function isStruct($array) {
-        /* Nasty function to check if an array is a struct or not */
</del><ins>+    /**
+     * Checks whether or not the supplied array is a struct or not
+     *
+     * @param unknown_type $array
+     * @return boolean
+     */
+    function isStruct($array)
+    {
</ins><span class="cx">         $expected = 0;
</span><span class="cx">         foreach ($array as $key => $value) {
</span><span class="cx">             if ((string)$key != (string)$expected) {
</span><span class="lines">@@ -131,18 +168,21 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * IXR_Message
</del><ins>+ * IXR_MESSAGE
</ins><span class="cx">  *
</span><span class="cx">  * @package IXR
</span><span class="cx">  * @since 1.5
</span><ins>+ *
</ins><span class="cx">  */
</span><del>-class IXR_Message {
</del><ins>+class IXR_Message
+{
</ins><span class="cx">     var $message;
</span><span class="cx">     var $messageType;  // methodCall / methodResponse / fault
</span><span class="cx">     var $faultCode;
</span><span class="cx">     var $faultString;
</span><span class="cx">     var $methodName;
</span><span class="cx">     var $params;
</span><ins>+
</ins><span class="cx">     // Current variable stacks
</span><span class="cx">     var $_arraystructs = array();   // The stack used to keep track of the current array/struct
</span><span class="cx">     var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array
</span><span class="lines">@@ -153,44 +193,54 @@
</span><span class="cx">     var $_currentTagContents;
</span><span class="cx">     // The XML parser
</span><span class="cx">     var $_parser;
</span><del>-    function IXR_Message (&$message) {
-        $this->message = &$message;
</del><ins>+
+    function IXR_Message($message)
+    {
+        $this->message =& $message;
</ins><span class="cx">     }
</span><del>-    function parse() {
-                // first remove the XML declaration
-                // this method avoids the RAM usage of preg_replace on very large messages
-                $header = preg_replace( '/<\?xml.*?\?'.'>/', '', substr( $this->message, 0, 100 ), 1 );
-                $this->message = substr_replace($this->message, $header, 0, 100);
</del><ins>+
+    function parse()
+    {
+        // 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.*?\?'.'>/', '', substr($this->message, 0, 100), 1);
+        $this->message = substr_replace($this->message, $header, 0, 100);
</ins><span class="cx">         if (trim($this->message) == '') {
</span><span class="cx">             return false;
</span><del>-                }
</del><ins>+        }
</ins><span class="cx">         $this->_parser = xml_parser_create();
</span><span class="cx">         // Set XML parser to take the case of tags in to account
</span><span class="cx">         xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false);
</span><span class="cx">         // Set XML parser callback functions
</span><span class="cx">         xml_set_object($this->_parser, $this);
</span><span class="cx">         xml_set_element_handler($this->_parser, 'tag_open', 'tag_close');
</span><del>-                xml_set_character_data_handler($this->_parser, 'cdata');
-                $chunk_size = 262144; // 256Kb, parse in chunks to avoid the RAM usage on very large messages
-                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);
</del><ins>+        xml_set_character_data_handler($this->_parser, 'cdata');
+        $chunk_size = 262144; // 256Kb, parse in chunks to avoid the RAM usage on very large messages
+        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);
+
</ins><span class="cx">         // Grab the error messages, if any
</span><span class="cx">         if ($this->messageType == 'fault') {
</span><span class="cx">             $this->faultCode = $this->params[0]['faultCode'];
</span><span class="cx">             $this->faultString = $this->params[0]['faultString'];
</span><del>-                }
</del><ins>+        }
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><del>-    function tag_open($parser, $tag, $attr) {
</del><ins>+
+    function tag_open($parser, $tag, $attr)
+    {
</ins><span class="cx">         $this->_currentTagContents = '';
</span><span class="cx">         $this->currentTag = $tag;
</span><span class="cx">         switch($tag) {
</span><span class="lines">@@ -199,7 +249,7 @@
</span><span class="cx">             case 'fault':
</span><span class="cx">                 $this->messageType = $tag;
</span><span class="cx">                 break;
</span><del>-            /* Deal with stacks of arrays and structs */
</del><ins>+                /* Deal with stacks of arrays and structs */
</ins><span class="cx">             case 'data':    // data is to all intents and puposes more interesting than array
</span><span class="cx">                 $this->_arraystructstypes[] = 'array';
</span><span class="cx">                 $this->_arraystructs[] = array();
</span><span class="lines">@@ -210,28 +260,31 @@
</span><span class="cx">                 break;
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-    function cdata($parser, $cdata) {
</del><ins>+
+    function cdata($parser, $cdata)
+    {
</ins><span class="cx">         $this->_currentTagContents .= $cdata;
</span><span class="cx">     }
</span><del>-    function tag_close($parser, $tag) {
</del><ins>+
+    function tag_close($parser, $tag)
+    {
</ins><span class="cx">         $valueFlag = false;
</span><span class="cx">         switch($tag) {
</span><span class="cx">             case 'int':
</span><span class="cx">             case 'i4':
</span><del>-                $value = (int) trim($this->_currentTagContents);
</del><ins>+                $value = (int)trim($this->_currentTagContents);
</ins><span class="cx">                 $valueFlag = true;
</span><span class="cx">                 break;
</span><span class="cx">             case 'double':
</span><del>-                $value = (double) trim($this->_currentTagContents);
</del><ins>+                $value = (double)trim($this->_currentTagContents);
</ins><span class="cx">                 $valueFlag = true;
</span><span class="cx">                 break;
</span><span class="cx">             case 'string':
</span><del>-                $value = $this->_currentTagContents;
</del><ins>+                $value = (string)trim($this->_currentTagContents);
</ins><span class="cx">                 $valueFlag = true;
</span><span class="cx">                 break;
</span><span class="cx">             case 'dateTime.iso8601':
</span><span class="cx">                 $value = new IXR_Date(trim($this->_currentTagContents));
</span><del>-                // $value = $iso->getTimestamp();
</del><span class="cx">                 $valueFlag = true;
</span><span class="cx">                 break;
</span><span class="cx">             case 'value':
</span><span class="lines">@@ -242,14 +295,14 @@
</span><span class="cx">                 }
</span><span class="cx">                 break;
</span><span class="cx">             case 'boolean':
</span><del>-                $value = (boolean) trim($this->_currentTagContents);
</del><ins>+                $value = (boolean)trim($this->_currentTagContents);
</ins><span class="cx">                 $valueFlag = true;
</span><span class="cx">                 break;
</span><span class="cx">             case 'base64':
</span><del>-                $value = base64_decode( trim( $this->_currentTagContents ) );
</del><ins>+                $value = base64_decode($this->_currentTagContents);
</ins><span class="cx">                 $valueFlag = true;
</span><span class="cx">                 break;
</span><del>-            /* Deal with stacks of arrays and structs */
</del><ins>+                /* Deal with stacks of arrays and structs */
</ins><span class="cx">             case 'data':
</span><span class="cx">             case 'struct':
</span><span class="cx">                 $value = array_pop($this->_arraystructs);
</span><span class="lines">@@ -266,6 +319,7 @@
</span><span class="cx">                 $this->methodName = trim($this->_currentTagContents);
</span><span class="cx">                 break;
</span><span class="cx">         }
</span><ins>+
</ins><span class="cx">         if ($valueFlag) {
</span><span class="cx">             if (count($this->_arraystructs) > 0) {
</span><span class="cx">                 // Add value to struct or array
</span><span class="lines">@@ -291,27 +345,40 @@
</span><span class="cx">  * @package IXR
</span><span class="cx">  * @since 1.5
</span><span class="cx">  */
</span><del>-class IXR_Server {
</del><ins>+class IXR_Server
+{
</ins><span class="cx">     var $data;
</span><span class="cx">     var $callbacks = array();
</span><span class="cx">     var $message;
</span><span class="cx">     var $capabilities;
</span><del>-    function IXR_Server($callbacks = false, $data = false) {
</del><ins>+
+    function IXR_Server($callbacks = false, $data = false, $wait = false)
+    {
</ins><span class="cx">         $this->setCapabilities();
</span><span class="cx">         if ($callbacks) {
</span><span class="cx">             $this->callbacks = $callbacks;
</span><span class="cx">         }
</span><span class="cx">         $this->setCallbacks();
</span><del>-        $this->serve($data);
</del><ins>+        if (!$wait) {
+            $this->serve($data);
+        }
</ins><span class="cx">     }
</span><del>-    function serve($data = false) {
</del><ins>+
+    function serve($data = false)
+    {
</ins><span class="cx">         if (!$data) {
</span><ins>+            if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] !== 'POST') {
+                    header('Content-Type: text/plain'); // merged from WP #9093
+                die('XML-RPC server accepts POST requests only.');
+            }
+
</ins><span class="cx">             global $HTTP_RAW_POST_DATA;
</span><del>-            if (!$HTTP_RAW_POST_DATA) {
-               header( 'Content-Type: text/plain' );
-               die('XML-RPC server accepts POST requests only.');
</del><ins>+            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;
</ins><span class="cx">             }
</span><del>-            $data = &$HTTP_RAW_POST_DATA;
</del><span class="cx">         }
</span><span class="cx">         $this->message = new IXR_Message($data);
</span><span class="cx">         if (!$this->message->parse()) {
</span><span class="lines">@@ -321,75 +388,83 @@
</span><span class="cx">             $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall');
</span><span class="cx">         }
</span><span class="cx">         $result = $this->call($this->message->methodName, $this->message->params);
</span><ins>+
</ins><span class="cx">         // Is the result an error?
</span><span class="cx">         if (is_a($result, 'IXR_Error')) {
</span><span class="cx">             $this->error($result);
</span><span class="cx">         }
</span><ins>+
</ins><span class="cx">         // Encode the result
</span><span class="cx">         $r = new IXR_Value($result);
</span><span class="cx">         $resultxml = $r->getXml();
</span><ins>+
</ins><span class="cx">         // Create the XML
</span><span class="cx">         $xml = <<<EOD
</span><span class="cx"> <methodResponse>
</span><span class="cx">   <params>
</span><span class="cx">     <param>
</span><span class="cx">       <value>
</span><del>-        $resultxml
</del><ins>+      $resultxml
</ins><span class="cx">       </value>
</span><span class="cx">     </param>
</span><span class="cx">   </params>
</span><span class="cx"> </methodResponse>
</span><span class="cx"> 
</span><span class="cx"> EOD;
</span><del>-        // Send it
-        $this->output($xml);
</del><ins>+      // Send it
+      $this->output($xml);
</ins><span class="cx">     }
</span><del>-    function call($methodname, $args) {
</del><ins>+
+    function call($methodname, $args)
+    {
</ins><span class="cx">         if (!$this->hasMethod($methodname)) {
</span><del>-            return new IXR_Error(-32601, 'server error. requested method '.
-                $methodname.' does not exist.');
</del><ins>+            return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.');
</ins><span class="cx">         }
</span><span class="cx">         $method = $this->callbacks[$methodname];
</span><ins>+
</ins><span class="cx">         // Perform the callback and send the response
</span><span class="cx">         if (count($args) == 1) {
</span><span class="cx">             // If only one paramater just send that instead of the whole array
</span><span class="cx">             $args = $args[0];
</span><span class="cx">         }
</span><ins>+
</ins><span class="cx">         // Are we dealing with a function or a method?
</span><del>-        if ( is_string( $method ) && substr($method, 0, 5) == 'this:' ) {
</del><ins>+        if (is_string($method) && substr($method, 0, 5) == 'this:') {
</ins><span class="cx">             // It's a class method - check it exists
</span><span class="cx">             $method = substr($method, 5);
</span><span class="cx">             if (!method_exists($this, $method)) {
</span><del>-                return new IXR_Error(-32601, 'server error. requested class method "'.
-                    $method.'" does not exist.');
</del><ins>+                return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.');
</ins><span class="cx">             }
</span><del>-            // Call the method
</del><ins>+
+            //Call the method
</ins><span class="cx">             $result = $this->$method($args);
</span><span class="cx">         } else {
</span><span class="cx">             // It's a function - does it exist?
</span><span class="cx">             if (is_array($method)) {
</span><span class="cx">                 if (!method_exists($method[0], $method[1])) {
</span><del>-                    return new IXR_Error(-32601, 'server error. requested object method "'.
-                        $method[1].'" does not exist.');
</del><ins>+                    return new IXR_Error(-32601, 'server error. requested object method "'.$method[1].'" does not exist.');
</ins><span class="cx">                 }
</span><span class="cx">             } else if (!function_exists($method)) {
</span><del>-                return new IXR_Error(-32601, 'server error. requested function "'.
-                    $method.'" does not exist.');
</del><ins>+                return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.');
</ins><span class="cx">             }
</span><ins>+
</ins><span class="cx">             // Call the function
</span><span class="cx">             $result = call_user_func($method, $args);
</span><span class="cx">         }
</span><span class="cx">         return $result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function error($error, $message = false) {
</del><ins>+    function error($error, $message = false)
+    {
</ins><span class="cx">         // Accepts either an error object or an error code and message
</span><span class="cx">         if ($message && !is_object($error)) {
</span><span class="cx">             $error = new IXR_Error($error, $message);
</span><span class="cx">         }
</span><span class="cx">         $this->output($error->getXml());
</span><span class="cx">     }
</span><del>-    function output($xml) {
</del><ins>+
+    function output($xml)
+    {
</ins><span class="cx">         $xml = '<?xml version="1.0"?>'."\n".$xml;
</span><span class="cx">         $length = strlen($xml);
</span><span class="cx">         header('Connection: close');
</span><span class="lines">@@ -399,40 +474,52 @@
</span><span class="cx">         echo $xml;
</span><span class="cx">         exit;
</span><span class="cx">     }
</span><del>-    function hasMethod($method) {
</del><ins>+
+    function hasMethod($method)
+    {
</ins><span class="cx">         return in_array($method, array_keys($this->callbacks));
</span><span class="cx">     }
</span><del>-    function setCapabilities() {
</del><ins>+
+    function setCapabilities()
+    {
</ins><span class="cx">         // Initialises capabilities array
</span><span class="cx">         $this->capabilities = array(
</span><span class="cx">             'xmlrpc' => array(
</span><span class="cx">                 'specUrl' => 'http://www.xmlrpc.com/spec',
</span><span class="cx">                 'specVersion' => 1
</span><del>-            ),
</del><ins>+        ),
</ins><span class="cx">             'faults_interop' => array(
</span><span class="cx">                 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php',
</span><span class="cx">                 'specVersion' => 20010516
</span><del>-            ),
</del><ins>+        ),
</ins><span class="cx">             'system.multicall' => array(
</span><span class="cx">                 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208',
</span><span class="cx">                 'specVersion' => 1
</span><del>-            ),
</del><ins>+        ),
</ins><span class="cx">         );
</span><span class="cx">     }
</span><del>-    function getCapabilities($args) {
</del><ins>+
+    function getCapabilities($args)
+    {
</ins><span class="cx">         return $this->capabilities;
</span><span class="cx">     }
</span><del>-    function setCallbacks() {
</del><ins>+
+    function setCallbacks()
+    {
</ins><span class="cx">         $this->callbacks['system.getCapabilities'] = 'this:getCapabilities';
</span><span class="cx">         $this->callbacks['system.listMethods'] = 'this:listMethods';
</span><span class="cx">         $this->callbacks['system.multicall'] = 'this:multiCall';
</span><span class="cx">     }
</span><del>-    function listMethods($args) {
</del><ins>+
+    function listMethods($args)
+    {
</ins><span class="cx">         // Returns a list of methods - uses array_reverse to ensure user defined
</span><span class="cx">         // methods are listed before server defined methods
</span><span class="cx">         return array_reverse(array_keys($this->callbacks));
</span><span class="cx">     }
</span><del>-    function multiCall($methodcalls) {
</del><ins>+
+    function multiCall($methodcalls)
+    {
</ins><span class="cx">         // See http://www.xmlrpc.com/discuss/msgReader$1208
</span><span class="cx">         $return = array();
</span><span class="cx">         foreach ($methodcalls as $call) {
</span><span class="lines">@@ -462,11 +549,14 @@
</span><span class="cx">  * @package IXR
</span><span class="cx">  * @since 1.5
</span><span class="cx">  */
</span><del>-class IXR_Request {
</del><ins>+class IXR_Request
+{
</ins><span class="cx">     var $method;
</span><span class="cx">     var $args;
</span><span class="cx">     var $xml;
</span><del>-    function IXR_Request($method, $args) {
</del><ins>+
+    function IXR_Request($method, $args)
+    {
</ins><span class="cx">         $this->method = $method;
</span><span class="cx">         $this->args = $args;
</span><span class="cx">         $this->xml = <<<EOD
</span><span class="lines">@@ -484,10 +574,14 @@
</span><span class="cx">         }
</span><span class="cx">         $this->xml .= '</params></methodCall>';
</span><span class="cx">     }
</span><del>-    function getLength() {
</del><ins>+
+    function getLength()
+    {
</ins><span class="cx">         return strlen($this->xml);
</span><span class="cx">     }
</span><del>-    function getXml() {
</del><ins>+
+    function getXml()
+    {
</ins><span class="cx">         return $this->xml;
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -497,26 +591,31 @@
</span><span class="cx">  *
</span><span class="cx">  * @package IXR
</span><span class="cx">  * @since 1.5
</span><ins>+ *
</ins><span class="cx">  */
</span><del>-class IXR_Client {
</del><ins>+class IXR_Client
+{
</ins><span class="cx">     var $server;
</span><span class="cx">     var $port;
</span><span class="cx">     var $path;
</span><span class="cx">     var $useragent;
</span><del>-        var $headers;
</del><span class="cx">     var $response;
</span><span class="cx">     var $message = false;
</span><span class="cx">     var $debug = false;
</span><span class="cx">     var $timeout;
</span><ins>+
</ins><span class="cx">     // Storage place for an error message
</span><span class="cx">     var $error = false;
</span><del>-    function IXR_Client($server, $path = false, $port = 80, $timeout = false) {
</del><ins>+
+    function IXR_Client($server, $path = false, $port = 80, $timeout = 15)
+    {
</ins><span class="cx">         if (!$path) {
</span><span class="cx">             // Assume we have been given a URL instead
</span><span class="cx">             $bits = parse_url($server);
</span><span class="cx">             $this->server = $bits['host'];
</span><span class="cx">             $this->port = isset($bits['port']) ? $bits['port'] : 80;
</span><span class="cx">             $this->path = isset($bits['path']) ? $bits['path'] : '/';
</span><ins>+
</ins><span class="cx">             // Make absolutely sure we have a path
</span><span class="cx">             if (!$this->path) {
</span><span class="cx">                 $this->path = '/';
</span><span class="lines">@@ -529,7 +628,9 @@
</span><span class="cx">         $this->useragent = 'The Incutio XML-RPC PHP Library';
</span><span class="cx">         $this->timeout = $timeout;
</span><span class="cx">     }
</span><del>-    function query() {
</del><ins>+
+    function query()
+    {
</ins><span class="cx">         $args = func_get_args();
</span><span class="cx">         $method = array_shift($args);
</span><span class="cx">         $request = new IXR_Request($method, $args);
</span><span class="lines">@@ -538,33 +639,36 @@
</span><span class="cx">         $r = "\r\n";
</span><span class="cx">         $request  = "POST {$this->path} HTTP/1.0$r";
</span><span class="cx"> 
</span><del>-                $this->headers['Host']                        = $this->server;
-                $this->headers['Content-Type']        = 'text/xml';
-                $this->headers['User-Agent']        = $this->useragent;
-                $this->headers['Content-Length']= $length;
</del><ins>+        // 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;
</ins><span class="cx"> 
</span><del>-                foreach( $this->headers as $header => $value ) {
-                        $request .= "{$header}: {$value}{$r}";
-                }
-                $request .= $r;
</del><ins>+        foreach( $this->headers as $header => $value ) {
+            $request .= "{$header}: {$value}{$r}";
+        }
+        $request .= $r;
</ins><span class="cx"> 
</span><span class="cx">         $request .= $xml;
</span><ins>+
</ins><span class="cx">         // Now send the request
</span><span class="cx">         if ($this->debug) {
</span><span class="cx">             echo '<pre class="ixr_request">'.htmlspecialchars($request)."\n</pre>\n\n";
</span><span class="cx">         }
</span><ins>+
</ins><span class="cx">         if ($this->timeout) {
</span><span class="cx">             $fp = @fsockopen($this->server, $this->port, $errno, $errstr, $this->timeout);
</span><span class="cx">         } else {
</span><span class="cx">             $fp = @fsockopen($this->server, $this->port, $errno, $errstr);
</span><span class="cx">         }
</span><span class="cx">         if (!$fp) {
</span><del>-            $this->error = new IXR_Error(-32300, "transport error - could not open socket: $errno $errstr");
</del><ins>+            $this->error = new IXR_Error(-32300, 'transport error - could not open socket');
</ins><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="cx">         fputs($fp, $request);
</span><span class="cx">         $contents = '';
</span><del>-        $debug_contents = '';
</del><ins>+        $debugContents = '';
</ins><span class="cx">         $gotFirstLine = false;
</span><span class="cx">         $gettingHeaders = true;
</span><span class="cx">         while (!feof($fp)) {
</span><span class="lines">@@ -572,7 +676,7 @@
</span><span class="cx">             if (!$gotFirstLine) {
</span><span class="cx">                 // Check line for '200'
</span><span class="cx">                 if (strstr($line, '200') === false) {
</span><del>-                    $this->error = new IXR_Error(-32301, 'transport error - HTTP status code was not 200');
</del><ins>+                    $this->error = new IXR_Error(-32300, 'transport error - HTTP status code was not 200');
</ins><span class="cx">                     return false;
</span><span class="cx">                 }
</span><span class="cx">                 $gotFirstLine = true;
</span><span class="lines">@@ -581,16 +685,17 @@
</span><span class="cx">                 $gettingHeaders = false;
</span><span class="cx">             }
</span><span class="cx">             if (!$gettingHeaders) {
</span><del>-                    // WP#12559 remove trim so as to not strip newlines from received response.
</del><ins>+                    // merged from WP #12559 - remove trim
</ins><span class="cx">                 $contents .= $line;
</span><span class="cx">             }
</span><span class="cx">             if ($this->debug) {
</span><del>-                $debug_contents .= $line;
</del><ins>+                    $debugContents .= $line;
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         if ($this->debug) {
</span><del>-            echo '<pre class="ixr_response">'.htmlspecialchars($debug_contents)."\n</pre>\n\n";
</del><ins>+            echo '<pre class="ixr_response">'.htmlspecialchars($debugContents)."\n</pre>\n\n";
</ins><span class="cx">         }
</span><ins>+
</ins><span class="cx">         // Now parse what we've got back
</span><span class="cx">         $this->message = new IXR_Message($contents);
</span><span class="cx">         if (!$this->message->parse()) {
</span><span class="lines">@@ -598,44 +703,59 @@
</span><span class="cx">             $this->error = new IXR_Error(-32700, 'parse error. not well formed');
</span><span class="cx">             return false;
</span><span class="cx">         }
</span><ins>+
</ins><span class="cx">         // Is the message a fault?
</span><span class="cx">         if ($this->message->messageType == 'fault') {
</span><span class="cx">             $this->error = new IXR_Error($this->message->faultCode, $this->message->faultString);
</span><span class="cx">             return false;
</span><span class="cx">         }
</span><ins>+
</ins><span class="cx">         // Message must be OK
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><del>-    function getResponse() {
</del><ins>+
+    function getResponse()
+    {
</ins><span class="cx">         // methodResponses can only have one param - return that
</span><span class="cx">         return $this->message->params[0];
</span><span class="cx">     }
</span><del>-    function isError() {
</del><ins>+
+    function isError()
+    {
</ins><span class="cx">         return (is_object($this->error));
</span><span class="cx">     }
</span><del>-    function getErrorCode() {
</del><ins>+
+    function getErrorCode()
+    {
</ins><span class="cx">         return $this->error->code;
</span><span class="cx">     }
</span><del>-    function getErrorMessage() {
</del><ins>+
+    function getErrorMessage()
+    {
</ins><span class="cx">         return $this->error->message;
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> /**
</span><span class="cx">  * IXR_Error
</span><span class="cx">  *
</span><span class="cx">  * @package IXR
</span><span class="cx">  * @since 1.5
</span><span class="cx">  */
</span><del>-class IXR_Error {
</del><ins>+class IXR_Error
+{
</ins><span class="cx">     var $code;
</span><span class="cx">     var $message;
</span><del>-    function IXR_Error($code, $message) {
</del><ins>+
+    function IXR_Error($code, $message)
+    {
</ins><span class="cx">         $this->code = $code;
</span><del>-        // WP adds htmlspecialchars(). See #5666
</del><span class="cx">         $this->message = htmlspecialchars($message);
</span><span class="cx">     }
</span><del>-    function getXml() {
</del><ins>+
+    function getXml()
+    {
</ins><span class="cx">         $xml = <<<EOD
</span><span class="cx"> <methodResponse>
</span><span class="cx">   <fault>
</span><span class="lines">@@ -673,7 +793,9 @@
</span><span class="cx">     var $minute;
</span><span class="cx">     var $second;
</span><span class="cx">     var $timezone;
</span><del>-    function IXR_Date($time) {
</del><ins>+
+    function IXR_Date($time)
+    {
</ins><span class="cx">         // $time can be a PHP timestamp or an ISO one
</span><span class="cx">         if (is_numeric($time)) {
</span><span class="cx">             $this->parseTimestamp($time);
</span><span class="lines">@@ -681,34 +803,41 @@
</span><span class="cx">             $this->parseIso($time);
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-    function parseTimestamp($timestamp) {
</del><ins>+
+    function parseTimestamp($timestamp)
+    {
</ins><span class="cx">         $this->year = date('Y', $timestamp);
</span><span class="cx">         $this->month = date('m', $timestamp);
</span><span class="cx">         $this->day = date('d', $timestamp);
</span><span class="cx">         $this->hour = date('H', $timestamp);
</span><span class="cx">         $this->minute = date('i', $timestamp);
</span><span class="cx">         $this->second = date('s', $timestamp);
</span><del>-        // WP adds timezone. See #2036
</del><span class="cx">         $this->timezone = '';
</span><span class="cx">     }
</span><del>-    function parseIso($iso) {
</del><ins>+
+    function parseIso($iso)
+    {
</ins><span class="cx">         $this->year = substr($iso, 0, 4);
</span><span class="cx">         $this->month = substr($iso, 4, 2);
</span><span class="cx">         $this->day = substr($iso, 6, 2);
</span><span class="cx">         $this->hour = substr($iso, 9, 2);
</span><span class="cx">         $this->minute = substr($iso, 12, 2);
</span><span class="cx">         $this->second = substr($iso, 15, 2);
</span><del>-        // WP adds timezone. See #2036
</del><span class="cx">         $this->timezone = substr($iso, 17);
</span><span class="cx">     }
</span><del>-    function getIso() {
-            // WP adds timezone. See #2036
</del><ins>+
+    function getIso()
+    {
</ins><span class="cx">         return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second.$this->timezone;
</span><span class="cx">     }
</span><del>-    function getXml() {
</del><ins>+
+    function getXml()
+    {
</ins><span class="cx">         return '<dateTime.iso8601>'.$this->getIso().'</dateTime.iso8601>';
</span><span class="cx">     }
</span><del>-    function getTimestamp() {
</del><ins>+
+    function getTimestamp()
+    {
</ins><span class="cx">         return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year);
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -719,12 +848,17 @@
</span><span class="cx">  * @package IXR
</span><span class="cx">  * @since 1.5
</span><span class="cx">  */
</span><del>-class IXR_Base64 {
</del><ins>+class IXR_Base64
+{
</ins><span class="cx">     var $data;
</span><del>-    function IXR_Base64($data) {
</del><ins>+
+    function IXR_Base64($data)
+    {
</ins><span class="cx">         $this->data = $data;
</span><span class="cx">     }
</span><del>-    function getXml() {
</del><ins>+
+    function getXml()
+    {
</ins><span class="cx">         return '<base64>'.base64_encode($this->data).'</base64>';
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -735,10 +869,13 @@
</span><span class="cx">  * @package IXR
</span><span class="cx">  * @since 1.5
</span><span class="cx">  */
</span><del>-class IXR_IntrospectionServer extends IXR_Server {
</del><ins>+class IXR_IntrospectionServer extends IXR_Server
+{
</ins><span class="cx">     var $signatures;
</span><span class="cx">     var $help;
</span><del>-    function IXR_IntrospectionServer() {
</del><ins>+
+    function IXR_IntrospectionServer()
+    {
</ins><span class="cx">         $this->setCallbacks();
</span><span class="cx">         $this->setCapabilities();
</span><span class="cx">         $this->capabilities['introspection'] = array(
</span><span class="lines">@@ -770,16 +907,21 @@
</span><span class="cx">             'Returns a documentation string for the specified method'
</span><span class="cx">         );
</span><span class="cx">     }
</span><del>-    function addCallback($method, $callback, $args, $help) {
</del><ins>+
+    function addCallback($method, $callback, $args, $help)
+    {
</ins><span class="cx">         $this->callbacks[$method] = $callback;
</span><span class="cx">         $this->signatures[$method] = $args;
</span><span class="cx">         $this->help[$method] = $help;
</span><span class="cx">     }
</span><del>-    function call($methodname, $args) {
</del><ins>+
+    function call($methodname, $args)
+    {
</ins><span class="cx">         // Make sure it's in an array
</span><span class="cx">         if ($args && !is_array($args)) {
</span><span class="cx">             $args = array($args);
</span><span class="cx">         }
</span><ins>+
</ins><span class="cx">         // Over-rides default call method, adds signature check
</span><span class="cx">         if (!$this->hasMethod($methodname)) {
</span><span class="cx">             return new IXR_Error(-32601, 'server error. requested method "'.$this->message->methodName.'" not specified.');
</span><span class="lines">@@ -787,10 +929,12 @@
</span><span class="cx">         $method = $this->callbacks[$methodname];
</span><span class="cx">         $signature = $this->signatures[$methodname];
</span><span class="cx">         $returnType = array_shift($signature);
</span><ins>+
</ins><span class="cx">         // Check the number of arguments
</span><span class="cx">         if (count($args) != count($signature)) {
</span><span class="cx">             return new IXR_Error(-32602, 'server error. wrong number of method parameters');
</span><span class="cx">         }
</span><ins>+
</ins><span class="cx">         // Check the argument types
</span><span class="cx">         $ok = true;
</span><span class="cx">         $argsbackup = $args;
</span><span class="lines">@@ -835,7 +979,9 @@
</span><span class="cx">         // It passed the test - run the "real" method call
</span><span class="cx">         return parent::call($methodname, $argsbackup);
</span><span class="cx">     }
</span><del>-    function methodSignature($method) {
</del><ins>+
+    function methodSignature($method)
+    {
</ins><span class="cx">         if (!$this->hasMethod($method)) {
</span><span class="cx">             return new IXR_Error(-32601, 'server error. requested method "'.$method.'" not specified.');
</span><span class="cx">         }
</span><span class="lines">@@ -873,7 +1019,9 @@
</span><span class="cx">         }
</span><span class="cx">         return $return;
</span><span class="cx">     }
</span><del>-    function methodHelp($method) {
</del><ins>+
+    function methodHelp($method)
+    {
</ins><span class="cx">         return $this->help[$method];
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -884,13 +1032,18 @@
</span><span class="cx">  * @package IXR
</span><span class="cx">  * @since 1.5
</span><span class="cx">  */
</span><del>-class IXR_ClientMulticall extends IXR_Client {
</del><ins>+class IXR_ClientMulticall extends IXR_Client
+{
</ins><span class="cx">     var $calls = array();
</span><del>-    function IXR_ClientMulticall($server, $path = false, $port = 80) {
</del><ins>+
+    function IXR_ClientMulticall($server, $path = false, $port = 80)
+    {
</ins><span class="cx">         parent::IXR_Client($server, $path, $port);
</span><span class="cx">         $this->useragent = 'The Incutio XML-RPC PHP Library (multicall client)';
</span><span class="cx">     }
</span><del>-    function addCall() {
</del><ins>+
+    function addCall()
+    {
</ins><span class="cx">         $args = func_get_args();
</span><span class="cx">         $methodName = array_shift($args);
</span><span class="cx">         $struct = array(
</span><span class="lines">@@ -899,7 +1052,9 @@
</span><span class="cx">         );
</span><span class="cx">         $this->calls[] = $struct;
</span><span class="cx">     }
</span><del>-    function query() {
</del><ins>+
+    function query()
+    {
</ins><span class="cx">         // Prepare multicall, then call the parent::query() method
</span><span class="cx">         return parent::query('system.multicall', $this->calls);
</span><span class="cx">     }
</span></span></pre>
</div>
</div>
</body>
</html>