WordPress.org

Make WordPress Core


Ignore:
Timestamp:
08/26/2016 10:07:14 PM (3 years ago)
Author:
wonderboymusic
Message:

XML-RPC: break up class-IXR.php into individual class files.

See #37827.

Location:
trunk/src/wp-includes/IXR
Files:
1 added
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/IXR/class-IXR-message.php

    r38384 r38389  
    11<?php
    2 /**
    3  * IXR - The Incutio XML-RPC Library
    4  *
    5  * Copyright (c) 2010, Incutio Ltd.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions are met:
    10  *
    11  *  - Redistributions of source code must retain the above copyright notice,
    12  *    this list of conditions and the following disclaimer.
    13  *  - Redistributions in binary form must reproduce the above copyright
    14  *    notice, this list of conditions and the following disclaimer in the
    15  *    documentation and/or other materials provided with the distribution.
    16  *  - Neither the name of Incutio Ltd. nor the names of its contributors
    17  *    may be used to endorse or promote products derived from this software
    18  *    without specific prior written permission.
    19  *
    20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
    21  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
    24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
    28  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
    30  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31  *
    32  * @package IXR
    33  * @since 1.5.0
    34  *
    35  * @copyright  Incutio Ltd 2010 (http://www.incutio.com)
    36  * @version    1.7.4 7th September 2010
    37  * @author     Simon Willison
    38  * @link       http://scripts.incutio.com/xmlrpc/ Site/manual
    39  * @license    http://www.opensource.org/licenses/bsd-license.php BSD
    40  */
    41 
    42 /**
    43  * IXR_Value
    44  *
    45  * @package IXR
    46  * @since 1.5.0
    47  */
    48 class IXR_Value {
    49     var $data;
    50     var $type;
    51 
    52     /**
    53      * PHP5 constructor.
    54      */
    55     function __construct( $data, $type = false )
    56     {
    57         $this->data = $data;
    58         if (!$type) {
    59             $type = $this->calculateType();
    60         }
    61         $this->type = $type;
    62         if ($type == 'struct') {
    63             // Turn all the values in the array in to new IXR_Value objects
    64             foreach ($this->data as $key => $value) {
    65                 $this->data[$key] = new IXR_Value($value);
    66             }
    67         }
    68         if ($type == 'array') {
    69             for ($i = 0, $j = count($this->data); $i < $j; $i++) {
    70                 $this->data[$i] = new IXR_Value($this->data[$i]);
    71             }
    72         }
    73     }
    74 
    75     /**
    76      * PHP4 constructor.
    77      */
    78     public function IXR_Value( $data, $type = false ) {
    79         self::__construct( $data, $type );
    80     }
    81 
    82     function calculateType()
    83     {
    84         if ($this->data === true || $this->data === false) {
    85             return 'boolean';
    86         }
    87         if (is_integer($this->data)) {
    88             return 'int';
    89         }
    90         if (is_double($this->data)) {
    91             return 'double';
    92         }
    93 
    94         // Deal with IXR object types base64 and date
    95         if (is_object($this->data) && is_a($this->data, 'IXR_Date')) {
    96             return 'date';
    97         }
    98         if (is_object($this->data) && is_a($this->data, 'IXR_Base64')) {
    99             return 'base64';
    100         }
    101 
    102         // If it is a normal PHP object convert it in to a struct
    103         if (is_object($this->data)) {
    104             $this->data = get_object_vars($this->data);
    105             return 'struct';
    106         }
    107         if (!is_array($this->data)) {
    108             return 'string';
    109         }
    110 
    111         // We have an array - is it an array or a struct?
    112         if ($this->isStruct($this->data)) {
    113             return 'struct';
    114         } else {
    115             return 'array';
    116         }
    117     }
    118 
    119     function getXml()
    120     {
    121         // Return XML for this value
    122         switch ($this->type) {
    123             case 'boolean':
    124                 return '<boolean>'.(($this->data) ? '1' : '0').'</boolean>';
    125                 break;
    126             case 'int':
    127                 return '<int>'.$this->data.'</int>';
    128                 break;
    129             case 'double':
    130                 return '<double>'.$this->data.'</double>';
    131                 break;
    132             case 'string':
    133                 return '<string>'.htmlspecialchars($this->data).'</string>';
    134                 break;
    135             case 'array':
    136                 $return = '<array><data>'."\n";
    137                 foreach ($this->data as $item) {
    138                     $return .= '  <value>'.$item->getXml()."</value>\n";
    139                 }
    140                 $return .= '</data></array>';
    141                 return $return;
    142                 break;
    143             case 'struct':
    144                 $return = '<struct>'."\n";
    145                 foreach ($this->data as $name => $value) {
    146                     $name = htmlspecialchars($name);
    147                     $return .= "  <member><name>$name</name><value>";
    148                     $return .= $value->getXml()."</value></member>\n";
    149                 }
    150                 $return .= '</struct>';
    151                 return $return;
    152                 break;
    153             case 'date':
    154             case 'base64':
    155                 return $this->data->getXml();
    156                 break;
    157         }
    158         return false;
    159     }
    160 
    161     /**
    162      * Checks whether or not the supplied array is a struct or not
    163      *
    164      * @param array $array
    165      * @return bool
    166      */
    167     function isStruct($array)
    168     {
    169         $expected = 0;
    170         foreach ($array as $key => $value) {
    171             if ((string)$key !== (string)$expected) {
    172                 return true;
    173             }
    174             $expected++;
    175         }
    176         return false;
    177     }
    178 }
    1792
    1803/**
     
    405228    }
    406229}
    407 
    408 /**
    409  * IXR_Server
    410  *
    411  * @package IXR
    412  * @since 1.5.0
    413  */
    414 class IXR_Server
    415 {
    416     var $data;
    417     var $callbacks = array();
    418     var $message;
    419     var $capabilities;
    420 
    421     /**
    422      * PHP5 constructor.
    423      */
    424     function __construct( $callbacks = false, $data = false, $wait = false )
    425     {
    426         $this->setCapabilities();
    427         if ($callbacks) {
    428             $this->callbacks = $callbacks;
    429         }
    430         $this->setCallbacks();
    431         if (!$wait) {
    432             $this->serve($data);
    433         }
    434     }
    435 
    436     /**
    437      * PHP4 constructor.
    438      */
    439     public function IXR_Server( $callbacks = false, $data = false, $wait = false ) {
    440         self::__construct( $callbacks, $data, $wait );
    441     }
    442 
    443     function serve($data = false)
    444     {
    445         if (!$data) {
    446             if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] !== 'POST') {
    447                 if ( function_exists( 'status_header' ) ) {
    448                     status_header( 405 ); // WP #20986
    449                     header( 'Allow: POST' );
    450                 }
    451                 header('Content-Type: text/plain'); // merged from WP #9093
    452                 die('XML-RPC server accepts POST requests only.');
    453             }
    454 
    455             global $HTTP_RAW_POST_DATA;
    456             if (empty($HTTP_RAW_POST_DATA)) {
    457                 // workaround for a bug in PHP 5.2.2 - http://bugs.php.net/bug.php?id=41293
    458                 $data = file_get_contents('php://input');
    459             } else {
    460                 $data =& $HTTP_RAW_POST_DATA;
    461             }
    462         }
    463         $this->message = new IXR_Message($data);
    464         if (!$this->message->parse()) {
    465             $this->error(-32700, 'parse error. not well formed');
    466         }
    467         if ($this->message->messageType != 'methodCall') {
    468             $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall');
    469         }
    470         $result = $this->call($this->message->methodName, $this->message->params);
    471 
    472         // Is the result an error?
    473         if (is_a($result, 'IXR_Error')) {
    474             $this->error($result);
    475         }
    476 
    477         // Encode the result
    478         $r = new IXR_Value($result);
    479         $resultxml = $r->getXml();
    480 
    481         // Create the XML
    482         $xml = <<<EOD
    483 <methodResponse>
    484   <params>
    485     <param>
    486       <value>
    487       $resultxml
    488       </value>
    489     </param>
    490   </params>
    491 </methodResponse>
    492 
    493 EOD;
    494       // Send it
    495       $this->output($xml);
    496     }
    497 
    498     function call($methodname, $args)
    499     {
    500         if (!$this->hasMethod($methodname)) {
    501             return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.');
    502         }
    503         $method = $this->callbacks[$methodname];
    504 
    505         // Perform the callback and send the response
    506         if (count($args) == 1) {
    507             // If only one parameter just send that instead of the whole array
    508             $args = $args[0];
    509         }
    510 
    511         // Are we dealing with a function or a method?
    512         if (is_string($method) && substr($method, 0, 5) == 'this:') {
    513             // It's a class method - check it exists
    514             $method = substr($method, 5);
    515             if (!method_exists($this, $method)) {
    516                 return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.');
    517             }
    518 
    519             //Call the method
    520             $result = $this->$method($args);
    521         } else {
    522             // It's a function - does it exist?
    523             if (is_array($method)) {
    524                 if (!is_callable(array($method[0], $method[1]))) {
    525                     return new IXR_Error(-32601, 'server error. requested object method "'.$method[1].'" does not exist.');
    526                 }
    527             } else if (!function_exists($method)) {
    528                 return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.');
    529             }
    530 
    531             // Call the function
    532             $result = call_user_func($method, $args);
    533         }
    534         return $result;
    535     }
    536 
    537     function error($error, $message = false)
    538     {
    539         // Accepts either an error object or an error code and message
    540         if ($message && !is_object($error)) {
    541             $error = new IXR_Error($error, $message);
    542         }
    543         $this->output($error->getXml());
    544     }
    545 
    546     function output($xml)
    547     {
    548         $charset = function_exists('get_option') ? get_option('blog_charset') : '';
    549         if ($charset)
    550             $xml = '<?xml version="1.0" encoding="'.$charset.'"?>'."\n".$xml;
    551         else
    552             $xml = '<?xml version="1.0"?>'."\n".$xml;
    553         $length = strlen($xml);
    554         header('Connection: close');
    555         if ($charset)
    556             header('Content-Type: text/xml; charset='.$charset);
    557         else
    558             header('Content-Type: text/xml');
    559         header('Date: '.date('r'));
    560         echo $xml;
    561         exit;
    562     }
    563 
    564     function hasMethod($method)
    565     {
    566         return in_array($method, array_keys($this->callbacks));
    567     }
    568 
    569     function setCapabilities()
    570     {
    571         // Initialises capabilities array
    572         $this->capabilities = array(
    573             'xmlrpc' => array(
    574                 'specUrl' => 'http://www.xmlrpc.com/spec',
    575                 'specVersion' => 1
    576         ),
    577             'faults_interop' => array(
    578                 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php',
    579                 'specVersion' => 20010516
    580         ),
    581             'system.multicall' => array(
    582                 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208',
    583                 'specVersion' => 1
    584         ),
    585         );
    586     }
    587 
    588     function getCapabilities($args)
    589     {
    590         return $this->capabilities;
    591     }
    592 
    593     function setCallbacks()
    594     {
    595         $this->callbacks['system.getCapabilities'] = 'this:getCapabilities';
    596         $this->callbacks['system.listMethods'] = 'this:listMethods';
    597         $this->callbacks['system.multicall'] = 'this:multiCall';
    598     }
    599 
    600     function listMethods($args)
    601     {
    602         // Returns a list of methods - uses array_reverse to ensure user defined
    603         // methods are listed before server defined methods
    604         return array_reverse(array_keys($this->callbacks));
    605     }
    606 
    607     function multiCall($methodcalls)
    608     {
    609         // See http://www.xmlrpc.com/discuss/msgReader$1208
    610         $return = array();
    611         foreach ($methodcalls as $call) {
    612             $method = $call['methodName'];
    613             $params = $call['params'];
    614             if ($method == 'system.multicall') {
    615                 $result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden');
    616             } else {
    617                 $result = $this->call($method, $params);
    618             }
    619             if (is_a($result, 'IXR_Error')) {
    620                 $return[] = array(
    621                     'faultCode' => $result->code,
    622                     'faultString' => $result->message
    623                 );
    624             } else {
    625                 $return[] = array($result);
    626             }
    627         }
    628         return $return;
    629     }
    630 }
    631 
    632 /**
    633  * IXR_Request
    634  *
    635  * @package IXR
    636  * @since 1.5.0
    637  */
    638 class IXR_Request
    639 {
    640     var $method;
    641     var $args;
    642     var $xml;
    643 
    644     /**
    645      * PHP5 constructor.
    646      */
    647     function __construct($method, $args)
    648     {
    649         $this->method = $method;
    650         $this->args = $args;
    651         $this->xml = <<<EOD
    652 <?xml version="1.0"?>
    653 <methodCall>
    654 <methodName>{$this->method}</methodName>
    655 <params>
    656 
    657 EOD;
    658         foreach ($this->args as $arg) {
    659             $this->xml .= '<param><value>';
    660             $v = new IXR_Value($arg);
    661             $this->xml .= $v->getXml();
    662             $this->xml .= "</value></param>\n";
    663         }
    664         $this->xml .= '</params></methodCall>';
    665     }
    666 
    667     /**
    668      * PHP4 constructor.
    669      */
    670     public function IXR_Request( $method, $args ) {
    671         self::__construct( $method, $args );
    672     }
    673 
    674     function getLength()
    675     {
    676         return strlen($this->xml);
    677     }
    678 
    679     function getXml()
    680     {
    681         return $this->xml;
    682     }
    683 }
    684 
    685 /**
    686  * IXR_Client
    687  *
    688  * @package IXR
    689  * @since 1.5.0
    690  *
    691  */
    692 class IXR_Client
    693 {
    694     var $server;
    695     var $port;
    696     var $path;
    697     var $useragent;
    698     var $response;
    699     var $message = false;
    700     var $debug = false;
    701     var $timeout;
    702     var $headers = array();
    703 
    704     // Storage place for an error message
    705     var $error = false;
    706 
    707     /**
    708      * PHP5 constructor.
    709      */
    710     function __construct( $server, $path = false, $port = 80, $timeout = 15 )
    711     {
    712         if (!$path) {
    713             // Assume we have been given a URL instead
    714             $bits = parse_url($server);
    715             $this->server = $bits['host'];
    716             $this->port = isset($bits['port']) ? $bits['port'] : 80;
    717             $this->path = isset($bits['path']) ? $bits['path'] : '/';
    718 
    719             // Make absolutely sure we have a path
    720             if (!$this->path) {
    721                 $this->path = '/';
    722             }
    723 
    724             if ( ! empty( $bits['query'] ) ) {
    725                 $this->path .= '?' . $bits['query'];
    726             }
    727         } else {
    728             $this->server = $server;
    729             $this->path = $path;
    730             $this->port = $port;
    731         }
    732         $this->useragent = 'The Incutio XML-RPC PHP Library';
    733         $this->timeout = $timeout;
    734     }
    735 
    736     /**
    737      * PHP4 constructor.
    738      */
    739     public function IXR_Client( $server, $path = false, $port = 80, $timeout = 15 ) {
    740         self::__construct( $server, $path, $port, $timeout );
    741     }
    742 
    743     function query()
    744     {
    745         $args = func_get_args();
    746         $method = array_shift($args);
    747         $request = new IXR_Request($method, $args);
    748         $length = $request->getLength();
    749         $xml = $request->getXml();
    750         $r = "\r\n";
    751         $request  = "POST {$this->path} HTTP/1.0$r";
    752 
    753         // Merged from WP #8145 - allow custom headers
    754         $this->headers['Host']          = $this->server;
    755         $this->headers['Content-Type']  = 'text/xml';
    756         $this->headers['User-Agent']    = $this->useragent;
    757         $this->headers['Content-Length']= $length;
    758 
    759         foreach( $this->headers as $header => $value ) {
    760             $request .= "{$header}: {$value}{$r}";
    761         }
    762         $request .= $r;
    763 
    764         $request .= $xml;
    765 
    766         // Now send the request
    767         if ($this->debug) {
    768             echo '<pre class="ixr_request">'.htmlspecialchars($request)."\n</pre>\n\n";
    769         }
    770 
    771         if ($this->timeout) {
    772             $fp = @fsockopen($this->server, $this->port, $errno, $errstr, $this->timeout);
    773         } else {
    774             $fp = @fsockopen($this->server, $this->port, $errno, $errstr);
    775         }
    776         if (!$fp) {
    777             $this->error = new IXR_Error(-32300, 'transport error - could not open socket');
    778             return false;
    779         }
    780         fputs($fp, $request);
    781         $contents = '';
    782         $debugContents = '';
    783         $gotFirstLine = false;
    784         $gettingHeaders = true;
    785         while (!feof($fp)) {
    786             $line = fgets($fp, 4096);
    787             if (!$gotFirstLine) {
    788                 // Check line for '200'
    789                 if (strstr($line, '200') === false) {
    790                     $this->error = new IXR_Error(-32300, 'transport error - HTTP status code was not 200');
    791                     return false;
    792                 }
    793                 $gotFirstLine = true;
    794             }
    795             if (trim($line) == '') {
    796                 $gettingHeaders = false;
    797             }
    798             if (!$gettingHeaders) {
    799                 // merged from WP #12559 - remove trim
    800                 $contents .= $line;
    801             }
    802             if ($this->debug) {
    803                 $debugContents .= $line;
    804             }
    805         }
    806         if ($this->debug) {
    807             echo '<pre class="ixr_response">'.htmlspecialchars($debugContents)."\n</pre>\n\n";
    808         }
    809 
    810         // Now parse what we've got back
    811         $this->message = new IXR_Message($contents);
    812         if (!$this->message->parse()) {
    813             // XML error
    814             $this->error = new IXR_Error(-32700, 'parse error. not well formed');
    815             return false;
    816         }
    817 
    818         // Is the message a fault?
    819         if ($this->message->messageType == 'fault') {
    820             $this->error = new IXR_Error($this->message->faultCode, $this->message->faultString);
    821             return false;
    822         }
    823 
    824         // Message must be OK
    825         return true;
    826     }
    827 
    828     function getResponse()
    829     {
    830         // methodResponses can only have one param - return that
    831         return $this->message->params[0];
    832     }
    833 
    834     function isError()
    835     {
    836         return (is_object($this->error));
    837     }
    838 
    839     function getErrorCode()
    840     {
    841         return $this->error->code;
    842     }
    843 
    844     function getErrorMessage()
    845     {
    846         return $this->error->message;
    847     }
    848 }
    849 
    850 
    851 /**
    852  * IXR_Error
    853  *
    854  * @package IXR
    855  * @since 1.5.0
    856  */
    857 class IXR_Error
    858 {
    859     var $code;
    860     var $message;
    861 
    862     /**
    863      * PHP5 constructor.
    864      */
    865     function __construct( $code, $message )
    866     {
    867         $this->code = $code;
    868         $this->message = htmlspecialchars($message);
    869     }
    870 
    871     /**
    872      * PHP4 constructor.
    873      */
    874     public function IXR_Error( $code, $message ) {
    875         self::__construct( $code, $message );
    876     }
    877 
    878     function getXml()
    879     {
    880         $xml = <<<EOD
    881 <methodResponse>
    882   <fault>
    883     <value>
    884       <struct>
    885         <member>
    886           <name>faultCode</name>
    887           <value><int>{$this->code}</int></value>
    888         </member>
    889         <member>
    890           <name>faultString</name>
    891           <value><string>{$this->message}</string></value>
    892         </member>
    893       </struct>
    894     </value>
    895   </fault>
    896 </methodResponse>
    897 
    898 EOD;
    899         return $xml;
    900     }
    901 }
    902 
    903 /**
    904  * IXR_Date
    905  *
    906  * @package IXR
    907  * @since 1.5.0
    908  */
    909 class IXR_Date {
    910     var $year;
    911     var $month;
    912     var $day;
    913     var $hour;
    914     var $minute;
    915     var $second;
    916     var $timezone;
    917 
    918     /**
    919      * PHP5 constructor.
    920      */
    921     function __construct( $time )
    922     {
    923         // $time can be a PHP timestamp or an ISO one
    924         if (is_numeric($time)) {
    925             $this->parseTimestamp($time);
    926         } else {
    927             $this->parseIso($time);
    928         }
    929     }
    930 
    931     /**
    932      * PHP4 constructor.
    933      */
    934     public function IXR_Date( $time ) {
    935         self::__construct( $time );
    936     }
    937 
    938     function parseTimestamp($timestamp)
    939     {
    940         $this->year = date('Y', $timestamp);
    941         $this->month = date('m', $timestamp);
    942         $this->day = date('d', $timestamp);
    943         $this->hour = date('H', $timestamp);
    944         $this->minute = date('i', $timestamp);
    945         $this->second = date('s', $timestamp);
    946         $this->timezone = '';
    947     }
    948 
    949     function parseIso($iso)
    950     {
    951         $this->year = substr($iso, 0, 4);
    952         $this->month = substr($iso, 4, 2);
    953         $this->day = substr($iso, 6, 2);
    954         $this->hour = substr($iso, 9, 2);
    955         $this->minute = substr($iso, 12, 2);
    956         $this->second = substr($iso, 15, 2);
    957         $this->timezone = substr($iso, 17);
    958     }
    959 
    960     function getIso()
    961     {
    962         return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second.$this->timezone;
    963     }
    964 
    965     function getXml()
    966     {
    967         return '<dateTime.iso8601>'.$this->getIso().'</dateTime.iso8601>';
    968     }
    969 
    970     function getTimestamp()
    971     {
    972         return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year);
    973     }
    974 }
    975 
    976 /**
    977  * IXR_Base64
    978  *
    979  * @package IXR
    980  * @since 1.5.0
    981  */
    982 class IXR_Base64
    983 {
    984     var $data;
    985 
    986     /**
    987      * PHP5 constructor.
    988      */
    989     function __construct( $data )
    990     {
    991         $this->data = $data;
    992     }
    993 
    994     /**
    995      * PHP4 constructor.
    996      */
    997     public function IXR_Base64( $data ) {
    998         self::__construct( $data );
    999     }
    1000 
    1001     function getXml()
    1002     {
    1003         return '<base64>'.base64_encode($this->data).'</base64>';
    1004     }
    1005 }
    1006 
    1007 /**
    1008  * IXR_IntrospectionServer
    1009  *
    1010  * @package IXR
    1011  * @since 1.5.0
    1012  */
    1013 class IXR_IntrospectionServer extends IXR_Server
    1014 {
    1015     var $signatures;
    1016     var $help;
    1017 
    1018     /**
    1019      * PHP5 constructor.
    1020      */
    1021     function __construct()
    1022     {
    1023         $this->setCallbacks();
    1024         $this->setCapabilities();
    1025         $this->capabilities['introspection'] = array(
    1026             'specUrl' => 'http://xmlrpc.usefulinc.com/doc/reserved.html',
    1027             'specVersion' => 1
    1028         );
    1029         $this->addCallback(
    1030             'system.methodSignature',
    1031             'this:methodSignature',
    1032             array('array', 'string'),
    1033             'Returns an array describing the return type and required parameters of a method'
    1034         );
    1035         $this->addCallback(
    1036             'system.getCapabilities',
    1037             'this:getCapabilities',
    1038             array('struct'),
    1039             'Returns a struct describing the XML-RPC specifications supported by this server'
    1040         );
    1041         $this->addCallback(
    1042             'system.listMethods',
    1043             'this:listMethods',
    1044             array('array'),
    1045             'Returns an array of available methods on this server'
    1046         );
    1047         $this->addCallback(
    1048             'system.methodHelp',
    1049             'this:methodHelp',
    1050             array('string', 'string'),
    1051             'Returns a documentation string for the specified method'
    1052         );
    1053     }
    1054 
    1055     /**
    1056      * PHP4 constructor.
    1057      */
    1058     public function IXR_IntrospectionServer() {
    1059         self::__construct();
    1060     }
    1061 
    1062     function addCallback($method, $callback, $args, $help)
    1063     {
    1064         $this->callbacks[$method] = $callback;
    1065         $this->signatures[$method] = $args;
    1066         $this->help[$method] = $help;
    1067     }
    1068 
    1069     function call($methodname, $args)
    1070     {
    1071         // Make sure it's in an array
    1072         if ($args && !is_array($args)) {
    1073             $args = array($args);
    1074         }
    1075 
    1076         // Over-rides default call method, adds signature check
    1077         if (!$this->hasMethod($methodname)) {
    1078             return new IXR_Error(-32601, 'server error. requested method "'.$this->message->methodName.'" not specified.');
    1079         }
    1080         $method = $this->callbacks[$methodname];
    1081         $signature = $this->signatures[$methodname];
    1082         $returnType = array_shift($signature);
    1083 
    1084         // Check the number of arguments
    1085         if (count($args) != count($signature)) {
    1086             return new IXR_Error(-32602, 'server error. wrong number of method parameters');
    1087         }
    1088 
    1089         // Check the argument types
    1090         $ok = true;
    1091         $argsbackup = $args;
    1092         for ($i = 0, $j = count($args); $i < $j; $i++) {
    1093             $arg = array_shift($args);
    1094             $type = array_shift($signature);
    1095             switch ($type) {
    1096                 case 'int':
    1097                 case 'i4':
    1098                     if (is_array($arg) || !is_int($arg)) {
    1099                         $ok = false;
    1100                     }
    1101                     break;
    1102                 case 'base64':
    1103                 case 'string':
    1104                     if (!is_string($arg)) {
    1105                         $ok = false;
    1106                     }
    1107                     break;
    1108                 case 'boolean':
    1109                     if ($arg !== false && $arg !== true) {
    1110                         $ok = false;
    1111                     }
    1112                     break;
    1113                 case 'float':
    1114                 case 'double':
    1115                     if (!is_float($arg)) {
    1116                         $ok = false;
    1117                     }
    1118                     break;
    1119                 case 'date':
    1120                 case 'dateTime.iso8601':
    1121                     if (!is_a($arg, 'IXR_Date')) {
    1122                         $ok = false;
    1123                     }
    1124                     break;
    1125             }
    1126             if (!$ok) {
    1127                 return new IXR_Error(-32602, 'server error. invalid method parameters');
    1128             }
    1129         }
    1130         // It passed the test - run the "real" method call
    1131         return parent::call($methodname, $argsbackup);
    1132     }
    1133 
    1134     function methodSignature($method)
    1135     {
    1136         if (!$this->hasMethod($method)) {
    1137             return new IXR_Error(-32601, 'server error. requested method "'.$method.'" not specified.');
    1138         }
    1139         // We should be returning an array of types
    1140         $types = $this->signatures[$method];
    1141         $return = array();
    1142         foreach ($types as $type) {
    1143             switch ($type) {
    1144                 case 'string':
    1145                     $return[] = 'string';
    1146                     break;
    1147                 case 'int':
    1148                 case 'i4':
    1149                     $return[] = 42;
    1150                     break;
    1151                 case 'double':
    1152                     $return[] = 3.1415;
    1153                     break;
    1154                 case 'dateTime.iso8601':
    1155                     $return[] = new IXR_Date(time());
    1156                     break;
    1157                 case 'boolean':
    1158                     $return[] = true;
    1159                     break;
    1160                 case 'base64':
    1161                     $return[] = new IXR_Base64('base64');
    1162                     break;
    1163                 case 'array':
    1164                     $return[] = array('array');
    1165                     break;
    1166                 case 'struct':
    1167                     $return[] = array('struct' => 'struct');
    1168                     break;
    1169             }
    1170         }
    1171         return $return;
    1172     }
    1173 
    1174     function methodHelp($method)
    1175     {
    1176         return $this->help[$method];
    1177     }
    1178 }
    1179 
    1180 /**
    1181  * IXR_ClientMulticall
    1182  *
    1183  * @package IXR
    1184  * @since 1.5.0
    1185  */
    1186 class IXR_ClientMulticall extends IXR_Client
    1187 {
    1188     var $calls = array();
    1189 
    1190     /**
    1191      * PHP5 constructor.
    1192      */
    1193     function __construct( $server, $path = false, $port = 80 )
    1194     {
    1195         parent::IXR_Client($server, $path, $port);
    1196         $this->useragent = 'The Incutio XML-RPC PHP Library (multicall client)';
    1197     }
    1198 
    1199     /**
    1200      * PHP4 constructor.
    1201      */
    1202     public function IXR_ClientMulticall( $server, $path = false, $port = 80 ) {
    1203         self::__construct( $server, $path, $port );
    1204     }
    1205 
    1206     function addCall()
    1207     {
    1208         $args = func_get_args();
    1209         $methodName = array_shift($args);
    1210         $struct = array(
    1211             'methodName' => $methodName,
    1212             'params' => $args
    1213         );
    1214         $this->calls[] = $struct;
    1215     }
    1216 
    1217     function query()
    1218     {
    1219         // Prepare multicall, then call the parent::query() method
    1220         return parent::query('system.multicall', $this->calls);
    1221     }
    1222 }
Note: See TracChangeset for help on using the changeset viewer.