blob: 3ed050a2e304729bf5b452cd684032506bd870ca [file] [log] [blame]
Andrey Andreeva30faf92011-12-25 18:15:34 +02001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Phil Sturgeon07c1ac82012-03-09 17:03:37 +00005 * An open source application development framework for PHP 5.2.4 or newer
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05007 * NOTICE OF LICENSE
Andrey Andreeva30faf92011-12-25 18:15:34 +02008 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05009 * Licensed under the Open Software License version 3.0
Andrey Andreeva30faf92011-12-25 18:15:34 +020010 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -050011 * This source file is subject to the Open Software License (OSL 3.0) that is
12 * bundled with this package in the files license.txt / license.rst. It is
13 * also available through the world wide web at this URL:
14 * http://opensource.org/licenses/OSL-3.0
15 * If you did not receive a copy of the license and are unable to obtain it
16 * through the world wide web, please send an email to
17 * licensing@ellislab.com so we can send you a copy immediately.
18 *
Derek Allard2067d1a2008-11-13 22:59:24 +000019 * @package CodeIgniter
Derek Jonesf4a4bd82011-10-20 12:18:42 -050020 * @author EllisLab Dev Team
Greg Aker0defe5d2012-01-01 18:46:41 -060021 * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
Derek Jonesf4a4bd82011-10-20 12:18:42 -050022 * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
Derek Allard2067d1a2008-11-13 22:59:24 +000023 * @link http://codeigniter.com
24 * @since Version 1.0
25 * @filesource
26 */
27
Derek Allard2067d1a2008-11-13 22:59:24 +000028/**
29 * XML-RPC request handler class
30 *
31 * @package CodeIgniter
32 * @subpackage Libraries
33 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -050034 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000035 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
36 */
Andrey Andreevc8709832012-04-04 13:43:53 +030037
38if ( ! function_exists('xml_parser_create'))
39{
40 show_error('Your PHP installation does not support XML');
41}
42
43// ------------------------------------------------------------------------
44
Derek Allard2067d1a2008-11-13 22:59:24 +000045class CI_Xmlrpc {
46
Andrey Andreeva30faf92011-12-25 18:15:34 +020047 public $debug = FALSE; // Debugging on or off
48 public $xmlrpcI4 = 'i4';
49 public $xmlrpcInt = 'int';
50 public $xmlrpcBoolean = 'boolean';
51 public $xmlrpcDouble = 'double';
52 public $xmlrpcString = 'string';
53 public $xmlrpcDateTime = 'dateTime.iso8601';
54 public $xmlrpcBase64 = 'base64';
55 public $xmlrpcArray = 'array';
56 public $xmlrpcStruct = 'struct';
Barry Mienydd671972010-10-04 16:33:58 +020057
Andrey Andreeva30faf92011-12-25 18:15:34 +020058 public $xmlrpcTypes = array();
59 public $valid_parents = array();
60 public $xmlrpcerr = array(); // Response numbers
61 public $xmlrpcstr = array(); // Response strings
Barry Mienydd671972010-10-04 16:33:58 +020062
Andrey Andreeva30faf92011-12-25 18:15:34 +020063 public $xmlrpc_defencoding = 'UTF-8';
64 public $xmlrpcName = 'XML-RPC for CodeIgniter';
65 public $xmlrpcVersion = '1.1';
66 public $xmlrpcerruser = 800; // Start of user errors
67 public $xmlrpcerrxml = 100; // Start of XML Parse errors
68 public $xmlrpc_backslash = ''; // formulate backslashes for escaping regexp
Barry Mienydd671972010-10-04 16:33:58 +020069
Andrey Andreeva30faf92011-12-25 18:15:34 +020070 public $client;
71 public $method;
72 public $data;
73 public $message = '';
74 public $error = ''; // Error string for request
75 public $result;
76 public $response = array(); // Response from remote server
Derek Allard2067d1a2008-11-13 22:59:24 +000077
Andrey Andreeva30faf92011-12-25 18:15:34 +020078 public $xss_clean = TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +000079
Derek Allard2067d1a2008-11-13 22:59:24 +000080
Andrey Andreevc8709832012-04-04 13:43:53 +030081 /**
82 * Constructor
83 *
84 * Initializes property default values
85 *
86 * @param array
87 * @return void
88 */
Greg Akera9263282010-11-10 15:26:43 -060089 public function __construct($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +000090 {
Derek Allard2067d1a2008-11-13 22:59:24 +000091 $this->xmlrpc_backslash = chr(92).chr(92);
Barry Mienydd671972010-10-04 16:33:58 +020092
Derek Allard2067d1a2008-11-13 22:59:24 +000093 // Types for info sent back and forth
94 $this->xmlrpcTypes = array(
Barry Mienydd671972010-10-04 16:33:58 +020095 $this->xmlrpcI4 => '1',
96 $this->xmlrpcInt => '1',
97 $this->xmlrpcBoolean => '1',
98 $this->xmlrpcString => '1',
99 $this->xmlrpcDouble => '1',
100 $this->xmlrpcDateTime => '1',
101 $this->xmlrpcBase64 => '1',
102 $this->xmlrpcArray => '2',
103 $this->xmlrpcStruct => '3'
Derek Allard2067d1a2008-11-13 22:59:24 +0000104 );
Barry Mienydd671972010-10-04 16:33:58 +0200105
Derek Allard2067d1a2008-11-13 22:59:24 +0000106 // Array of Valid Parents for Various XML-RPC elements
Timothy Warren0688ac92012-04-20 10:25:04 -0400107 $this->valid_parents = array('BOOLEAN' => array('VALUE'),
108 'I4' => array('VALUE'),
109 'INT' => array('VALUE'),
110 'STRING' => array('VALUE'),
111 'DOUBLE' => array('VALUE'),
112 'DATETIME.ISO8601' => array('VALUE'),
113 'BASE64' => array('VALUE'),
114 'ARRAY' => array('VALUE'),
115 'STRUCT' => array('VALUE'),
116 'PARAM' => array('PARAMS'),
117 'METHODNAME' => array('METHODCALL'),
118 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'),
119 'MEMBER' => array('STRUCT'),
120 'NAME' => array('MEMBER'),
121 'DATA' => array('ARRAY'),
122 'FAULT' => array('METHODRESPONSE'),
123 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT')
124 );
Barry Mienydd671972010-10-04 16:33:58 +0200125
126
Derek Allard2067d1a2008-11-13 22:59:24 +0000127 // XML-RPC Responses
128 $this->xmlrpcerr['unknown_method'] = '1';
129 $this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server';
130 $this->xmlrpcerr['invalid_return'] = '2';
Derek Jones37f4b9c2011-07-01 17:56:50 -0500131 $this->xmlrpcstr['invalid_return'] = 'The XML data received was either invalid or not in the correct form for XML-RPC. Turn on debugging to examine the XML data further.';
Derek Allard2067d1a2008-11-13 22:59:24 +0000132 $this->xmlrpcerr['incorrect_params'] = '3';
133 $this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method';
134 $this->xmlrpcerr['introspect_unknown'] = '4';
Andrey Andreeva30faf92011-12-25 18:15:34 +0200135 $this->xmlrpcstr['introspect_unknown'] = 'Cannot inspect signature for request: method unknown';
Derek Allard2067d1a2008-11-13 22:59:24 +0000136 $this->xmlrpcerr['http_error'] = '5';
137 $this->xmlrpcstr['http_error'] = "Did not receive a '200 OK' response from remote server.";
138 $this->xmlrpcerr['no_data'] = '6';
139 $this->xmlrpcstr['no_data'] ='No data received from server.';
Barry Mienydd671972010-10-04 16:33:58 +0200140
Derek Allard2067d1a2008-11-13 22:59:24 +0000141 $this->initialize($config);
Barry Mienydd671972010-10-04 16:33:58 +0200142
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300143 log_message('debug', 'XML-RPC Class Initialized');
Derek Allard2067d1a2008-11-13 22:59:24 +0000144 }
Barry Mienydd671972010-10-04 16:33:58 +0200145
Andrey Andreevc8709832012-04-04 13:43:53 +0300146 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000147
Andrey Andreevc8709832012-04-04 13:43:53 +0300148 /**
149 * Initialize
150 *
151 * @param array
152 * @return void
153 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200154 public function initialize($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000155 {
Derek Jones33559102009-02-02 18:50:38 +0000156 if (count($config) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000157 {
158 foreach ($config as $key => $val)
159 {
160 if (isset($this->$key))
161 {
Barry Mienydd671972010-10-04 16:33:58 +0200162 $this->$key = $val;
Derek Allard2067d1a2008-11-13 22:59:24 +0000163 }
164 }
165 }
166 }
Barry Mienydd671972010-10-04 16:33:58 +0200167
Andrey Andreevc8709832012-04-04 13:43:53 +0300168 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000169
Andrey Andreevc8709832012-04-04 13:43:53 +0300170 /**
171 * Parse server URL
172 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300173 * @param string $url
174 * @param int $port = 80
175 * @param string $proxy = FALSE
176 * @param int $proxy_port = 8080
Andrey Andreevc8709832012-04-04 13:43:53 +0300177 * @return void
178 */
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300179 public function server($url, $port = 80, $proxy = FALSE, $proxy_port = 8080)
Derek Allard2067d1a2008-11-13 22:59:24 +0000180 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200181 if (strpos($url, 'http') !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000182 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300183 $url = 'http://'.$url;
Derek Allard2067d1a2008-11-13 22:59:24 +0000184 }
Barry Mienydd671972010-10-04 16:33:58 +0200185
Derek Allard2067d1a2008-11-13 22:59:24 +0000186 $parts = parse_url($url);
Barry Mienydd671972010-10-04 16:33:58 +0200187
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300188 $path = isset($parts['path']) ? $parts['path'] : '/';
Barry Mienydd671972010-10-04 16:33:58 +0200189
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300190 if ( ! empty($parts['query']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000191 {
192 $path .= '?'.$parts['query'];
Barry Mienydd671972010-10-04 16:33:58 +0200193 }
194
Valio9dee5352012-07-02 10:42:28 +0300195 $this->client = new XML_RPC_Client($path, $parts['host'], $port, $proxy, $proxy_port);
Derek Allard2067d1a2008-11-13 22:59:24 +0000196 }
Barry Mienydd671972010-10-04 16:33:58 +0200197
Andrey Andreevc8709832012-04-04 13:43:53 +0300198 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000199
Andrey Andreevc8709832012-04-04 13:43:53 +0300200 /**
201 * Set Timeout
202 *
203 * @param int seconds
204 * @return void
205 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200206 public function timeout($seconds = 5)
Derek Allard2067d1a2008-11-13 22:59:24 +0000207 {
208 if ( ! is_null($this->client) && is_int($seconds))
209 {
210 $this->client->timeout = $seconds;
211 }
212 }
Barry Mienydd671972010-10-04 16:33:58 +0200213
Andrey Andreevc8709832012-04-04 13:43:53 +0300214 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000215
Andrey Andreevc8709832012-04-04 13:43:53 +0300216 /**
217 * Set Methods
218 *
219 * @param string method name
220 * @return void
221 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200222 public function method($function)
Derek Allard2067d1a2008-11-13 22:59:24 +0000223 {
224 $this->method = $function;
225 }
Barry Mienydd671972010-10-04 16:33:58 +0200226
Andrey Andreevc8709832012-04-04 13:43:53 +0300227 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000228
Andrey Andreevc8709832012-04-04 13:43:53 +0300229 /**
230 * Take Array of Data and Create Objects
231 *
232 * @param array
233 * @return void
234 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200235 public function request($incoming)
Derek Allard2067d1a2008-11-13 22:59:24 +0000236 {
237 if ( ! is_array($incoming))
238 {
239 // Send Error
Andrey Andreevc8709832012-04-04 13:43:53 +0300240 return;
Derek Allard2067d1a2008-11-13 22:59:24 +0000241 }
Barry Mienydd671972010-10-04 16:33:58 +0200242
Derek Allard2067d1a2008-11-13 22:59:24 +0000243 $this->data = array();
Barry Mienydd671972010-10-04 16:33:58 +0200244
Pascal Kriete14287f32011-02-14 13:39:34 -0500245 foreach ($incoming as $key => $value)
Derek Allard2067d1a2008-11-13 22:59:24 +0000246 {
247 $this->data[$key] = $this->values_parsing($value);
248 }
249 }
Barry Mienydd671972010-10-04 16:33:58 +0200250
Andrey Andreevc8709832012-04-04 13:43:53 +0300251 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200252
Andrey Andreevc8709832012-04-04 13:43:53 +0300253 /**
254 * Set Debug
255 *
256 * @param bool
257 * @return void
258 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200259 public function set_debug($flag = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000260 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100261 $this->debug = ($flag === TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000262 }
Barry Mienydd671972010-10-04 16:33:58 +0200263
Andrey Andreevc8709832012-04-04 13:43:53 +0300264 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000265
Andrey Andreevc8709832012-04-04 13:43:53 +0300266 /**
267 * Values Parsing
268 *
269 * @param mixed
270 * @return object
271 */
272 public function values_parsing($value)
Derek Allard2067d1a2008-11-13 22:59:24 +0000273 {
Derek Jones8c4b5e72010-01-06 22:21:41 +0000274 if (is_array($value) && array_key_exists(0, $value))
Derek Allard2067d1a2008-11-13 22:59:24 +0000275 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300276 if ( ! isset($value[1], $this->xmlrpcTypes[$value[1]]))
Derek Allard2067d1a2008-11-13 22:59:24 +0000277 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200278 $temp = new XML_RPC_Values($value[0], (is_array($value[0]) ? 'array' : 'string'));
Derek Allard2067d1a2008-11-13 22:59:24 +0000279 }
280 else
281 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100282 if (is_array($value[0]) && ($value[1] === 'struct' OR $value[1] === 'array'))
Andrey Andreeva30faf92011-12-25 18:15:34 +0200283 {
284 while (list($k) = each($value[0]))
285 {
286 $value[0][$k] = $this->values_parsing($value[0][$k], TRUE);
287 }
288 }
289
290 $temp = new XML_RPC_Values($value[0], $value[1]);
Derek Allard2067d1a2008-11-13 22:59:24 +0000291 }
292 }
293 else
294 {
295 $temp = new XML_RPC_Values($value, 'string');
296 }
297
298 return $temp;
299 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000300
Andrey Andreevc8709832012-04-04 13:43:53 +0300301 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000302
Andrey Andreevc8709832012-04-04 13:43:53 +0300303 /**
304 * Sends XML-RPC Request
305 *
306 * @return bool
307 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200308 public function send_request()
Derek Allard2067d1a2008-11-13 22:59:24 +0000309 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300310 $this->message = new XML_RPC_Message($this->method, $this->data);
Derek Allard2067d1a2008-11-13 22:59:24 +0000311 $this->message->debug = $this->debug;
Barry Mienydd671972010-10-04 16:33:58 +0200312
Andrey Andreeva30faf92011-12-25 18:15:34 +0200313 if ( ! $this->result = $this->client->send($this->message) OR ! is_object($this->result->val))
Derek Allard2067d1a2008-11-13 22:59:24 +0000314 {
315 $this->error = $this->result->errstr;
316 return FALSE;
317 }
Barry Mienydd671972010-10-04 16:33:58 +0200318
Derek Allard2067d1a2008-11-13 22:59:24 +0000319 $this->response = $this->result->decode();
Derek Allard2067d1a2008-11-13 22:59:24 +0000320 return TRUE;
321 }
Barry Mienydd671972010-10-04 16:33:58 +0200322
Andrey Andreevc8709832012-04-04 13:43:53 +0300323 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000324
Andrey Andreevc8709832012-04-04 13:43:53 +0300325 /**
326 * Returns Error
327 *
328 * @return string
329 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200330 public function display_error()
Derek Allard2067d1a2008-11-13 22:59:24 +0000331 {
332 return $this->error;
333 }
Barry Mienydd671972010-10-04 16:33:58 +0200334
Andrey Andreevc8709832012-04-04 13:43:53 +0300335 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000336
Andrey Andreevc8709832012-04-04 13:43:53 +0300337 /**
338 * Returns Remote Server Response
339 *
340 * @return string
341 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200342 public function display_response()
Derek Allard2067d1a2008-11-13 22:59:24 +0000343 {
344 return $this->response;
345 }
Barry Mienydd671972010-10-04 16:33:58 +0200346
Andrey Andreevc8709832012-04-04 13:43:53 +0300347 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200348
Andrey Andreevc8709832012-04-04 13:43:53 +0300349 /**
350 * Sends an Error Message for Server Request
351 *
352 * @param int
353 * @param string
354 * @return object
355 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200356 public function send_error_message($number, $message)
Derek Allard2067d1a2008-11-13 22:59:24 +0000357 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200358 return new XML_RPC_Response(0, $number, $message);
Derek Allard2067d1a2008-11-13 22:59:24 +0000359 }
Barry Mienydd671972010-10-04 16:33:58 +0200360
Andrey Andreevc8709832012-04-04 13:43:53 +0300361 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200362
Andrey Andreevc8709832012-04-04 13:43:53 +0300363 /**
364 * Send Response for Server Request
365 *
366 * @param array
367 * @return object
368 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200369 public function send_response($response)
Derek Allard2067d1a2008-11-13 22:59:24 +0000370 {
371 // $response should be array of values, which will be parsed
372 // based on their data and type into a valid group of XML-RPC values
Andrey Andreeva30faf92011-12-25 18:15:34 +0200373 return new XML_RPC_Response($this->values_parsing($response));
Derek Allard2067d1a2008-11-13 22:59:24 +0000374 }
Barry Mienydd671972010-10-04 16:33:58 +0200375
Derek Allard2067d1a2008-11-13 22:59:24 +0000376} // END XML_RPC Class
377
Derek Allard2067d1a2008-11-13 22:59:24 +0000378/**
379 * XML-RPC Client class
380 *
381 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500382 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000383 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
384 */
385class XML_RPC_Client extends CI_Xmlrpc
386{
Andrey Andreeva30faf92011-12-25 18:15:34 +0200387 public $path = '';
388 public $server = '';
389 public $port = 80;
Valio9dee5352012-07-02 10:42:28 +0300390 public $proxy = FALSE;
391 public $proxy_port = 8080;
Andrey Andreeva30faf92011-12-25 18:15:34 +0200392 public $errno = '';
393 public $errstring = '';
394 public $timeout = 5;
395 public $no_multicall = FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000396
Andrey Andreevc8709832012-04-04 13:43:53 +0300397 /**
398 * Constructor
399 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300400 * @param string $path
401 * @param object $server
402 * @param int $port = 80
403 * @param string $proxy = FALSE
404 * @param int $proxy_port = 8080
Andrey Andreevc8709832012-04-04 13:43:53 +0300405 * @return void
406 */
Valio9dee5352012-07-02 10:42:28 +0300407 public function __construct($path, $server, $port = 80, $proxy = FALSE, $proxy_port = 8080)
Derek Allard2067d1a2008-11-13 22:59:24 +0000408 {
Greg Akera9263282010-11-10 15:26:43 -0600409 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +0200410
Derek Allard2067d1a2008-11-13 22:59:24 +0000411 $this->port = $port;
412 $this->server = $server;
413 $this->path = $path;
Valio9dee5352012-07-02 10:42:28 +0300414 $this->proxy = $proxy;
415 $this->proxy_port = $proxy_port;
Derek Allard2067d1a2008-11-13 22:59:24 +0000416 }
Barry Mienydd671972010-10-04 16:33:58 +0200417
Andrey Andreevc8709832012-04-04 13:43:53 +0300418 // --------------------------------------------------------------------
419
420 /**
421 * Send message
422 *
423 * @param mixed
424 * @return object
425 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200426 public function send($msg)
Derek Allard2067d1a2008-11-13 22:59:24 +0000427 {
428 if (is_array($msg))
429 {
430 // Multi-call disabled
Andrey Andreevc8709832012-04-04 13:43:53 +0300431 return new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'], $this->xmlrpcstr['multicall_recursion']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000432 }
433
434 return $this->sendPayload($msg);
435 }
436
Andrey Andreevc8709832012-04-04 13:43:53 +0300437 // --------------------------------------------------------------------
438
439 /**
440 * Send payload
441 *
442 * @param object
443 * @return object
444 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200445 public function sendPayload($msg)
Barry Mienydd671972010-10-04 16:33:58 +0200446 {
Andrey Andreevc02e7c52012-07-02 16:43:43 +0300447 if ($this->proxy === FALSE)
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300448 {
449 $server = $this->server;
450 $port = $this->port;
Valentin Sheyretski09217ce2012-07-02 16:27:01 +0300451 }
452 else
453 {
Valio9dee5352012-07-02 10:42:28 +0300454 $server = $this->proxy;
455 $port = $this->proxy_port;
456 }
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300457
Valio9dee5352012-07-02 10:42:28 +0300458 $fp = @fsockopen($server, $port, $this->errno, $this->errstring, $this->timeout);
Barry Mienydd671972010-10-04 16:33:58 +0200459
Derek Allard2067d1a2008-11-13 22:59:24 +0000460 if ( ! is_resource($fp))
461 {
462 error_log($this->xmlrpcstr['http_error']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300463 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000464 }
Barry Mienydd671972010-10-04 16:33:58 +0200465
Pascal Kriete14287f32011-02-14 13:39:34 -0500466 if (empty($msg->payload))
Derek Allard2067d1a2008-11-13 22:59:24 +0000467 {
468 // $msg = XML_RPC_Messages
469 $msg->createPayload();
470 }
Barry Mienydd671972010-10-04 16:33:58 +0200471
Derek Allard2067d1a2008-11-13 22:59:24 +0000472 $r = "\r\n";
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300473 $op = 'POST '.$this->path.' HTTP/1.0'.$r
474 .'Host: '.$this->server.$r
475 .'Content-Type: text/xml'.$r
476 .'User-Agent: '.$this->xmlrpcName.$r
477 .'Content-Length: '.strlen($msg->payload).$r.$r
478 .$msg->payload;
Barry Mienydd671972010-10-04 16:33:58 +0200479
George Petsagourakis306b3782012-05-02 20:31:08 +0300480 if ( ! fwrite($fp, $op, strlen($op)))
Derek Allard2067d1a2008-11-13 22:59:24 +0000481 {
482 error_log($this->xmlrpcstr['http_error']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300483 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000484 }
Andrey Andreevc8709832012-04-04 13:43:53 +0300485
Derek Allard2067d1a2008-11-13 22:59:24 +0000486 $resp = $msg->parseResponse($fp);
487 fclose($fp);
488 return $resp;
489 }
490
Andrey Andreevc8709832012-04-04 13:43:53 +0300491} // END XML_RPC_Client Class
Derek Allard2067d1a2008-11-13 22:59:24 +0000492
493/**
494 * XML-RPC Response class
495 *
496 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500497 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000498 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
499 */
500class XML_RPC_Response
501{
Andrey Andreevc8709832012-04-04 13:43:53 +0300502 public $val = 0;
503 public $errno = 0;
504 public $errstr = '';
505 public $headers = array();
506 public $xss_clean = TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000507
Andrey Andreevc8709832012-04-04 13:43:53 +0300508 /**
509 * Constructor
510 *
511 * @param mixed
512 * @param int
513 * @param string
514 * @return void
515 */
Greg Akera9263282010-11-10 15:26:43 -0600516 public function __construct($val, $code = 0, $fstr = '')
Barry Mienydd671972010-10-04 16:33:58 +0200517 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100518 if ($code !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000519 {
520 // error
521 $this->errno = $code;
Andrey Andreevc8709832012-04-04 13:43:53 +0300522 $this->errstr = htmlspecialchars($fstr,
523 (is_php('5.4') ? ENT_XML1 | ENT_NOQUOTES : ENT_NOQUOTES),
524 'UTF-8');
Derek Allard2067d1a2008-11-13 22:59:24 +0000525 }
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300526 elseif ( ! is_object($val))
Derek Allard2067d1a2008-11-13 22:59:24 +0000527 {
528 // programmer error, not an object
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300529 error_log("Invalid type '".gettype($val)."' (value: ".$val.') passed to XML_RPC_Response. Defaulting to empty value.');
Derek Allard2067d1a2008-11-13 22:59:24 +0000530 $this->val = new XML_RPC_Values();
531 }
532 else
533 {
534 $this->val = $val;
535 }
536 }
537
Andrey Andreevc8709832012-04-04 13:43:53 +0300538 // --------------------------------------------------------------------
539
540 /**
541 * Fault code
542 *
543 * @return int
544 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200545 public function faultCode()
Derek Allard2067d1a2008-11-13 22:59:24 +0000546 {
547 return $this->errno;
548 }
549
Andrey Andreevc8709832012-04-04 13:43:53 +0300550 // --------------------------------------------------------------------
551
552 /**
553 * Fault string
554 *
555 * @return string
556 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200557 public function faultString()
Derek Allard2067d1a2008-11-13 22:59:24 +0000558 {
559 return $this->errstr;
560 }
561
Andrey Andreevc8709832012-04-04 13:43:53 +0300562 // --------------------------------------------------------------------
563
564 /**
565 * Value
566 *
567 * @return mixed
568 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200569 public function value()
Derek Allard2067d1a2008-11-13 22:59:24 +0000570 {
571 return $this->val;
572 }
Barry Mienydd671972010-10-04 16:33:58 +0200573
Andrey Andreevc8709832012-04-04 13:43:53 +0300574 // --------------------------------------------------------------------
575
576 /**
577 * Prepare response
578 *
579 * @return string xml
580 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200581 public function prepare_response()
Derek Allard2067d1a2008-11-13 22:59:24 +0000582 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200583 return "<methodResponse>\n"
Andrey Andreevc8709832012-04-04 13:43:53 +0300584 .($this->errno
585 ? '<fault>
Derek Allard2067d1a2008-11-13 22:59:24 +0000586 <value>
587 <struct>
588 <member>
589 <name>faultCode</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300590 <value><int>'.$this->errno.'</int></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000591 </member>
592 <member>
593 <name>faultString</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300594 <value><string>'.$this->errstr.'</string></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000595 </member>
596 </struct>
597 </value>
Andrey Andreeva30faf92011-12-25 18:15:34 +0200598</fault>'
Andrey Andreevc8709832012-04-04 13:43:53 +0300599 : "<params>\n<param>\n".$this->val->serialize_class()."</param>\n</params>")
600 ."\n</methodResponse>";
Derek Allard2067d1a2008-11-13 22:59:24 +0000601 }
Barry Mienydd671972010-10-04 16:33:58 +0200602
Andrey Andreevc8709832012-04-04 13:43:53 +0300603 // --------------------------------------------------------------------
604
605 /**
606 * Decode
607 *
608 * @param mixed
609 * @return array
610 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200611 public function decode($array = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000612 {
613 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +0200614
615 if (is_array($array))
Derek Allard2067d1a2008-11-13 22:59:24 +0000616 {
617 while (list($key) = each($array))
618 {
619 if (is_array($array[$key]))
620 {
621 $array[$key] = $this->decode($array[$key]);
622 }
623 else
624 {
Robin Sowell66a3fc02010-03-18 09:44:55 -0400625 $array[$key] = ($this->xss_clean) ? $CI->security->xss_clean($array[$key]) : $array[$key];
Derek Allard2067d1a2008-11-13 22:59:24 +0000626 }
627 }
Barry Mienydd671972010-10-04 16:33:58 +0200628
Andrey Andreevc8709832012-04-04 13:43:53 +0300629 return $array;
630 }
631
632 $result = $this->xmlrpc_decoder($this->val);
633
634 if (is_array($result))
635 {
636 $result = $this->decode($result);
Derek Allard2067d1a2008-11-13 22:59:24 +0000637 }
638 else
639 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300640 $result = ($this->xss_clean) ? $CI->security->xss_clean($result) : $result;
Derek Allard2067d1a2008-11-13 22:59:24 +0000641 }
Barry Mienydd671972010-10-04 16:33:58 +0200642
Derek Allard2067d1a2008-11-13 22:59:24 +0000643 return $result;
644 }
645
Andrey Andreevc8709832012-04-04 13:43:53 +0300646 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000647
Andrey Andreevc8709832012-04-04 13:43:53 +0300648 /**
649 * XML-RPC Object to PHP Types
650 *
651 * @param object
652 * @return array
653 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200654 public function xmlrpc_decoder($xmlrpc_val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000655 {
656 $kind = $xmlrpc_val->kindOf();
657
Alex Bilbied261b1e2012-06-02 11:12:16 +0100658 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +0000659 {
660 return $xmlrpc_val->scalarval();
661 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100662 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +0000663 {
664 reset($xmlrpc_val->me);
Andrey Andreevadc11752011-12-30 14:46:08 +0200665 $b = current($xmlrpc_val->me);
Derek Allard2067d1a2008-11-13 22:59:24 +0000666 $arr = array();
667
Andrey Andreeva30faf92011-12-25 18:15:34 +0200668 for ($i = 0, $size = count($b); $i < $size; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000669 {
670 $arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);
671 }
672 return $arr;
673 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100674 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +0000675 {
676 reset($xmlrpc_val->me['struct']);
677 $arr = array();
678
Pascal Kriete14287f32011-02-14 13:39:34 -0500679 while (list($key,$value) = each($xmlrpc_val->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000680 {
681 $arr[$key] = $this->xmlrpc_decoder($value);
682 }
683 return $arr;
684 }
685 }
Barry Mienydd671972010-10-04 16:33:58 +0200686
Andrey Andreevc8709832012-04-04 13:43:53 +0300687 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000688
Andrey Andreevc8709832012-04-04 13:43:53 +0300689 /**
690 * ISO-8601 time to server or UTC time
691 *
692 * @param string
693 * @param bool
694 * @return int unix timestamp
695 */
696 public function iso8601_decode($time, $utc = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000697 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300698 // return a time in the localtime, or UTC
Derek Allard2067d1a2008-11-13 22:59:24 +0000699 $t = 0;
700 if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))
701 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100702 $fnc = ($utc === TRUE) ? 'gmmktime' : 'mktime';
Pascal Kriete14287f32011-02-14 13:39:34 -0500703 $t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
Derek Allard2067d1a2008-11-13 22:59:24 +0000704 }
705 return $t;
706 }
Barry Mienydd671972010-10-04 16:33:58 +0200707
Andrey Andreevc8709832012-04-04 13:43:53 +0300708} // END XML_RPC_Response Class
Derek Allard2067d1a2008-11-13 22:59:24 +0000709
710/**
711 * XML-RPC Message class
712 *
713 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500714 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000715 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
716 */
717class XML_RPC_Message extends CI_Xmlrpc
718{
Andrey Andreeva30faf92011-12-25 18:15:34 +0200719 public $payload;
720 public $method_name;
Andrey Andreevc8709832012-04-04 13:43:53 +0300721 public $params = array();
722 public $xh = array();
Derek Allard2067d1a2008-11-13 22:59:24 +0000723
Andrey Andreevc8709832012-04-04 13:43:53 +0300724 /**
725 * Constructor
726 *
727 * @param string method name
728 * @param array
729 * @return void
730 */
731 public function __construct($method, $pars = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000732 {
Greg Akera9263282010-11-10 15:26:43 -0600733 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +0200734
Derek Allard2067d1a2008-11-13 22:59:24 +0000735 $this->method_name = $method;
Derek Jones33559102009-02-02 18:50:38 +0000736 if (is_array($pars) && count($pars) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000737 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200738 for ($i = 0, $c = count($pars); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000739 {
740 // $pars[$i] = XML_RPC_Values
741 $this->params[] = $pars[$i];
742 }
743 }
744 }
Barry Mienydd671972010-10-04 16:33:58 +0200745
Andrey Andreevc8709832012-04-04 13:43:53 +0300746 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200747
Andrey Andreevc8709832012-04-04 13:43:53 +0300748 /**
749 * Create Payload to Send
750 *
751 * @return void
752 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200753 public function createPayload()
Derek Allard2067d1a2008-11-13 22:59:24 +0000754 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300755 $this->payload = '<?xml version="1.0"?'.">\r\n<methodCall>\r\n"
756 .'<methodName>'.$this->method_name."</methodName>\r\n"
757 ."<params>\r\n";
Barry Mienydd671972010-10-04 16:33:58 +0200758
Andrey Andreeva30faf92011-12-25 18:15:34 +0200759 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000760 {
761 // $p = XML_RPC_Values
762 $p = $this->params[$i];
763 $this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n";
764 }
Barry Mienydd671972010-10-04 16:33:58 +0200765
Derek Allard2067d1a2008-11-13 22:59:24 +0000766 $this->payload .= "</params>\r\n</methodCall>\r\n";
767 }
Barry Mienydd671972010-10-04 16:33:58 +0200768
Andrey Andreevc8709832012-04-04 13:43:53 +0300769 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200770
Andrey Andreevc8709832012-04-04 13:43:53 +0300771 /**
772 * Parse External XML-RPC Server's Response
773 *
774 * @param resource
775 * @return object
776 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200777 public function parseResponse($fp)
Derek Allard2067d1a2008-11-13 22:59:24 +0000778 {
779 $data = '';
Barry Mienydd671972010-10-04 16:33:58 +0200780
Pascal Kriete14287f32011-02-14 13:39:34 -0500781 while ($datum = fread($fp, 4096))
Derek Allard2067d1a2008-11-13 22:59:24 +0000782 {
783 $data .= $datum;
784 }
Barry Mienydd671972010-10-04 16:33:58 +0200785
Andrey Andreevc8709832012-04-04 13:43:53 +0300786 // Display HTTP content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +0000787 if ($this->debug === TRUE)
788 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200789 echo "<pre>---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n</pre>";
Derek Allard2067d1a2008-11-13 22:59:24 +0000790 }
Barry Mienydd671972010-10-04 16:33:58 +0200791
Andrey Andreevc8709832012-04-04 13:43:53 +0300792 // Check for data
Andrey Andreeva30faf92011-12-25 18:15:34 +0200793 if ($data === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000794 {
795 error_log($this->xmlrpcstr['no_data']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300796 return new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000797 }
Barry Mienydd671972010-10-04 16:33:58 +0200798
Andrey Andreevc8709832012-04-04 13:43:53 +0300799 // Check for HTTP 200 Response
Andrey Andreev3dad2e72012-06-14 15:10:56 +0300800 if (strpos($data, 'HTTP') === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
Derek Allard2067d1a2008-11-13 22:59:24 +0000801 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300802 $errstr = substr($data, 0, strpos($data, "\n")-1);
803 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');
Derek Allard2067d1a2008-11-13 22:59:24 +0000804 }
Barry Mienydd671972010-10-04 16:33:58 +0200805
Derek Allard2067d1a2008-11-13 22:59:24 +0000806 //-------------------------------------
Derek Jones37f4b9c2011-07-01 17:56:50 -0500807 // Create and Set Up XML Parser
Derek Allard2067d1a2008-11-13 22:59:24 +0000808 //-------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200809
Derek Allard2067d1a2008-11-13 22:59:24 +0000810 $parser = xml_parser_create($this->xmlrpc_defencoding);
811
Andrey Andreeva30faf92011-12-25 18:15:34 +0200812 $this->xh[$parser] = array(
Andrey Andreevc8709832012-04-04 13:43:53 +0300813 'isf' => 0,
814 'ac' => '',
815 'headers' => array(),
816 'stack' => array(),
817 'valuestack' => array(),
818 'isf_reason' => 0
Andrey Andreeva30faf92011-12-25 18:15:34 +0200819 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000820
821 xml_set_object($parser, $this);
Andrey Andreevc8709832012-04-04 13:43:53 +0300822 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000823 xml_set_element_handler($parser, 'open_tag', 'closing_tag');
824 xml_set_character_data_handler($parser, 'character_data');
825 //xml_set_default_handler($parser, 'default_handler');
826
Andrey Andreevc8709832012-04-04 13:43:53 +0300827 // Get headers
Derek Allard2067d1a2008-11-13 22:59:24 +0000828 $lines = explode("\r\n", $data);
829 while (($line = array_shift($lines)))
830 {
831 if (strlen($line) < 1)
832 {
833 break;
834 }
835 $this->xh[$parser]['headers'][] = $line;
836 }
837 $data = implode("\r\n", $lines);
Barry Mienydd671972010-10-04 16:33:58 +0200838
Andrey Andreevc8709832012-04-04 13:43:53 +0300839 // Parse XML data
Derek Jones33559102009-02-02 18:50:38 +0000840 if ( ! xml_parse($parser, $data, count($data)))
Derek Allard2067d1a2008-11-13 22:59:24 +0000841 {
842 $errstr = sprintf('XML error: %s at line %d',
Andrey Andreevc8709832012-04-04 13:43:53 +0300843 xml_error_string(xml_get_error_code($parser)),
844 xml_get_current_line_number($parser));
Derek Allard2067d1a2008-11-13 22:59:24 +0000845 //error_log($errstr);
846 $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
847 xml_parser_free($parser);
848 return $r;
849 }
850 xml_parser_free($parser);
Barry Mienydd671972010-10-04 16:33:58 +0200851
Andrey Andreevc8709832012-04-04 13:43:53 +0300852 // Got ourselves some badness, it seems
Derek Allard2067d1a2008-11-13 22:59:24 +0000853 if ($this->xh[$parser]['isf'] > 1)
854 {
855 if ($this->debug === TRUE)
856 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200857 echo "---Invalid Return---\n".$this->xh[$parser]['isf_reason']."---Invalid Return---\n\n";
Derek Allard2067d1a2008-11-13 22:59:24 +0000858 }
Barry Mienydd671972010-10-04 16:33:58 +0200859
Andrey Andreevc8709832012-04-04 13:43:53 +0300860 return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000861 }
862 elseif ( ! is_object($this->xh[$parser]['value']))
863 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300864 return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000865 }
Barry Mienydd671972010-10-04 16:33:58 +0200866
Andrey Andreevc8709832012-04-04 13:43:53 +0300867 // Display XML content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +0000868 if ($this->debug === TRUE)
869 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300870 echo '<pre>';
Barry Mienydd671972010-10-04 16:33:58 +0200871
Derek Allard2067d1a2008-11-13 22:59:24 +0000872 if (count($this->xh[$parser]['headers'] > 0))
873 {
874 echo "---HEADERS---\n";
875 foreach ($this->xh[$parser]['headers'] as $header)
876 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300877 echo $header."\n";
Derek Allard2067d1a2008-11-13 22:59:24 +0000878 }
879 echo "---END HEADERS---\n\n";
880 }
Barry Mienydd671972010-10-04 16:33:58 +0200881
Andrey Andreeva30faf92011-12-25 18:15:34 +0200882 echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n---PARSED---\n";
Derek Allard2067d1a2008-11-13 22:59:24 +0000883 var_dump($this->xh[$parser]['value']);
884 echo "\n---END PARSED---</pre>";
885 }
Barry Mienydd671972010-10-04 16:33:58 +0200886
Andrey Andreevc8709832012-04-04 13:43:53 +0300887 // Send response
Derek Allard2067d1a2008-11-13 22:59:24 +0000888 $v = $this->xh[$parser]['value'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000889 if ($this->xh[$parser]['isf'])
890 {
891 $errno_v = $v->me['struct']['faultCode'];
892 $errstr_v = $v->me['struct']['faultString'];
893 $errno = $errno_v->scalarval();
894
Alex Bilbied261b1e2012-06-02 11:12:16 +0100895 if ($errno === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000896 {
897 // FAULT returned, errno needs to reflect that
898 $errno = -1;
899 }
900
901 $r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
902 }
903 else
904 {
905 $r = new XML_RPC_Response($v);
906 }
907
908 $r->headers = $this->xh[$parser]['headers'];
909 return $r;
910 }
Barry Mienydd671972010-10-04 16:33:58 +0200911
Andrey Andreevc8709832012-04-04 13:43:53 +0300912 // --------------------------------------------------------------------
913
Derek Allard2067d1a2008-11-13 22:59:24 +0000914 // ------------------------------------
Derek Jones37f4b9c2011-07-01 17:56:50 -0500915 // Begin Return Message Parsing section
Derek Allard2067d1a2008-11-13 22:59:24 +0000916 // ------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200917
Derek Allard2067d1a2008-11-13 22:59:24 +0000918 // quick explanation of components:
Derek Jones37f4b9c2011-07-01 17:56:50 -0500919 // ac - used to accumulate values
920 // isf - used to indicate a fault
921 // lv - used to indicate "looking for a value": implements
Derek Allard2067d1a2008-11-13 22:59:24 +0000922 // the logic to allow values with no types to be strings
Derek Jones37f4b9c2011-07-01 17:56:50 -0500923 // params - used to store parameters in method calls
924 // method - used to store method name
Derek Allard2067d1a2008-11-13 22:59:24 +0000925 // stack - array with parent tree of the xml element,
926 // used to validate the nesting of elements
927
Andrey Andreevc8709832012-04-04 13:43:53 +0300928 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000929
Andrey Andreevc8709832012-04-04 13:43:53 +0300930 /**
931 * Start Element Handler
932 *
933 * @param string
934 * @param string
935 * @return void
936 */
937 public function open_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +0000938 {
939 // If invalid nesting, then return
940 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +0200941
Derek Allard2067d1a2008-11-13 22:59:24 +0000942 // Evaluate and check for correct nesting of XML elements
Alex Bilbied261b1e2012-06-02 11:12:16 +0100943 if (count($this->xh[$the_parser]['stack']) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000944 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100945 if ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')
Derek Allard2067d1a2008-11-13 22:59:24 +0000946 {
947 $this->xh[$the_parser]['isf'] = 2;
948 $this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
949 return;
950 }
951 }
Andrey Andreevc8709832012-04-04 13:43:53 +0300952 // not top level element: see if parent is OK
953 elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +0000954 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300955 $this->xh[$the_parser]['isf'] = 2;
956 $this->xh[$the_parser]['isf_reason'] = 'XML-RPC element $name cannot be child of '.$this->xh[$the_parser]['stack'][0];
957 return;
Derek Allard2067d1a2008-11-13 22:59:24 +0000958 }
Barry Mienydd671972010-10-04 16:33:58 +0200959
Andrey Andreevc8709832012-04-04 13:43:53 +0300960 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +0000961 {
962 case 'STRUCT':
963 case 'ARRAY':
964 // Creates array for child elements
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300965 $cur_val = array('value' => array(), 'type' => $name);
Derek Allard2067d1a2008-11-13 22:59:24 +0000966 array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
Andrey Andreevc8709832012-04-04 13:43:53 +0300967 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000968 case 'METHODNAME':
969 case 'NAME':
970 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +0300971 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000972 case 'FAULT':
973 $this->xh[$the_parser]['isf'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +0300974 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000975 case 'PARAM':
Pascal Kriete8761ef52011-02-14 13:13:52 -0500976 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +0300977 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000978 case 'VALUE':
979 $this->xh[$the_parser]['vt'] = 'value';
980 $this->xh[$the_parser]['ac'] = '';
981 $this->xh[$the_parser]['lv'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +0300982 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000983 case 'I4':
984 case 'INT':
985 case 'STRING':
986 case 'BOOLEAN':
987 case 'DOUBLE':
988 case 'DATETIME.ISO8601':
989 case 'BASE64':
Alex Bilbied261b1e2012-06-02 11:12:16 +0100990 if ($this->xh[$the_parser]['vt'] !== 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +0000991 {
992 //two data elements inside a value: an error occurred!
993 $this->xh[$the_parser]['isf'] = 2;
Andrey Andreevc8709832012-04-04 13:43:53 +0300994 $this->xh[$the_parser]['isf_reason'] = "'Twas a ".$name.' element following a '
995 .$this->xh[$the_parser]['vt'].' element inside a single value';
Derek Allard2067d1a2008-11-13 22:59:24 +0000996 return;
997 }
Barry Mienydd671972010-10-04 16:33:58 +0200998
Derek Allard2067d1a2008-11-13 22:59:24 +0000999 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +03001000 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001001 case 'MEMBER':
1002 // Set name of <member> to nothing to prevent errors later if no <name> is found
1003 $this->xh[$the_parser]['valuestack'][0]['name'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001004
Derek Allard2067d1a2008-11-13 22:59:24 +00001005 // Set NULL value to check to see if value passed for this param/member
Pascal Kriete8761ef52011-02-14 13:13:52 -05001006 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +03001007 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001008 case 'DATA':
1009 case 'METHODCALL':
1010 case 'METHODRESPONSE':
1011 case 'PARAMS':
1012 // valid elements that add little to processing
Andrey Andreevc8709832012-04-04 13:43:53 +03001013 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001014 default:
1015 /// An Invalid Element is Found, so we have trouble
1016 $this->xh[$the_parser]['isf'] = 2;
Andrey Andreevc8709832012-04-04 13:43:53 +03001017 $this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;
1018 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001019 }
Barry Mienydd671972010-10-04 16:33:58 +02001020
Derek Allard2067d1a2008-11-13 22:59:24 +00001021 // Add current element name to stack, to allow validation of nesting
1022 array_unshift($this->xh[$the_parser]['stack'], $name);
1023
Alex Bilbied261b1e2012-06-02 11:12:16 +01001024 $name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001025 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001026
Andrey Andreevc8709832012-04-04 13:43:53 +03001027 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001028
Andrey Andreevc8709832012-04-04 13:43:53 +03001029 /**
1030 * End Element Handler
1031 *
1032 * @param string
1033 * @param string
1034 * @return void
1035 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001036 public function closing_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001037 {
1038 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001039
Derek Allard2067d1a2008-11-13 22:59:24 +00001040 // Remove current element from stack and set variable
1041 // NOTE: If the XML validates, then we do not have to worry about
Andrey Andreevc8709832012-04-04 13:43:53 +03001042 // the opening and closing of elements. Nesting is checked on the opening
Derek Allard2067d1a2008-11-13 22:59:24 +00001043 // tag so we be safe there as well.
Barry Mienydd671972010-10-04 16:33:58 +02001044
Derek Allard2067d1a2008-11-13 22:59:24 +00001045 $curr_elem = array_shift($this->xh[$the_parser]['stack']);
Barry Mienydd671972010-10-04 16:33:58 +02001046
Andrey Andreevc8709832012-04-04 13:43:53 +03001047 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001048 {
1049 case 'STRUCT':
1050 case 'ARRAY':
1051 $cur_val = array_shift($this->xh[$the_parser]['valuestack']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001052 $this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();
Derek Allard2067d1a2008-11-13 22:59:24 +00001053 $this->xh[$the_parser]['vt'] = strtolower($name);
Andrey Andreevc8709832012-04-04 13:43:53 +03001054 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001055 case 'NAME':
1056 $this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
Andrey Andreevc8709832012-04-04 13:43:53 +03001057 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001058 case 'BOOLEAN':
1059 case 'I4':
1060 case 'INT':
1061 case 'STRING':
1062 case 'DOUBLE':
1063 case 'DATETIME.ISO8601':
1064 case 'BASE64':
1065 $this->xh[$the_parser]['vt'] = strtolower($name);
Barry Mienydd671972010-10-04 16:33:58 +02001066
Alex Bilbied261b1e2012-06-02 11:12:16 +01001067 if ($name === 'STRING')
Derek Allard2067d1a2008-11-13 22:59:24 +00001068 {
1069 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1070 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001071 elseif ($name === 'DATETIME.ISO8601')
Derek Allard2067d1a2008-11-13 22:59:24 +00001072 {
1073 $this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime;
1074 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1075 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001076 elseif ($name === 'BASE64')
Derek Allard2067d1a2008-11-13 22:59:24 +00001077 {
1078 $this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
1079 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001080 elseif ($name === 'BOOLEAN')
Derek Allard2067d1a2008-11-13 22:59:24 +00001081 {
1082 // Translated BOOLEAN values to TRUE AND FALSE
Andrey Andreevc8709832012-04-04 13:43:53 +03001083 $this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001084 }
1085 elseif ($name=='DOUBLE')
1086 {
1087 // we have a DOUBLE
1088 // we must check that only 0123456789-.<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001089 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])
1090 ? (float) $this->xh[$the_parser]['ac']
1091 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001092 }
1093 else
1094 {
1095 // we have an I4/INT
1096 // we must check that only 0123456789-<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001097 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])
George Petsagourakis306b3782012-05-02 20:31:08 +03001098 ? (int) $this->xh[$the_parser]['ac']
Andrey Andreevc8709832012-04-04 13:43:53 +03001099 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001100 }
1101 $this->xh[$the_parser]['ac'] = '';
1102 $this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
Andrey Andreevc8709832012-04-04 13:43:53 +03001103 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001104 case 'VALUE':
1105 // This if() detects if no scalar was inside <VALUE></VALUE>
1106 if ($this->xh[$the_parser]['vt']=='value')
1107 {
1108 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1109 $this->xh[$the_parser]['vt'] = $this->xmlrpcString;
1110 }
Barry Mienydd671972010-10-04 16:33:58 +02001111
Derek Allard2067d1a2008-11-13 22:59:24 +00001112 // build the XML-RPC value out of the data received, and substitute it
1113 $temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
Barry Mienydd671972010-10-04 16:33:58 +02001114
Alex Bilbied261b1e2012-06-02 11:12:16 +01001115 if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')
Derek Allard2067d1a2008-11-13 22:59:24 +00001116 {
1117 // Array
1118 $this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
1119 }
1120 else
1121 {
1122 // Struct
1123 $this->xh[$the_parser]['value'] = $temp;
1124 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001125 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001126 case 'MEMBER':
Andrey Andreevc8709832012-04-04 13:43:53 +03001127 $this->xh[$the_parser]['ac'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001128
Derek Allard2067d1a2008-11-13 22:59:24 +00001129 // If value add to array in the stack for the last element built
1130 if ($this->xh[$the_parser]['value'])
1131 {
1132 $this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
1133 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001134 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001135 case 'DATA':
Andrey Andreevc8709832012-04-04 13:43:53 +03001136 $this->xh[$the_parser]['ac'] = '';
1137 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001138 case 'PARAM':
1139 if ($this->xh[$the_parser]['value'])
1140 {
1141 $this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
1142 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001143 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001144 case 'METHODNAME':
1145 $this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001146 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001147 case 'PARAMS':
1148 case 'FAULT':
1149 case 'METHODCALL':
1150 case 'METHORESPONSE':
1151 // We're all good kids with nuthin' to do
Andrey Andreevc8709832012-04-04 13:43:53 +03001152 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001153 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001154 // End of an Invalid Element. Taken care of during the opening tag though
1155 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001156 }
1157 }
1158
Andrey Andreevc8709832012-04-04 13:43:53 +03001159 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001160
Andrey Andreevc8709832012-04-04 13:43:53 +03001161 /**
1162 * Parse character data
1163 *
1164 * @param string
1165 * @param string
1166 * @return void
1167 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001168 public function character_data($the_parser, $data)
Derek Allard2067d1a2008-11-13 22:59:24 +00001169 {
1170 if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
Barry Mienydd671972010-10-04 16:33:58 +02001171
Derek Allard2067d1a2008-11-13 22:59:24 +00001172 // If a value has not been found
Alex Bilbied261b1e2012-06-02 11:12:16 +01001173 if ($this->xh[$the_parser]['lv'] !== 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001174 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001175 if ($this->xh[$the_parser]['lv'] === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001176 {
1177 $this->xh[$the_parser]['lv'] = 2; // Found a value
1178 }
Barry Mienydd671972010-10-04 16:33:58 +02001179
Andrey Andreevc8709832012-04-04 13:43:53 +03001180 if ( ! isset($this->xh[$the_parser]['ac']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001181 {
1182 $this->xh[$the_parser]['ac'] = '';
1183 }
Barry Mienydd671972010-10-04 16:33:58 +02001184
Derek Allard2067d1a2008-11-13 22:59:24 +00001185 $this->xh[$the_parser]['ac'] .= $data;
1186 }
1187 }
Barry Mienydd671972010-10-04 16:33:58 +02001188
Andrey Andreevc8709832012-04-04 13:43:53 +03001189 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001190
Andrey Andreevc8709832012-04-04 13:43:53 +03001191 /**
1192 * Add parameter
1193 *
1194 * @param mixed
1195 * @return void
1196 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001197 public function addParam($par)
1198 {
1199 $this->params[] = $par;
1200 }
Barry Mienydd671972010-10-04 16:33:58 +02001201
Andrey Andreevc8709832012-04-04 13:43:53 +03001202 // --------------------------------------------------------------------
1203
1204 /**
1205 * Output parameters
1206 *
1207 * @param array
1208 * @return array
1209 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001210 public function output_parameters($array = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001211 {
Barry Mienydd671972010-10-04 16:33:58 +02001212 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +02001213
1214 if (is_array($array))
Derek Allard2067d1a2008-11-13 22:59:24 +00001215 {
1216 while (list($key) = each($array))
1217 {
1218 if (is_array($array[$key]))
1219 {
1220 $array[$key] = $this->output_parameters($array[$key]);
1221 }
1222 else
1223 {
Derek Jonesa9647e82010-03-02 22:59:07 -06001224 // 'bits' is for the MetaWeblog API image bits
1225 // @todo - this needs to be made more general purpose
Alex Bilbied261b1e2012-06-02 11:12:16 +01001226 $array[$key] = ($key === 'bits' OR $this->xss_clean === FALSE) ? $array[$key] : $CI->security->xss_clean($array[$key]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001227 }
1228 }
Barry Mienydd671972010-10-04 16:33:58 +02001229
Andrey Andreevc8709832012-04-04 13:43:53 +03001230 return $array;
Derek Allard2067d1a2008-11-13 22:59:24 +00001231 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001232
1233 $parameters = array();
1234
1235 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001236 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001237 $a_param = $this->decode_message($this->params[$i]);
Barry Mienydd671972010-10-04 16:33:58 +02001238
Andrey Andreevc8709832012-04-04 13:43:53 +03001239 if (is_array($a_param))
Derek Allard2067d1a2008-11-13 22:59:24 +00001240 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001241 $parameters[] = $this->output_parameters($a_param);
1242 }
1243 else
1244 {
1245 $parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;
Barry Mienydd671972010-10-04 16:33:58 +02001246 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001247 }
Barry Mienydd671972010-10-04 16:33:58 +02001248
Derek Allard2067d1a2008-11-13 22:59:24 +00001249 return $parameters;
1250 }
Barry Mienydd671972010-10-04 16:33:58 +02001251
Andrey Andreevc8709832012-04-04 13:43:53 +03001252 // --------------------------------------------------------------------
1253
1254 /**
1255 * Decode message
1256 *
1257 * @param object
1258 * @return mixed
1259 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001260 public function decode_message($param)
Derek Allard2067d1a2008-11-13 22:59:24 +00001261 {
1262 $kind = $param->kindOf();
1263
Alex Bilbied261b1e2012-06-02 11:12:16 +01001264 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +00001265 {
1266 return $param->scalarval();
1267 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001268 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +00001269 {
1270 reset($param->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001271 $b = current($param->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001272 $arr = array();
1273
Andrey Andreevc8709832012-04-04 13:43:53 +03001274 for ($i = 0, $c = count($b); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001275 {
1276 $arr[] = $this->decode_message($param->me['array'][$i]);
1277 }
Barry Mienydd671972010-10-04 16:33:58 +02001278
Derek Allard2067d1a2008-11-13 22:59:24 +00001279 return $arr;
1280 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001281 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +00001282 {
1283 reset($param->me['struct']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001284 $arr = array();
1285
Pascal Kriete14287f32011-02-14 13:39:34 -05001286 while (list($key,$value) = each($param->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001287 {
1288 $arr[$key] = $this->decode_message($value);
1289 }
Barry Mienydd671972010-10-04 16:33:58 +02001290
Derek Allard2067d1a2008-11-13 22:59:24 +00001291 return $arr;
1292 }
1293 }
Barry Mienydd671972010-10-04 16:33:58 +02001294
Andrey Andreevc8709832012-04-04 13:43:53 +03001295} // END XML_RPC_Message Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001296
1297/**
1298 * XML-RPC Values class
1299 *
1300 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -05001301 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +00001302 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
1303 */
1304class XML_RPC_Values extends CI_Xmlrpc
1305{
Andrey Andreeva30faf92011-12-25 18:15:34 +02001306 public $me = array();
1307 public $mytype = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001308
Andrey Andreevc8709832012-04-04 13:43:53 +03001309 /**
1310 * Constructor
1311 *
1312 * @param mixed
1313 * @param string
1314 * @return void
1315 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001316 public function __construct($val = -1, $type = '')
Barry Mienydd671972010-10-04 16:33:58 +02001317 {
Greg Akera9263282010-11-10 15:26:43 -06001318 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +02001319
Alex Bilbied261b1e2012-06-02 11:12:16 +01001320 if ($val !== -1 OR $type !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001321 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001322 $type = $type === '' ? 'string' : $type;
Barry Mienydd671972010-10-04 16:33:58 +02001323
Dimitar740480a2012-10-05 13:24:59 +03001324 if ($this->xmlrpcTypes[$type] == 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001325 {
1326 $this->addScalar($val,$type);
1327 }
Dimitar740480a2012-10-05 13:24:59 +03001328 elseif ($this->xmlrpcTypes[$type] == 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001329 {
1330 $this->addArray($val);
1331 }
Dimitar740480a2012-10-05 13:24:59 +03001332 elseif ($this->xmlrpcTypes[$type] == 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001333 {
1334 $this->addStruct($val);
1335 }
1336 }
1337 }
1338
Andrey Andreevc8709832012-04-04 13:43:53 +03001339 // --------------------------------------------------------------------
1340
1341 /**
1342 * Add scalar value
1343 *
1344 * @param scalar
1345 * @param string
1346 * @return int
1347 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001348 public function addScalar($val, $type = 'string')
Derek Allard2067d1a2008-11-13 22:59:24 +00001349 {
1350 $typeof = $this->xmlrpcTypes[$type];
Barry Mienydd671972010-10-04 16:33:58 +02001351
Alex Bilbied261b1e2012-06-02 11:12:16 +01001352 if ($this->mytype === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001353 {
1354 echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
1355 return 0;
1356 }
Barry Mienydd671972010-10-04 16:33:58 +02001357
Dimitar740480a2012-10-05 13:24:59 +03001358 if ($typeof != 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001359 {
1360 echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';
1361 return 0;
1362 }
1363
Alex Bilbied261b1e2012-06-02 11:12:16 +01001364 if ($type === $this->xmlrpcBoolean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001365 {
Andrey Andreev3f3f1352012-09-05 16:39:28 +03001366 $val = (int) (strcasecmp($val, 'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
Derek Allard2067d1a2008-11-13 22:59:24 +00001367 }
1368
Alex Bilbied261b1e2012-06-02 11:12:16 +01001369 if ($this->mytype === 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001370 {
1371 // adding to an array here
1372 $ar = $this->me['array'];
1373 $ar[] = new XML_RPC_Values($val, $type);
1374 $this->me['array'] = $ar;
1375 }
1376 else
1377 {
1378 // a scalar, so set the value and remember we're scalar
1379 $this->me[$type] = $val;
1380 $this->mytype = $typeof;
1381 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001382
Derek Allard2067d1a2008-11-13 22:59:24 +00001383 return 1;
1384 }
1385
Andrey Andreevc8709832012-04-04 13:43:53 +03001386 // --------------------------------------------------------------------
1387
1388 /**
1389 * Add array value
1390 *
1391 * @param array
1392 * @return int
1393 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001394 public function addArray($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001395 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001396 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001397 {
1398 echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
1399 return 0;
1400 }
1401
1402 $this->mytype = $this->xmlrpcTypes['array'];
1403 $this->me['array'] = $vals;
1404 return 1;
1405 }
1406
Andrey Andreevc8709832012-04-04 13:43:53 +03001407 // --------------------------------------------------------------------
1408
1409 /**
1410 * Add struct value
1411 *
1412 * @param object
1413 * @return int
1414 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001415 public function addStruct($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001416 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001417 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001418 {
1419 echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
1420 return 0;
1421 }
1422 $this->mytype = $this->xmlrpcTypes['struct'];
1423 $this->me['struct'] = $vals;
1424 return 1;
1425 }
1426
Andrey Andreevc8709832012-04-04 13:43:53 +03001427 // --------------------------------------------------------------------
1428
1429 /**
1430 * Get value type
1431 *
1432 * @return string
1433 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001434 public function kindOf()
Derek Allard2067d1a2008-11-13 22:59:24 +00001435 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001436 switch ($this->mytype)
Derek Allard2067d1a2008-11-13 22:59:24 +00001437 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001438 case 3: return 'struct';
1439 case 2: return 'array';
1440 case 1: return 'scalar';
1441 default: return 'undef';
Derek Allard2067d1a2008-11-13 22:59:24 +00001442 }
1443 }
1444
Andrey Andreevc8709832012-04-04 13:43:53 +03001445 // --------------------------------------------------------------------
1446
1447 /**
1448 * Serialize data
1449 *
1450 * @param string
1451 * @param mixed
1452 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001453 public function serializedata($typ, $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001454 {
1455 $rs = '';
Derek Jonesa9647e82010-03-02 22:59:07 -06001456
Andrey Andreevc8709832012-04-04 13:43:53 +03001457 switch ($this->xmlrpcTypes[$typ])
Derek Allard2067d1a2008-11-13 22:59:24 +00001458 {
1459 case 3:
1460 // struct
1461 $rs .= "<struct>\n";
1462 reset($val);
Pascal Kriete14287f32011-02-14 13:39:34 -05001463 while (list($key2, $val2) = each($val))
Derek Allard2067d1a2008-11-13 22:59:24 +00001464 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001465 $rs .= "<member>\n<name>{$key2}</name>\n".$this->serializeval($val2)."</member>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001466 }
1467 $rs .= '</struct>';
Andrey Andreevc8709832012-04-04 13:43:53 +03001468 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001469 case 2:
1470 // array
1471 $rs .= "<array>\n<data>\n";
Andrey Andreevc8709832012-04-04 13:43:53 +03001472 for ($i = 0, $c = count($val); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001473 {
1474 $rs .= $this->serializeval($val[$i]);
1475 }
Andrey Andreeva30faf92011-12-25 18:15:34 +02001476 $rs .= "</data>\n</array>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001477 break;
1478 case 1:
1479 // others
1480 switch ($typ)
1481 {
1482 case $this->xmlrpcBase64:
Andrey Andreevc8709832012-04-04 13:43:53 +03001483 $rs .= '<'.$typ.'>'.base64_encode( (string) $val).'</'.$typ.">\n";
1484 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001485 case $this->xmlrpcBoolean:
Andrey Andreevc8709832012-04-04 13:43:53 +03001486 $rs .= '<'.$typ.'>'.( (bool) $val ? '1' : '0').'</'.$typ.">\n";
1487 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001488 case $this->xmlrpcString:
Andrey Andreevc8709832012-04-04 13:43:53 +03001489 $rs .= '<'.$typ.'>'.htmlspecialchars( (string) $val).'</'.$typ.">\n";
1490 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001491 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001492 $rs .= '<'.$typ.'>'.$val.'</'.$typ.">\n";
1493 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001494 }
1495 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001496 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001497 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001498
Derek Allard2067d1a2008-11-13 22:59:24 +00001499 return $rs;
1500 }
1501
Andrey Andreevc8709832012-04-04 13:43:53 +03001502 // --------------------------------------------------------------------
1503
1504 /**
1505 * Serialize class
1506 *
1507 * @return string
1508 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001509 public function serialize_class()
Derek Allard2067d1a2008-11-13 22:59:24 +00001510 {
1511 return $this->serializeval($this);
1512 }
1513
Andrey Andreevc8709832012-04-04 13:43:53 +03001514 // --------------------------------------------------------------------
1515
1516 /**
1517 * Serialize value
1518 *
1519 * @param object
1520 * @return string
1521 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001522 public function serializeval($o)
Derek Allard2067d1a2008-11-13 22:59:24 +00001523 {
1524 $ar = $o->me;
1525 reset($ar);
Barry Mienydd671972010-10-04 16:33:58 +02001526
Derek Allard2067d1a2008-11-13 22:59:24 +00001527 list($typ, $val) = each($ar);
Andrey Andreeva30faf92011-12-25 18:15:34 +02001528 return "<value>\n".$this->serializedata($typ, $val)."</value>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001529 }
Barry Mienydd671972010-10-04 16:33:58 +02001530
Andrey Andreevc8709832012-04-04 13:43:53 +03001531 // --------------------------------------------------------------------
1532
1533 /**
1534 * Scalar value
1535 *
1536 * @return mixed
1537 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001538 public function scalarval()
Derek Allard2067d1a2008-11-13 22:59:24 +00001539 {
1540 reset($this->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001541 return current($this->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001542 }
1543
Andrey Andreevc8709832012-04-04 13:43:53 +03001544 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001545
Andrey Andreevc8709832012-04-04 13:43:53 +03001546 /**
1547 * Encode time in ISO-8601 form.
1548 * Useful for sending time in XML-RPC
1549 *
1550 * @param int unix timestamp
1551 * @param bool
1552 * @return string
1553 */
1554 public function iso8601_encode($time, $utc = FALSE)
Barry Mienydd671972010-10-04 16:33:58 +02001555 {
Andrey Andreev62090152011-12-30 12:49:27 +02001556 return ($utc) ? strftime('%Y%m%dT%H:%i:%s', $time) : gmstrftime('%Y%m%dT%H:%i:%s', $time);
Derek Allard2067d1a2008-11-13 22:59:24 +00001557 }
Barry Mienydd671972010-10-04 16:33:58 +02001558
Andrey Andreevc8709832012-04-04 13:43:53 +03001559} // END XML_RPC_Values Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001560
1561/* End of file Xmlrpc.php */
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001562/* Location: ./system/libraries/Xmlrpc.php */