blob: 2fd12599e32ff1d26cd662360c96a0750720247e [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
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
Andrey Andreev80500af2013-01-01 08:16:53 +020021 * @copyright Copyright (c) 2008 - 2013, 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 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020027defined('BASEPATH') OR exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +000028
Andrey Andreevf5ccd122012-11-02 00:17:39 +020029if ( ! function_exists('xml_parser_create'))
30{
31 show_error('Your PHP installation does not support XML');
32}
33
34// ------------------------------------------------------------------------
35
Derek Allard2067d1a2008-11-13 22:59:24 +000036/**
37 * XML-RPC request handler class
38 *
39 * @package CodeIgniter
40 * @subpackage Libraries
41 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -050042 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000043 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
44 */
45class CI_Xmlrpc {
46
Andrey Andreevf5ccd122012-11-02 00:17:39 +020047 /**
48 * Debug flag
49 *
50 * @var bool
51 */
52 public $debug = FALSE;
53
54 /**
55 * I4 data type
56 *
57 * @var string
58 */
Andrey Andreeva30faf92011-12-25 18:15:34 +020059 public $xmlrpcI4 = 'i4';
Andrey Andreevf5ccd122012-11-02 00:17:39 +020060
61 /**
62 * Integer data type
63 *
64 * @var string
65 */
Andrey Andreeva30faf92011-12-25 18:15:34 +020066 public $xmlrpcInt = 'int';
Andrey Andreevf5ccd122012-11-02 00:17:39 +020067
68 /**
69 * Boolean data type
70 *
71 * @var string
72 */
Andrey Andreeva30faf92011-12-25 18:15:34 +020073 public $xmlrpcBoolean = 'boolean';
Andrey Andreevf5ccd122012-11-02 00:17:39 +020074
75 /**
76 * Double data type
77 *
78 * @var string
79 */
Andrey Andreeva30faf92011-12-25 18:15:34 +020080 public $xmlrpcDouble = 'double';
Andrey Andreevf5ccd122012-11-02 00:17:39 +020081
82 /**
83 * String data type
84 *
85 * @var string
86 */
Andrey Andreeva30faf92011-12-25 18:15:34 +020087 public $xmlrpcString = 'string';
Andrey Andreevf5ccd122012-11-02 00:17:39 +020088
89 /**
90 * DateTime format
91 *
92 * @var string
93 */
Andrey Andreeva30faf92011-12-25 18:15:34 +020094 public $xmlrpcDateTime = 'dateTime.iso8601';
Andrey Andreevf5ccd122012-11-02 00:17:39 +020095
96 /**
97 * Base64 data type
98 *
99 * @var string
100 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200101 public $xmlrpcBase64 = 'base64';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200102
103 /**
104 * Array data type
105 *
106 * @var string
107 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200108 public $xmlrpcArray = 'array';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200109
110 /**
111 * Struct data type
112 *
113 * @var string
114 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200115 public $xmlrpcStruct = 'struct';
Barry Mienydd671972010-10-04 16:33:58 +0200116
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200117 /**
118 * Data types list
119 *
120 * @var array
121 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200122 public $xmlrpcTypes = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200123
124 /**
125 * Valid parents list
126 *
127 * @var array
128 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200129 public $valid_parents = array();
Barry Mienydd671972010-10-04 16:33:58 +0200130
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200131 /**
132 * Response error numbers list
133 *
134 * @var array
135 */
136 public $xmlrpcerr = array();
137
138 /**
139 * Response error messages list
140 *
141 * @var string[]
142 */
143 public $xmlrpcstr = array();
144
145 /**
146 * Encoding charset
147 *
148 * @var string
149 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200150 public $xmlrpc_defencoding = 'UTF-8';
Barry Mienydd671972010-10-04 16:33:58 +0200151
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200152 /**
153 * XML-RPC client name
154 *
155 * @var string
156 */
157 public $xmlrpcName = 'XML-RPC for CodeIgniter';
158
159 /**
160 * XML-RPC version
161 *
162 * @var string
163 */
164 public $xmlrpcVersion = '1.1';
165
166 /**
167 * Start of user errors
168 *
169 * @var int
170 */
171 public $xmlrpcerruser = 800;
172
173 /**
174 * Start of XML parse errors
175 *
176 * @var int
177 */
178 public $xmlrpcerrxml = 100;
179
180 /**
181 * Backslash replacement value
182 *
183 * @var string
184 */
185 public $xmlrpc_backslash = '';
186
187 /**
188 * XML-RPC Client object
189 *
190 * @var object
191 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200192 public $client;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200193
194 /**
195 * XML-RPC Method name
196 *
197 * @var string
198 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200199 public $method;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200200
201 /**
202 * XML-RPC Data
203 *
204 * @var array
205 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200206 public $data;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200207
208 /**
209 * XML-RPC Message
210 *
211 * @var string
212 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200213 public $message = '';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200214
215 /**
216 * Request error message
217 *
218 * @var string
219 */
220 public $error = '';
221
222 /**
223 * XML-RPC result object
224 *
225 * @var object
226 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200227 public $result;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200228
229 /**
230 * XML-RPC Reponse
231 *
232 * @var array
233 */
vkeranovb497d2b2012-11-23 23:27:33 +0200234 public $response = array(); // Response from remote server
Derek Allard2067d1a2008-11-13 22:59:24 +0000235
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200236 /**
237 * XSS Filter flag
238 *
239 * @var bool
240 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200241 public $xss_clean = TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000242
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200243 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000244
Andrey Andreevc8709832012-04-04 13:43:53 +0300245 /**
246 * Constructor
247 *
248 * Initializes property default values
249 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200250 * @param array $config
Andrey Andreevc8709832012-04-04 13:43:53 +0300251 * @return void
252 */
Greg Akera9263282010-11-10 15:26:43 -0600253 public function __construct($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000254 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000255 $this->xmlrpc_backslash = chr(92).chr(92);
Barry Mienydd671972010-10-04 16:33:58 +0200256
Derek Allard2067d1a2008-11-13 22:59:24 +0000257 // Types for info sent back and forth
258 $this->xmlrpcTypes = array(
Barry Mienydd671972010-10-04 16:33:58 +0200259 $this->xmlrpcI4 => '1',
260 $this->xmlrpcInt => '1',
261 $this->xmlrpcBoolean => '1',
262 $this->xmlrpcString => '1',
263 $this->xmlrpcDouble => '1',
264 $this->xmlrpcDateTime => '1',
265 $this->xmlrpcBase64 => '1',
266 $this->xmlrpcArray => '2',
267 $this->xmlrpcStruct => '3'
vkeranovb497d2b2012-11-23 23:27:33 +0200268 );
Barry Mienydd671972010-10-04 16:33:58 +0200269
Derek Allard2067d1a2008-11-13 22:59:24 +0000270 // Array of Valid Parents for Various XML-RPC elements
Timothy Warren0688ac92012-04-20 10:25:04 -0400271 $this->valid_parents = array('BOOLEAN' => array('VALUE'),
272 'I4' => array('VALUE'),
273 'INT' => array('VALUE'),
274 'STRING' => array('VALUE'),
275 'DOUBLE' => array('VALUE'),
276 'DATETIME.ISO8601' => array('VALUE'),
277 'BASE64' => array('VALUE'),
278 'ARRAY' => array('VALUE'),
279 'STRUCT' => array('VALUE'),
280 'PARAM' => array('PARAMS'),
281 'METHODNAME' => array('METHODCALL'),
282 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'),
283 'MEMBER' => array('STRUCT'),
284 'NAME' => array('MEMBER'),
285 'DATA' => array('ARRAY'),
286 'FAULT' => array('METHODRESPONSE'),
287 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT')
vkeranovb497d2b2012-11-23 23:27:33 +0200288 );
Barry Mienydd671972010-10-04 16:33:58 +0200289
Derek Allard2067d1a2008-11-13 22:59:24 +0000290 // XML-RPC Responses
291 $this->xmlrpcerr['unknown_method'] = '1';
292 $this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server';
293 $this->xmlrpcerr['invalid_return'] = '2';
vkeranovb497d2b2012-11-23 23:27:33 +0200294 $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 +0000295 $this->xmlrpcerr['incorrect_params'] = '3';
296 $this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method';
297 $this->xmlrpcerr['introspect_unknown'] = '4';
Andrey Andreeva30faf92011-12-25 18:15:34 +0200298 $this->xmlrpcstr['introspect_unknown'] = 'Cannot inspect signature for request: method unknown';
Derek Allard2067d1a2008-11-13 22:59:24 +0000299 $this->xmlrpcerr['http_error'] = '5';
300 $this->xmlrpcstr['http_error'] = "Did not receive a '200 OK' response from remote server.";
301 $this->xmlrpcerr['no_data'] = '6';
vkeranovb497d2b2012-11-23 23:27:33 +0200302 $this->xmlrpcstr['no_data'] = 'No data received from server.';
Barry Mienydd671972010-10-04 16:33:58 +0200303
Derek Allard2067d1a2008-11-13 22:59:24 +0000304 $this->initialize($config);
Barry Mienydd671972010-10-04 16:33:58 +0200305
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300306 log_message('debug', 'XML-RPC Class Initialized');
Derek Allard2067d1a2008-11-13 22:59:24 +0000307 }
Barry Mienydd671972010-10-04 16:33:58 +0200308
Andrey Andreevc8709832012-04-04 13:43:53 +0300309 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000310
Andrey Andreevc8709832012-04-04 13:43:53 +0300311 /**
312 * Initialize
313 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200314 * @param array $config
Andrey Andreevc8709832012-04-04 13:43:53 +0300315 * @return void
316 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200317 public function initialize($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000318 {
Derek Jones33559102009-02-02 18:50:38 +0000319 if (count($config) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000320 {
321 foreach ($config as $key => $val)
322 {
323 if (isset($this->$key))
324 {
Barry Mienydd671972010-10-04 16:33:58 +0200325 $this->$key = $val;
Derek Allard2067d1a2008-11-13 22:59:24 +0000326 }
327 }
328 }
329 }
Barry Mienydd671972010-10-04 16:33:58 +0200330
Andrey Andreevc8709832012-04-04 13:43:53 +0300331 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000332
Andrey Andreevc8709832012-04-04 13:43:53 +0300333 /**
334 * Parse server URL
335 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300336 * @param string $url
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200337 * @param int $port
338 * @param string $proxy
339 * @param int $proxy_port
Andrey Andreevc8709832012-04-04 13:43:53 +0300340 * @return void
341 */
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300342 public function server($url, $port = 80, $proxy = FALSE, $proxy_port = 8080)
Derek Allard2067d1a2008-11-13 22:59:24 +0000343 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200344 if (strpos($url, 'http') !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000345 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300346 $url = 'http://'.$url;
Derek Allard2067d1a2008-11-13 22:59:24 +0000347 }
Barry Mienydd671972010-10-04 16:33:58 +0200348
Derek Allard2067d1a2008-11-13 22:59:24 +0000349 $parts = parse_url($url);
Barry Mienydd671972010-10-04 16:33:58 +0200350
Andrey Andreevdc53d7b2014-01-07 12:12:11 +0200351 if (isset($parts['user'], $parts['pass']))
352 {
353 $parts['host'] = $parts['user'].':'.$parts['pass'].'@'.$parts['host'];
354 }
355
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300356 $path = isset($parts['path']) ? $parts['path'] : '/';
Barry Mienydd671972010-10-04 16:33:58 +0200357
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300358 if ( ! empty($parts['query']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000359 {
360 $path .= '?'.$parts['query'];
Barry Mienydd671972010-10-04 16:33:58 +0200361 }
362
Valio9dee5352012-07-02 10:42:28 +0300363 $this->client = new XML_RPC_Client($path, $parts['host'], $port, $proxy, $proxy_port);
Derek Allard2067d1a2008-11-13 22:59:24 +0000364 }
Barry Mienydd671972010-10-04 16:33:58 +0200365
Andrey Andreevc8709832012-04-04 13:43:53 +0300366 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000367
Andrey Andreevc8709832012-04-04 13:43:53 +0300368 /**
369 * Set Timeout
370 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200371 * @param int $seconds
Andrey Andreevc8709832012-04-04 13:43:53 +0300372 * @return void
373 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200374 public function timeout($seconds = 5)
Derek Allard2067d1a2008-11-13 22:59:24 +0000375 {
vlakoff1228fe22013-01-14 01:30:09 +0100376 if ($this->client !== NULL && is_int($seconds))
Derek Allard2067d1a2008-11-13 22:59:24 +0000377 {
378 $this->client->timeout = $seconds;
379 }
380 }
Barry Mienydd671972010-10-04 16:33:58 +0200381
Andrey Andreevc8709832012-04-04 13:43:53 +0300382 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000383
Andrey Andreevc8709832012-04-04 13:43:53 +0300384 /**
385 * Set Methods
386 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200387 * @param string $function Method name
Andrey Andreevc8709832012-04-04 13:43:53 +0300388 * @return void
389 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200390 public function method($function)
Derek Allard2067d1a2008-11-13 22:59:24 +0000391 {
392 $this->method = $function;
393 }
Barry Mienydd671972010-10-04 16:33:58 +0200394
Andrey Andreevc8709832012-04-04 13:43:53 +0300395 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000396
Andrey Andreevc8709832012-04-04 13:43:53 +0300397 /**
398 * Take Array of Data and Create Objects
399 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200400 * @param array $incoming
Andrey Andreevc8709832012-04-04 13:43:53 +0300401 * @return void
402 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200403 public function request($incoming)
Derek Allard2067d1a2008-11-13 22:59:24 +0000404 {
405 if ( ! is_array($incoming))
406 {
407 // Send Error
Andrey Andreevc8709832012-04-04 13:43:53 +0300408 return;
Derek Allard2067d1a2008-11-13 22:59:24 +0000409 }
Barry Mienydd671972010-10-04 16:33:58 +0200410
Derek Allard2067d1a2008-11-13 22:59:24 +0000411 $this->data = array();
Barry Mienydd671972010-10-04 16:33:58 +0200412
Pascal Kriete14287f32011-02-14 13:39:34 -0500413 foreach ($incoming as $key => $value)
Derek Allard2067d1a2008-11-13 22:59:24 +0000414 {
415 $this->data[$key] = $this->values_parsing($value);
416 }
417 }
Barry Mienydd671972010-10-04 16:33:58 +0200418
Andrey Andreevc8709832012-04-04 13:43:53 +0300419 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200420
Andrey Andreevc8709832012-04-04 13:43:53 +0300421 /**
422 * Set Debug
423 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200424 * @param bool $flag
Andrey Andreevc8709832012-04-04 13:43:53 +0300425 * @return void
426 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200427 public function set_debug($flag = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000428 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100429 $this->debug = ($flag === TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000430 }
Barry Mienydd671972010-10-04 16:33:58 +0200431
Andrey Andreevc8709832012-04-04 13:43:53 +0300432 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000433
Andrey Andreevc8709832012-04-04 13:43:53 +0300434 /**
435 * Values Parsing
436 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200437 * @param mixed $value
Andrey Andreevc8709832012-04-04 13:43:53 +0300438 * @return object
439 */
440 public function values_parsing($value)
Derek Allard2067d1a2008-11-13 22:59:24 +0000441 {
Derek Jones8c4b5e72010-01-06 22:21:41 +0000442 if (is_array($value) && array_key_exists(0, $value))
Derek Allard2067d1a2008-11-13 22:59:24 +0000443 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300444 if ( ! isset($value[1], $this->xmlrpcTypes[$value[1]]))
Derek Allard2067d1a2008-11-13 22:59:24 +0000445 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200446 $temp = new XML_RPC_Values($value[0], (is_array($value[0]) ? 'array' : 'string'));
Derek Allard2067d1a2008-11-13 22:59:24 +0000447 }
448 else
449 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100450 if (is_array($value[0]) && ($value[1] === 'struct' OR $value[1] === 'array'))
Andrey Andreeva30faf92011-12-25 18:15:34 +0200451 {
452 while (list($k) = each($value[0]))
453 {
Rasmus Lerdorf99860702013-05-18 10:27:12 -0400454 $value[0][$k] = $this->values_parsing($value[0][$k]);
Andrey Andreeva30faf92011-12-25 18:15:34 +0200455 }
456 }
457
458 $temp = new XML_RPC_Values($value[0], $value[1]);
Derek Allard2067d1a2008-11-13 22:59:24 +0000459 }
460 }
461 else
462 {
463 $temp = new XML_RPC_Values($value, 'string');
464 }
465
466 return $temp;
467 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000468
Andrey Andreevc8709832012-04-04 13:43:53 +0300469 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000470
Andrey Andreevc8709832012-04-04 13:43:53 +0300471 /**
472 * Sends XML-RPC Request
473 *
474 * @return bool
475 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200476 public function send_request()
Derek Allard2067d1a2008-11-13 22:59:24 +0000477 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300478 $this->message = new XML_RPC_Message($this->method, $this->data);
Derek Allard2067d1a2008-11-13 22:59:24 +0000479 $this->message->debug = $this->debug;
Barry Mienydd671972010-10-04 16:33:58 +0200480
Andrey Andreeva30faf92011-12-25 18:15:34 +0200481 if ( ! $this->result = $this->client->send($this->message) OR ! is_object($this->result->val))
Derek Allard2067d1a2008-11-13 22:59:24 +0000482 {
483 $this->error = $this->result->errstr;
484 return FALSE;
485 }
Barry Mienydd671972010-10-04 16:33:58 +0200486
Derek Allard2067d1a2008-11-13 22:59:24 +0000487 $this->response = $this->result->decode();
Derek Allard2067d1a2008-11-13 22:59:24 +0000488 return TRUE;
489 }
Barry Mienydd671972010-10-04 16:33:58 +0200490
Andrey Andreevc8709832012-04-04 13:43:53 +0300491 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000492
Andrey Andreevc8709832012-04-04 13:43:53 +0300493 /**
494 * Returns Error
495 *
496 * @return string
497 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200498 public function display_error()
Derek Allard2067d1a2008-11-13 22:59:24 +0000499 {
500 return $this->error;
501 }
Barry Mienydd671972010-10-04 16:33:58 +0200502
Andrey Andreevc8709832012-04-04 13:43:53 +0300503 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000504
Andrey Andreevc8709832012-04-04 13:43:53 +0300505 /**
506 * Returns Remote Server Response
507 *
508 * @return string
509 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200510 public function display_response()
Derek Allard2067d1a2008-11-13 22:59:24 +0000511 {
512 return $this->response;
513 }
Barry Mienydd671972010-10-04 16:33:58 +0200514
Andrey Andreevc8709832012-04-04 13:43:53 +0300515 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200516
Andrey Andreevc8709832012-04-04 13:43:53 +0300517 /**
518 * Sends an Error Message for Server Request
519 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200520 * @param int $number
521 * @param string $message
Andrey Andreevc8709832012-04-04 13:43:53 +0300522 * @return object
523 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200524 public function send_error_message($number, $message)
Derek Allard2067d1a2008-11-13 22:59:24 +0000525 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200526 return new XML_RPC_Response(0, $number, $message);
Derek Allard2067d1a2008-11-13 22:59:24 +0000527 }
Barry Mienydd671972010-10-04 16:33:58 +0200528
Andrey Andreevc8709832012-04-04 13:43:53 +0300529 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200530
Andrey Andreevc8709832012-04-04 13:43:53 +0300531 /**
532 * Send Response for Server Request
533 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200534 * @param array $response
Andrey Andreevc8709832012-04-04 13:43:53 +0300535 * @return object
536 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200537 public function send_response($response)
Derek Allard2067d1a2008-11-13 22:59:24 +0000538 {
539 // $response should be array of values, which will be parsed
540 // based on their data and type into a valid group of XML-RPC values
Andrey Andreeva30faf92011-12-25 18:15:34 +0200541 return new XML_RPC_Response($this->values_parsing($response));
Derek Allard2067d1a2008-11-13 22:59:24 +0000542 }
Barry Mienydd671972010-10-04 16:33:58 +0200543
Derek Allard2067d1a2008-11-13 22:59:24 +0000544} // END XML_RPC Class
545
Derek Allard2067d1a2008-11-13 22:59:24 +0000546/**
547 * XML-RPC Client class
548 *
549 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500550 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000551 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
552 */
553class XML_RPC_Client extends CI_Xmlrpc
554{
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200555 /**
556 * Path
557 *
558 * @var string
559 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200560 public $path = '';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200561
562 /**
563 * Server hostname
564 *
565 * @var string
566 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200567 public $server = '';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200568
569 /**
570 * Server port
571 *
572 * @var int
573 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200574 public $port = 80;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200575
576 /**
Andrey Andreevdc53d7b2014-01-07 12:12:11 +0200577 *
578 * Server username
579 *
580 * @var string
581 */
582 public $username;
583
584 /**
585 * Server password
586 *
587 * @var string
588 */
589 public $password;
590
591 /**
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200592 * Proxy hostname
593 *
594 * @var string
595 */
Valio9dee5352012-07-02 10:42:28 +0300596 public $proxy = FALSE;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200597
598 /**
599 * Proxy port
600 *
601 * @var int
602 */
Valio9dee5352012-07-02 10:42:28 +0300603 public $proxy_port = 8080;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200604
605 /**
606 * Error number
607 *
608 * @var string
609 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200610 public $errno = '';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200611
612 /**
613 * Error message
614 *
615 * @var string
616 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200617 public $errstring = '';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200618
619 /**
620 * Timeout in seconds
621 *
622 * @var int
623 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200624 public $timeout = 5;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200625
626 /**
627 * No Multicall flag
628 *
629 * @var bool
630 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200631 public $no_multicall = FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000632
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200633 // --------------------------------------------------------------------
634
Andrey Andreevc8709832012-04-04 13:43:53 +0300635 /**
636 * Constructor
637 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300638 * @param string $path
639 * @param object $server
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200640 * @param int $port
641 * @param string $proxy
642 * @param int $proxy_port
Andrey Andreevc8709832012-04-04 13:43:53 +0300643 * @return void
644 */
Valio9dee5352012-07-02 10:42:28 +0300645 public function __construct($path, $server, $port = 80, $proxy = FALSE, $proxy_port = 8080)
Derek Allard2067d1a2008-11-13 22:59:24 +0000646 {
Greg Akera9263282010-11-10 15:26:43 -0600647 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +0200648
Andrey Andreevdc53d7b2014-01-07 12:12:11 +0200649 $url = parse_url('http://'.$server);
650
651 if (isset($url['user'], $url['pass']))
652 {
653 $this->username = $url['user'];
654 $this->password = $url['pass'];
655 }
656
Derek Allard2067d1a2008-11-13 22:59:24 +0000657 $this->port = $port;
Andrey Andreevdc53d7b2014-01-07 12:12:11 +0200658 $this->server = $url['host'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000659 $this->path = $path;
Valio9dee5352012-07-02 10:42:28 +0300660 $this->proxy = $proxy;
661 $this->proxy_port = $proxy_port;
Derek Allard2067d1a2008-11-13 22:59:24 +0000662 }
Barry Mienydd671972010-10-04 16:33:58 +0200663
Andrey Andreevc8709832012-04-04 13:43:53 +0300664 // --------------------------------------------------------------------
665
666 /**
667 * Send message
668 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200669 * @param mixed $msg
Andrey Andreevc8709832012-04-04 13:43:53 +0300670 * @return object
671 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200672 public function send($msg)
Derek Allard2067d1a2008-11-13 22:59:24 +0000673 {
674 if (is_array($msg))
675 {
676 // Multi-call disabled
Andrey Andreevc8709832012-04-04 13:43:53 +0300677 return new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'], $this->xmlrpcstr['multicall_recursion']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000678 }
679
680 return $this->sendPayload($msg);
681 }
682
Andrey Andreevc8709832012-04-04 13:43:53 +0300683 // --------------------------------------------------------------------
684
685 /**
686 * Send payload
687 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200688 * @param object $msg
Andrey Andreevc8709832012-04-04 13:43:53 +0300689 * @return object
690 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200691 public function sendPayload($msg)
Barry Mienydd671972010-10-04 16:33:58 +0200692 {
Andrey Andreevc02e7c52012-07-02 16:43:43 +0300693 if ($this->proxy === FALSE)
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300694 {
695 $server = $this->server;
696 $port = $this->port;
Valentin Sheyretski09217ce2012-07-02 16:27:01 +0300697 }
698 else
699 {
Valio9dee5352012-07-02 10:42:28 +0300700 $server = $this->proxy;
701 $port = $this->proxy_port;
702 }
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300703
Valio9dee5352012-07-02 10:42:28 +0300704 $fp = @fsockopen($server, $port, $this->errno, $this->errstring, $this->timeout);
Barry Mienydd671972010-10-04 16:33:58 +0200705
Derek Allard2067d1a2008-11-13 22:59:24 +0000706 if ( ! is_resource($fp))
707 {
708 error_log($this->xmlrpcstr['http_error']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300709 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000710 }
Barry Mienydd671972010-10-04 16:33:58 +0200711
Pascal Kriete14287f32011-02-14 13:39:34 -0500712 if (empty($msg->payload))
Derek Allard2067d1a2008-11-13 22:59:24 +0000713 {
714 // $msg = XML_RPC_Messages
715 $msg->createPayload();
716 }
Barry Mienydd671972010-10-04 16:33:58 +0200717
Derek Allard2067d1a2008-11-13 22:59:24 +0000718 $r = "\r\n";
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300719 $op = 'POST '.$this->path.' HTTP/1.0'.$r
720 .'Host: '.$this->server.$r
721 .'Content-Type: text/xml'.$r
Andrey Andreevdc53d7b2014-01-07 12:12:11 +0200722 .(isset($this->username, $this->password) ? 'Authorization: Basic '.base64_encode($this->username.':'.$this->password).$r : '')
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300723 .'User-Agent: '.$this->xmlrpcName.$r
724 .'Content-Length: '.strlen($msg->payload).$r.$r
725 .$msg->payload;
Barry Mienydd671972010-10-04 16:33:58 +0200726
George Petsagourakis306b3782012-05-02 20:31:08 +0300727 if ( ! fwrite($fp, $op, strlen($op)))
Derek Allard2067d1a2008-11-13 22:59:24 +0000728 {
729 error_log($this->xmlrpcstr['http_error']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300730 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000731 }
Andrey Andreevc8709832012-04-04 13:43:53 +0300732
Derek Allard2067d1a2008-11-13 22:59:24 +0000733 $resp = $msg->parseResponse($fp);
734 fclose($fp);
735 return $resp;
736 }
737
Andrey Andreevc8709832012-04-04 13:43:53 +0300738} // END XML_RPC_Client Class
Derek Allard2067d1a2008-11-13 22:59:24 +0000739
740/**
741 * XML-RPC Response class
742 *
743 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500744 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000745 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
746 */
747class XML_RPC_Response
748{
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200749
750 /**
751 * Value
752 *
753 * @var mixed
754 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300755 public $val = 0;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200756
757 /**
758 * Error number
759 *
760 * @var int
761 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300762 public $errno = 0;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200763
764 /**
765 * Error message
766 *
767 * @var string
768 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300769 public $errstr = '';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200770
771 /**
772 * Headers list
773 *
774 * @var array
775 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300776 public $headers = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200777
778 /**
779 * XSS Filter flag
780 *
781 * @var bool
782 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300783 public $xss_clean = TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000784
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200785 // --------------------------------------------------------------------
786
Andrey Andreevc8709832012-04-04 13:43:53 +0300787 /**
788 * Constructor
789 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200790 * @param mixed $val
791 * @param int $code
792 * @param string $fstr
Andrey Andreevc8709832012-04-04 13:43:53 +0300793 * @return void
794 */
Greg Akera9263282010-11-10 15:26:43 -0600795 public function __construct($val, $code = 0, $fstr = '')
Barry Mienydd671972010-10-04 16:33:58 +0200796 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100797 if ($code !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000798 {
799 // error
800 $this->errno = $code;
Andrey Andreevc8709832012-04-04 13:43:53 +0300801 $this->errstr = htmlspecialchars($fstr,
802 (is_php('5.4') ? ENT_XML1 | ENT_NOQUOTES : ENT_NOQUOTES),
803 'UTF-8');
Derek Allard2067d1a2008-11-13 22:59:24 +0000804 }
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300805 elseif ( ! is_object($val))
Derek Allard2067d1a2008-11-13 22:59:24 +0000806 {
807 // programmer error, not an object
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300808 error_log("Invalid type '".gettype($val)."' (value: ".$val.') passed to XML_RPC_Response. Defaulting to empty value.');
Derek Allard2067d1a2008-11-13 22:59:24 +0000809 $this->val = new XML_RPC_Values();
810 }
811 else
812 {
813 $this->val = $val;
814 }
815 }
816
Andrey Andreevc8709832012-04-04 13:43:53 +0300817 // --------------------------------------------------------------------
818
819 /**
820 * Fault code
821 *
822 * @return int
823 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200824 public function faultCode()
Derek Allard2067d1a2008-11-13 22:59:24 +0000825 {
826 return $this->errno;
827 }
828
Andrey Andreevc8709832012-04-04 13:43:53 +0300829 // --------------------------------------------------------------------
830
831 /**
832 * Fault string
833 *
834 * @return string
835 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200836 public function faultString()
Derek Allard2067d1a2008-11-13 22:59:24 +0000837 {
838 return $this->errstr;
839 }
840
Andrey Andreevc8709832012-04-04 13:43:53 +0300841 // --------------------------------------------------------------------
842
843 /**
844 * Value
845 *
846 * @return mixed
847 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200848 public function value()
Derek Allard2067d1a2008-11-13 22:59:24 +0000849 {
850 return $this->val;
851 }
Barry Mienydd671972010-10-04 16:33:58 +0200852
Andrey Andreevc8709832012-04-04 13:43:53 +0300853 // --------------------------------------------------------------------
854
855 /**
856 * Prepare response
857 *
858 * @return string xml
859 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200860 public function prepare_response()
Derek Allard2067d1a2008-11-13 22:59:24 +0000861 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200862 return "<methodResponse>\n"
Andrey Andreevc8709832012-04-04 13:43:53 +0300863 .($this->errno
864 ? '<fault>
Derek Allard2067d1a2008-11-13 22:59:24 +0000865 <value>
866 <struct>
867 <member>
868 <name>faultCode</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300869 <value><int>'.$this->errno.'</int></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000870 </member>
871 <member>
872 <name>faultString</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300873 <value><string>'.$this->errstr.'</string></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000874 </member>
875 </struct>
876 </value>
Andrey Andreeva30faf92011-12-25 18:15:34 +0200877</fault>'
Andrey Andreevc8709832012-04-04 13:43:53 +0300878 : "<params>\n<param>\n".$this->val->serialize_class()."</param>\n</params>")
879 ."\n</methodResponse>";
Derek Allard2067d1a2008-11-13 22:59:24 +0000880 }
Barry Mienydd671972010-10-04 16:33:58 +0200881
Andrey Andreevc8709832012-04-04 13:43:53 +0300882 // --------------------------------------------------------------------
883
884 /**
885 * Decode
886 *
Andrey Andreeve417f042014-01-08 14:48:01 +0200887 * @param mixed $array
Andrey Andreevc8709832012-04-04 13:43:53 +0300888 * @return array
889 */
Andrey Andreeve417f042014-01-08 14:48:01 +0200890 public function decode($array = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000891 {
892 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +0200893
894 if (is_array($array))
Derek Allard2067d1a2008-11-13 22:59:24 +0000895 {
896 while (list($key) = each($array))
897 {
898 if (is_array($array[$key]))
899 {
900 $array[$key] = $this->decode($array[$key]);
901 }
Andrey Andreeve417f042014-01-08 14:48:01 +0200902 elseif ($this->xss_clean)
Derek Allard2067d1a2008-11-13 22:59:24 +0000903 {
Andrey Andreeve417f042014-01-08 14:48:01 +0200904 $array[$key] = $CI->security->xss_clean($array[$key]);
Derek Allard2067d1a2008-11-13 22:59:24 +0000905 }
906 }
Barry Mienydd671972010-10-04 16:33:58 +0200907
Andrey Andreevc8709832012-04-04 13:43:53 +0300908 return $array;
909 }
910
911 $result = $this->xmlrpc_decoder($this->val);
912
913 if (is_array($result))
914 {
915 $result = $this->decode($result);
Derek Allard2067d1a2008-11-13 22:59:24 +0000916 }
Andrey Andreeve417f042014-01-08 14:48:01 +0200917 elseif ($this->xss_clean)
Derek Allard2067d1a2008-11-13 22:59:24 +0000918 {
Andrey Andreeve417f042014-01-08 14:48:01 +0200919 $result = $CI->security->xss_clean($result);
Derek Allard2067d1a2008-11-13 22:59:24 +0000920 }
Barry Mienydd671972010-10-04 16:33:58 +0200921
Derek Allard2067d1a2008-11-13 22:59:24 +0000922 return $result;
923 }
924
Andrey Andreevc8709832012-04-04 13:43:53 +0300925 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000926
Andrey Andreevc8709832012-04-04 13:43:53 +0300927 /**
928 * XML-RPC Object to PHP Types
929 *
930 * @param object
931 * @return array
932 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200933 public function xmlrpc_decoder($xmlrpc_val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000934 {
935 $kind = $xmlrpc_val->kindOf();
936
Alex Bilbied261b1e2012-06-02 11:12:16 +0100937 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +0000938 {
939 return $xmlrpc_val->scalarval();
940 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100941 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +0000942 {
943 reset($xmlrpc_val->me);
Andrey Andreevadc11752011-12-30 14:46:08 +0200944 $b = current($xmlrpc_val->me);
Derek Allard2067d1a2008-11-13 22:59:24 +0000945 $arr = array();
946
Andrey Andreeva30faf92011-12-25 18:15:34 +0200947 for ($i = 0, $size = count($b); $i < $size; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000948 {
949 $arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);
950 }
951 return $arr;
952 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100953 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +0000954 {
955 reset($xmlrpc_val->me['struct']);
956 $arr = array();
957
Pascal Kriete14287f32011-02-14 13:39:34 -0500958 while (list($key,$value) = each($xmlrpc_val->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000959 {
960 $arr[$key] = $this->xmlrpc_decoder($value);
961 }
962 return $arr;
963 }
964 }
Barry Mienydd671972010-10-04 16:33:58 +0200965
Andrey Andreevc8709832012-04-04 13:43:53 +0300966 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000967
Andrey Andreevc8709832012-04-04 13:43:53 +0300968 /**
969 * ISO-8601 time to server or UTC time
970 *
971 * @param string
972 * @param bool
973 * @return int unix timestamp
974 */
975 public function iso8601_decode($time, $utc = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000976 {
vkeranovb497d2b2012-11-23 23:27:33 +0200977 // Return a time in the localtime, or UTC
Derek Allard2067d1a2008-11-13 22:59:24 +0000978 $t = 0;
979 if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))
980 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100981 $fnc = ($utc === TRUE) ? 'gmmktime' : 'mktime';
Pascal Kriete14287f32011-02-14 13:39:34 -0500982 $t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
Derek Allard2067d1a2008-11-13 22:59:24 +0000983 }
984 return $t;
985 }
Barry Mienydd671972010-10-04 16:33:58 +0200986
Andrey Andreevc8709832012-04-04 13:43:53 +0300987} // END XML_RPC_Response Class
Derek Allard2067d1a2008-11-13 22:59:24 +0000988
989/**
990 * XML-RPC Message class
991 *
992 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500993 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000994 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
995 */
996class XML_RPC_Message extends CI_Xmlrpc
997{
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200998
999 /**
1000 * Payload
1001 *
1002 * @var string
1003 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001004 public $payload;
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001005
1006 /**
1007 * Method name
1008 *
1009 * @var string
1010 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001011 public $method_name;
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001012
1013 /**
1014 * Parameter list
1015 *
1016 * @var array
1017 */
Andrey Andreevc8709832012-04-04 13:43:53 +03001018 public $params = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001019
1020 /**
1021 * XH?
1022 *
1023 * @var array
1024 */
Andrey Andreevc8709832012-04-04 13:43:53 +03001025 public $xh = array();
Derek Allard2067d1a2008-11-13 22:59:24 +00001026
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001027 // --------------------------------------------------------------------
1028
Andrey Andreevc8709832012-04-04 13:43:53 +03001029 /**
1030 * Constructor
1031 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001032 * @param string $method
1033 * @param array $pars
Andrey Andreevc8709832012-04-04 13:43:53 +03001034 * @return void
1035 */
1036 public function __construct($method, $pars = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001037 {
Greg Akera9263282010-11-10 15:26:43 -06001038 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +02001039
Derek Allard2067d1a2008-11-13 22:59:24 +00001040 $this->method_name = $method;
Derek Jones33559102009-02-02 18:50:38 +00001041 if (is_array($pars) && count($pars) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001042 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001043 for ($i = 0, $c = count($pars); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001044 {
1045 // $pars[$i] = XML_RPC_Values
1046 $this->params[] = $pars[$i];
1047 }
1048 }
1049 }
Barry Mienydd671972010-10-04 16:33:58 +02001050
Andrey Andreevc8709832012-04-04 13:43:53 +03001051 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001052
Andrey Andreevc8709832012-04-04 13:43:53 +03001053 /**
1054 * Create Payload to Send
1055 *
1056 * @return void
1057 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001058 public function createPayload()
Derek Allard2067d1a2008-11-13 22:59:24 +00001059 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001060 $this->payload = '<?xml version="1.0"?'.">\r\n<methodCall>\r\n"
1061 .'<methodName>'.$this->method_name."</methodName>\r\n"
1062 ."<params>\r\n";
Barry Mienydd671972010-10-04 16:33:58 +02001063
Andrey Andreeva30faf92011-12-25 18:15:34 +02001064 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001065 {
1066 // $p = XML_RPC_Values
1067 $p = $this->params[$i];
1068 $this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n";
1069 }
Barry Mienydd671972010-10-04 16:33:58 +02001070
Derek Allard2067d1a2008-11-13 22:59:24 +00001071 $this->payload .= "</params>\r\n</methodCall>\r\n";
1072 }
Barry Mienydd671972010-10-04 16:33:58 +02001073
Andrey Andreevc8709832012-04-04 13:43:53 +03001074 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001075
Andrey Andreevc8709832012-04-04 13:43:53 +03001076 /**
1077 * Parse External XML-RPC Server's Response
1078 *
1079 * @param resource
1080 * @return object
1081 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001082 public function parseResponse($fp)
Derek Allard2067d1a2008-11-13 22:59:24 +00001083 {
1084 $data = '';
Barry Mienydd671972010-10-04 16:33:58 +02001085
Pascal Kriete14287f32011-02-14 13:39:34 -05001086 while ($datum = fread($fp, 4096))
Derek Allard2067d1a2008-11-13 22:59:24 +00001087 {
1088 $data .= $datum;
1089 }
Barry Mienydd671972010-10-04 16:33:58 +02001090
Andrey Andreevc8709832012-04-04 13:43:53 +03001091 // Display HTTP content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +00001092 if ($this->debug === TRUE)
1093 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001094 echo "<pre>---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n</pre>";
Derek Allard2067d1a2008-11-13 22:59:24 +00001095 }
Barry Mienydd671972010-10-04 16:33:58 +02001096
Andrey Andreevc8709832012-04-04 13:43:53 +03001097 // Check for data
Andrey Andreeva30faf92011-12-25 18:15:34 +02001098 if ($data === '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001099 {
1100 error_log($this->xmlrpcstr['no_data']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001101 return new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001102 }
Barry Mienydd671972010-10-04 16:33:58 +02001103
Andrey Andreevc8709832012-04-04 13:43:53 +03001104 // Check for HTTP 200 Response
Andrey Andreev3dad2e72012-06-14 15:10:56 +03001105 if (strpos($data, 'HTTP') === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
Derek Allard2067d1a2008-11-13 22:59:24 +00001106 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001107 $errstr = substr($data, 0, strpos($data, "\n")-1);
1108 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');
Derek Allard2067d1a2008-11-13 22:59:24 +00001109 }
Barry Mienydd671972010-10-04 16:33:58 +02001110
Derek Allard2067d1a2008-11-13 22:59:24 +00001111 //-------------------------------------
vkeranovb497d2b2012-11-23 23:27:33 +02001112 // Create and Set Up XML Parser
Derek Allard2067d1a2008-11-13 22:59:24 +00001113 //-------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001114
Derek Allard2067d1a2008-11-13 22:59:24 +00001115 $parser = xml_parser_create($this->xmlrpc_defencoding);
1116
Andrey Andreeva30faf92011-12-25 18:15:34 +02001117 $this->xh[$parser] = array(
Andrey Andreevc8709832012-04-04 13:43:53 +03001118 'isf' => 0,
1119 'ac' => '',
1120 'headers' => array(),
1121 'stack' => array(),
1122 'valuestack' => array(),
1123 'isf_reason' => 0
Andrey Andreeva30faf92011-12-25 18:15:34 +02001124 );
Derek Allard2067d1a2008-11-13 22:59:24 +00001125
1126 xml_set_object($parser, $this);
Andrey Andreevc8709832012-04-04 13:43:53 +03001127 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +00001128 xml_set_element_handler($parser, 'open_tag', 'closing_tag');
1129 xml_set_character_data_handler($parser, 'character_data');
1130 //xml_set_default_handler($parser, 'default_handler');
1131
Andrey Andreevc8709832012-04-04 13:43:53 +03001132 // Get headers
Derek Allard2067d1a2008-11-13 22:59:24 +00001133 $lines = explode("\r\n", $data);
1134 while (($line = array_shift($lines)))
1135 {
1136 if (strlen($line) < 1)
1137 {
1138 break;
1139 }
1140 $this->xh[$parser]['headers'][] = $line;
1141 }
1142 $data = implode("\r\n", $lines);
Barry Mienydd671972010-10-04 16:33:58 +02001143
Andrey Andreevc8709832012-04-04 13:43:53 +03001144 // Parse XML data
Derek Jones33559102009-02-02 18:50:38 +00001145 if ( ! xml_parse($parser, $data, count($data)))
Derek Allard2067d1a2008-11-13 22:59:24 +00001146 {
1147 $errstr = sprintf('XML error: %s at line %d',
Andrey Andreevc8709832012-04-04 13:43:53 +03001148 xml_error_string(xml_get_error_code($parser)),
1149 xml_get_current_line_number($parser));
vkeranovb497d2b2012-11-23 23:27:33 +02001150
Derek Allard2067d1a2008-11-13 22:59:24 +00001151 $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
1152 xml_parser_free($parser);
1153 return $r;
1154 }
1155 xml_parser_free($parser);
Barry Mienydd671972010-10-04 16:33:58 +02001156
Andrey Andreevc8709832012-04-04 13:43:53 +03001157 // Got ourselves some badness, it seems
Derek Allard2067d1a2008-11-13 22:59:24 +00001158 if ($this->xh[$parser]['isf'] > 1)
1159 {
1160 if ($this->debug === TRUE)
1161 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001162 echo "---Invalid Return---\n".$this->xh[$parser]['isf_reason']."---Invalid Return---\n\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001163 }
Barry Mienydd671972010-10-04 16:33:58 +02001164
Andrey Andreevc8709832012-04-04 13:43:53 +03001165 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 +00001166 }
1167 elseif ( ! is_object($this->xh[$parser]['value']))
1168 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001169 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 +00001170 }
Barry Mienydd671972010-10-04 16:33:58 +02001171
Andrey Andreevc8709832012-04-04 13:43:53 +03001172 // Display XML content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +00001173 if ($this->debug === TRUE)
1174 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001175 echo '<pre>';
Barry Mienydd671972010-10-04 16:33:58 +02001176
Derek Allard2067d1a2008-11-13 22:59:24 +00001177 if (count($this->xh[$parser]['headers'] > 0))
1178 {
1179 echo "---HEADERS---\n";
1180 foreach ($this->xh[$parser]['headers'] as $header)
1181 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001182 echo $header."\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001183 }
1184 echo "---END HEADERS---\n\n";
1185 }
Barry Mienydd671972010-10-04 16:33:58 +02001186
Andrey Andreeva30faf92011-12-25 18:15:34 +02001187 echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n---PARSED---\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001188 var_dump($this->xh[$parser]['value']);
1189 echo "\n---END PARSED---</pre>";
1190 }
Barry Mienydd671972010-10-04 16:33:58 +02001191
Andrey Andreevc8709832012-04-04 13:43:53 +03001192 // Send response
Derek Allard2067d1a2008-11-13 22:59:24 +00001193 $v = $this->xh[$parser]['value'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001194 if ($this->xh[$parser]['isf'])
1195 {
1196 $errno_v = $v->me['struct']['faultCode'];
1197 $errstr_v = $v->me['struct']['faultString'];
1198 $errno = $errno_v->scalarval();
1199
Alex Bilbied261b1e2012-06-02 11:12:16 +01001200 if ($errno === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001201 {
1202 // FAULT returned, errno needs to reflect that
1203 $errno = -1;
1204 }
1205
1206 $r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
1207 }
1208 else
1209 {
1210 $r = new XML_RPC_Response($v);
1211 }
1212
1213 $r->headers = $this->xh[$parser]['headers'];
1214 return $r;
1215 }
Barry Mienydd671972010-10-04 16:33:58 +02001216
Andrey Andreevc8709832012-04-04 13:43:53 +03001217 // --------------------------------------------------------------------
1218
Derek Allard2067d1a2008-11-13 22:59:24 +00001219 // ------------------------------------
Derek Jones37f4b9c2011-07-01 17:56:50 -05001220 // Begin Return Message Parsing section
Derek Allard2067d1a2008-11-13 22:59:24 +00001221 // ------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001222
Derek Allard2067d1a2008-11-13 22:59:24 +00001223 // quick explanation of components:
Derek Jones37f4b9c2011-07-01 17:56:50 -05001224 // ac - used to accumulate values
1225 // isf - used to indicate a fault
1226 // lv - used to indicate "looking for a value": implements
Derek Allard2067d1a2008-11-13 22:59:24 +00001227 // the logic to allow values with no types to be strings
Derek Jones37f4b9c2011-07-01 17:56:50 -05001228 // params - used to store parameters in method calls
1229 // method - used to store method name
Derek Allard2067d1a2008-11-13 22:59:24 +00001230 // stack - array with parent tree of the xml element,
1231 // used to validate the nesting of elements
1232
Andrey Andreevc8709832012-04-04 13:43:53 +03001233 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001234
Andrey Andreevc8709832012-04-04 13:43:53 +03001235 /**
1236 * Start Element Handler
1237 *
1238 * @param string
1239 * @param string
1240 * @return void
1241 */
1242 public function open_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001243 {
1244 // If invalid nesting, then return
1245 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001246
Derek Allard2067d1a2008-11-13 22:59:24 +00001247 // Evaluate and check for correct nesting of XML elements
Alex Bilbied261b1e2012-06-02 11:12:16 +01001248 if (count($this->xh[$the_parser]['stack']) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001249 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001250 if ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')
Derek Allard2067d1a2008-11-13 22:59:24 +00001251 {
1252 $this->xh[$the_parser]['isf'] = 2;
1253 $this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
1254 return;
1255 }
1256 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001257 // not top level element: see if parent is OK
1258 elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +00001259 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001260 $this->xh[$the_parser]['isf'] = 2;
vkeranovb497d2b2012-11-23 23:27:33 +02001261 $this->xh[$the_parser]['isf_reason'] = 'XML-RPC element '.$name.' cannot be child of '.$this->xh[$the_parser]['stack'][0];
Andrey Andreevc8709832012-04-04 13:43:53 +03001262 return;
Derek Allard2067d1a2008-11-13 22:59:24 +00001263 }
Barry Mienydd671972010-10-04 16:33:58 +02001264
Andrey Andreevc8709832012-04-04 13:43:53 +03001265 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001266 {
1267 case 'STRUCT':
1268 case 'ARRAY':
1269 // Creates array for child elements
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001270 $cur_val = array('value' => array(), 'type' => $name);
Derek Allard2067d1a2008-11-13 22:59:24 +00001271 array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
Andrey Andreevc8709832012-04-04 13:43:53 +03001272 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001273 case 'METHODNAME':
1274 case 'NAME':
1275 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +03001276 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001277 case 'FAULT':
1278 $this->xh[$the_parser]['isf'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +03001279 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001280 case 'PARAM':
Pascal Kriete8761ef52011-02-14 13:13:52 -05001281 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +03001282 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001283 case 'VALUE':
1284 $this->xh[$the_parser]['vt'] = 'value';
1285 $this->xh[$the_parser]['ac'] = '';
1286 $this->xh[$the_parser]['lv'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +03001287 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001288 case 'I4':
1289 case 'INT':
1290 case 'STRING':
1291 case 'BOOLEAN':
1292 case 'DOUBLE':
1293 case 'DATETIME.ISO8601':
1294 case 'BASE64':
Alex Bilbied261b1e2012-06-02 11:12:16 +01001295 if ($this->xh[$the_parser]['vt'] !== 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +00001296 {
1297 //two data elements inside a value: an error occurred!
1298 $this->xh[$the_parser]['isf'] = 2;
vkeranovb497d2b2012-11-23 23:27:33 +02001299 $this->xh[$the_parser]['isf_reason'] = 'There is a '.$name.' element following a '
Andrey Andreevc8709832012-04-04 13:43:53 +03001300 .$this->xh[$the_parser]['vt'].' element inside a single value';
Derek Allard2067d1a2008-11-13 22:59:24 +00001301 return;
1302 }
Barry Mienydd671972010-10-04 16:33:58 +02001303
Derek Allard2067d1a2008-11-13 22:59:24 +00001304 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +03001305 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001306 case 'MEMBER':
1307 // Set name of <member> to nothing to prevent errors later if no <name> is found
1308 $this->xh[$the_parser]['valuestack'][0]['name'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001309
Derek Allard2067d1a2008-11-13 22:59:24 +00001310 // Set NULL value to check to see if value passed for this param/member
Pascal Kriete8761ef52011-02-14 13:13:52 -05001311 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +03001312 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001313 case 'DATA':
1314 case 'METHODCALL':
1315 case 'METHODRESPONSE':
1316 case 'PARAMS':
1317 // valid elements that add little to processing
Andrey Andreevc8709832012-04-04 13:43:53 +03001318 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001319 default:
1320 /// An Invalid Element is Found, so we have trouble
1321 $this->xh[$the_parser]['isf'] = 2;
Andrey Andreevc8709832012-04-04 13:43:53 +03001322 $this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;
1323 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001324 }
Barry Mienydd671972010-10-04 16:33:58 +02001325
Derek Allard2067d1a2008-11-13 22:59:24 +00001326 // Add current element name to stack, to allow validation of nesting
1327 array_unshift($this->xh[$the_parser]['stack'], $name);
1328
Alex Bilbied261b1e2012-06-02 11:12:16 +01001329 $name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001330 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001331
Andrey Andreevc8709832012-04-04 13:43:53 +03001332 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001333
Andrey Andreevc8709832012-04-04 13:43:53 +03001334 /**
1335 * End Element Handler
1336 *
1337 * @param string
1338 * @param string
1339 * @return void
1340 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001341 public function closing_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001342 {
1343 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001344
Derek Allard2067d1a2008-11-13 22:59:24 +00001345 // Remove current element from stack and set variable
1346 // NOTE: If the XML validates, then we do not have to worry about
Andrey Andreevc8709832012-04-04 13:43:53 +03001347 // the opening and closing of elements. Nesting is checked on the opening
Derek Allard2067d1a2008-11-13 22:59:24 +00001348 // tag so we be safe there as well.
Barry Mienydd671972010-10-04 16:33:58 +02001349
Derek Allard2067d1a2008-11-13 22:59:24 +00001350 $curr_elem = array_shift($this->xh[$the_parser]['stack']);
Barry Mienydd671972010-10-04 16:33:58 +02001351
Andrey Andreevc8709832012-04-04 13:43:53 +03001352 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001353 {
1354 case 'STRUCT':
1355 case 'ARRAY':
1356 $cur_val = array_shift($this->xh[$the_parser]['valuestack']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001357 $this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();
Derek Allard2067d1a2008-11-13 22:59:24 +00001358 $this->xh[$the_parser]['vt'] = strtolower($name);
Andrey Andreevc8709832012-04-04 13:43:53 +03001359 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001360 case 'NAME':
1361 $this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
Andrey Andreevc8709832012-04-04 13:43:53 +03001362 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001363 case 'BOOLEAN':
1364 case 'I4':
1365 case 'INT':
1366 case 'STRING':
1367 case 'DOUBLE':
1368 case 'DATETIME.ISO8601':
1369 case 'BASE64':
1370 $this->xh[$the_parser]['vt'] = strtolower($name);
Barry Mienydd671972010-10-04 16:33:58 +02001371
Alex Bilbied261b1e2012-06-02 11:12:16 +01001372 if ($name === 'STRING')
Derek Allard2067d1a2008-11-13 22:59:24 +00001373 {
1374 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1375 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001376 elseif ($name === 'DATETIME.ISO8601')
Derek Allard2067d1a2008-11-13 22:59:24 +00001377 {
1378 $this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime;
1379 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1380 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001381 elseif ($name === 'BASE64')
Derek Allard2067d1a2008-11-13 22:59:24 +00001382 {
1383 $this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
1384 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001385 elseif ($name === 'BOOLEAN')
Derek Allard2067d1a2008-11-13 22:59:24 +00001386 {
1387 // Translated BOOLEAN values to TRUE AND FALSE
Andrey Andreevc8709832012-04-04 13:43:53 +03001388 $this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001389 }
1390 elseif ($name=='DOUBLE')
1391 {
1392 // we have a DOUBLE
1393 // we must check that only 0123456789-.<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001394 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])
1395 ? (float) $this->xh[$the_parser]['ac']
1396 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001397 }
1398 else
1399 {
1400 // we have an I4/INT
1401 // we must check that only 0123456789-<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001402 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])
George Petsagourakis306b3782012-05-02 20:31:08 +03001403 ? (int) $this->xh[$the_parser]['ac']
Andrey Andreevc8709832012-04-04 13:43:53 +03001404 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001405 }
1406 $this->xh[$the_parser]['ac'] = '';
1407 $this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
Andrey Andreevc8709832012-04-04 13:43:53 +03001408 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001409 case 'VALUE':
1410 // This if() detects if no scalar was inside <VALUE></VALUE>
vkeranovb497d2b2012-11-23 23:27:33 +02001411 if ($this->xh[$the_parser]['vt'] == 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +00001412 {
1413 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1414 $this->xh[$the_parser]['vt'] = $this->xmlrpcString;
1415 }
Barry Mienydd671972010-10-04 16:33:58 +02001416
Derek Allard2067d1a2008-11-13 22:59:24 +00001417 // build the XML-RPC value out of the data received, and substitute it
1418 $temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
Barry Mienydd671972010-10-04 16:33:58 +02001419
Alex Bilbied261b1e2012-06-02 11:12:16 +01001420 if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')
Derek Allard2067d1a2008-11-13 22:59:24 +00001421 {
1422 // Array
1423 $this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
1424 }
1425 else
1426 {
1427 // Struct
1428 $this->xh[$the_parser]['value'] = $temp;
1429 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001430 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001431 case 'MEMBER':
Andrey Andreevc8709832012-04-04 13:43:53 +03001432 $this->xh[$the_parser]['ac'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001433
Derek Allard2067d1a2008-11-13 22:59:24 +00001434 // If value add to array in the stack for the last element built
1435 if ($this->xh[$the_parser]['value'])
1436 {
1437 $this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
1438 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001439 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001440 case 'DATA':
Andrey Andreevc8709832012-04-04 13:43:53 +03001441 $this->xh[$the_parser]['ac'] = '';
1442 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001443 case 'PARAM':
1444 if ($this->xh[$the_parser]['value'])
1445 {
1446 $this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
1447 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001448 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001449 case 'METHODNAME':
1450 $this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001451 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001452 case 'PARAMS':
1453 case 'FAULT':
1454 case 'METHODCALL':
1455 case 'METHORESPONSE':
1456 // We're all good kids with nuthin' to do
Andrey Andreevc8709832012-04-04 13:43:53 +03001457 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001458 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001459 // End of an Invalid Element. Taken care of during the opening tag though
1460 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001461 }
1462 }
1463
Andrey Andreevc8709832012-04-04 13:43:53 +03001464 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001465
Andrey Andreevc8709832012-04-04 13:43:53 +03001466 /**
1467 * Parse character data
1468 *
1469 * @param string
1470 * @param string
1471 * @return void
1472 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001473 public function character_data($the_parser, $data)
Derek Allard2067d1a2008-11-13 22:59:24 +00001474 {
1475 if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
Barry Mienydd671972010-10-04 16:33:58 +02001476
Derek Allard2067d1a2008-11-13 22:59:24 +00001477 // If a value has not been found
Alex Bilbied261b1e2012-06-02 11:12:16 +01001478 if ($this->xh[$the_parser]['lv'] !== 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001479 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001480 if ($this->xh[$the_parser]['lv'] === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001481 {
1482 $this->xh[$the_parser]['lv'] = 2; // Found a value
1483 }
Barry Mienydd671972010-10-04 16:33:58 +02001484
Andrey Andreevc8709832012-04-04 13:43:53 +03001485 if ( ! isset($this->xh[$the_parser]['ac']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001486 {
1487 $this->xh[$the_parser]['ac'] = '';
1488 }
Barry Mienydd671972010-10-04 16:33:58 +02001489
Derek Allard2067d1a2008-11-13 22:59:24 +00001490 $this->xh[$the_parser]['ac'] .= $data;
1491 }
1492 }
Barry Mienydd671972010-10-04 16:33:58 +02001493
Andrey Andreevc8709832012-04-04 13:43:53 +03001494 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001495
Andrey Andreevc8709832012-04-04 13:43:53 +03001496 /**
1497 * Add parameter
1498 *
1499 * @param mixed
1500 * @return void
1501 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001502 public function addParam($par)
1503 {
1504 $this->params[] = $par;
1505 }
Barry Mienydd671972010-10-04 16:33:58 +02001506
Andrey Andreevc8709832012-04-04 13:43:53 +03001507 // --------------------------------------------------------------------
1508
1509 /**
1510 * Output parameters
1511 *
Andrey Andreeve417f042014-01-08 14:48:01 +02001512 * @param array $array
Andrey Andreevc8709832012-04-04 13:43:53 +03001513 * @return array
1514 */
Andrey Andreeve417f042014-01-08 14:48:01 +02001515 public function output_parameters(array $array = array())
Derek Allard2067d1a2008-11-13 22:59:24 +00001516 {
Barry Mienydd671972010-10-04 16:33:58 +02001517 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +02001518
Andrey Andreeve417f042014-01-08 14:48:01 +02001519 if ( ! empty($array))
Derek Allard2067d1a2008-11-13 22:59:24 +00001520 {
1521 while (list($key) = each($array))
1522 {
1523 if (is_array($array[$key]))
1524 {
1525 $array[$key] = $this->output_parameters($array[$key]);
1526 }
Andrey Andreeve417f042014-01-08 14:48:01 +02001527 elseif ($key !== 'bits' && $this->xss_clean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001528 {
Derek Jonesa9647e82010-03-02 22:59:07 -06001529 // 'bits' is for the MetaWeblog API image bits
1530 // @todo - this needs to be made more general purpose
Andrey Andreeve417f042014-01-08 14:48:01 +02001531 $array[$key] = $CI->security->xss_clean($array[$key]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001532 }
1533 }
Barry Mienydd671972010-10-04 16:33:58 +02001534
Andrey Andreevc8709832012-04-04 13:43:53 +03001535 return $array;
Derek Allard2067d1a2008-11-13 22:59:24 +00001536 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001537
1538 $parameters = array();
1539
1540 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001541 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001542 $a_param = $this->decode_message($this->params[$i]);
Barry Mienydd671972010-10-04 16:33:58 +02001543
Andrey Andreevc8709832012-04-04 13:43:53 +03001544 if (is_array($a_param))
Derek Allard2067d1a2008-11-13 22:59:24 +00001545 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001546 $parameters[] = $this->output_parameters($a_param);
1547 }
1548 else
1549 {
1550 $parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;
Barry Mienydd671972010-10-04 16:33:58 +02001551 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001552 }
Barry Mienydd671972010-10-04 16:33:58 +02001553
Derek Allard2067d1a2008-11-13 22:59:24 +00001554 return $parameters;
1555 }
Barry Mienydd671972010-10-04 16:33:58 +02001556
Andrey Andreevc8709832012-04-04 13:43:53 +03001557 // --------------------------------------------------------------------
1558
1559 /**
1560 * Decode message
1561 *
1562 * @param object
1563 * @return mixed
1564 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001565 public function decode_message($param)
Derek Allard2067d1a2008-11-13 22:59:24 +00001566 {
1567 $kind = $param->kindOf();
1568
Alex Bilbied261b1e2012-06-02 11:12:16 +01001569 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +00001570 {
1571 return $param->scalarval();
1572 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001573 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +00001574 {
1575 reset($param->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001576 $b = current($param->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001577 $arr = array();
1578
Andrey Andreevc8709832012-04-04 13:43:53 +03001579 for ($i = 0, $c = count($b); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001580 {
1581 $arr[] = $this->decode_message($param->me['array'][$i]);
1582 }
Barry Mienydd671972010-10-04 16:33:58 +02001583
Derek Allard2067d1a2008-11-13 22:59:24 +00001584 return $arr;
1585 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001586 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +00001587 {
1588 reset($param->me['struct']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001589 $arr = array();
1590
Pascal Kriete14287f32011-02-14 13:39:34 -05001591 while (list($key,$value) = each($param->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001592 {
1593 $arr[$key] = $this->decode_message($value);
1594 }
Barry Mienydd671972010-10-04 16:33:58 +02001595
Derek Allard2067d1a2008-11-13 22:59:24 +00001596 return $arr;
1597 }
1598 }
Barry Mienydd671972010-10-04 16:33:58 +02001599
Andrey Andreevc8709832012-04-04 13:43:53 +03001600} // END XML_RPC_Message Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001601
1602/**
1603 * XML-RPC Values class
1604 *
1605 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -05001606 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +00001607 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
1608 */
1609class XML_RPC_Values extends CI_Xmlrpc
1610{
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001611 /**
1612 * Value data
1613 *
1614 * @var array
1615 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001616 public $me = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001617
1618 /**
1619 * Value type
1620 *
1621 * @var int
1622 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001623 public $mytype = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001624
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001625 // --------------------------------------------------------------------
1626
Andrey Andreevc8709832012-04-04 13:43:53 +03001627 /**
1628 * Constructor
1629 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001630 * @param mixed $val
1631 * @param string $type
Andrey Andreevc8709832012-04-04 13:43:53 +03001632 * @return void
1633 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001634 public function __construct($val = -1, $type = '')
Barry Mienydd671972010-10-04 16:33:58 +02001635 {
Greg Akera9263282010-11-10 15:26:43 -06001636 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +02001637
Alex Bilbied261b1e2012-06-02 11:12:16 +01001638 if ($val !== -1 OR $type !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001639 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001640 $type = $type === '' ? 'string' : $type;
Barry Mienydd671972010-10-04 16:33:58 +02001641
Dimitar740480a2012-10-05 13:24:59 +03001642 if ($this->xmlrpcTypes[$type] == 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001643 {
vkeranovb497d2b2012-11-23 23:27:33 +02001644 $this->addScalar($val, $type);
Derek Allard2067d1a2008-11-13 22:59:24 +00001645 }
Dimitar740480a2012-10-05 13:24:59 +03001646 elseif ($this->xmlrpcTypes[$type] == 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001647 {
1648 $this->addArray($val);
1649 }
Dimitar740480a2012-10-05 13:24:59 +03001650 elseif ($this->xmlrpcTypes[$type] == 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001651 {
1652 $this->addStruct($val);
1653 }
1654 }
1655 }
1656
Andrey Andreevc8709832012-04-04 13:43:53 +03001657 // --------------------------------------------------------------------
1658
1659 /**
1660 * Add scalar value
1661 *
1662 * @param scalar
1663 * @param string
1664 * @return int
1665 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001666 public function addScalar($val, $type = 'string')
Derek Allard2067d1a2008-11-13 22:59:24 +00001667 {
1668 $typeof = $this->xmlrpcTypes[$type];
Barry Mienydd671972010-10-04 16:33:58 +02001669
Alex Bilbied261b1e2012-06-02 11:12:16 +01001670 if ($this->mytype === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001671 {
1672 echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
1673 return 0;
1674 }
Barry Mienydd671972010-10-04 16:33:58 +02001675
Dimitar740480a2012-10-05 13:24:59 +03001676 if ($typeof != 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001677 {
1678 echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';
1679 return 0;
1680 }
1681
Alex Bilbied261b1e2012-06-02 11:12:16 +01001682 if ($type === $this->xmlrpcBoolean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001683 {
Andrey Andreev3f3f1352012-09-05 16:39:28 +03001684 $val = (int) (strcasecmp($val, 'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
Derek Allard2067d1a2008-11-13 22:59:24 +00001685 }
1686
Alex Bilbied261b1e2012-06-02 11:12:16 +01001687 if ($this->mytype === 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001688 {
1689 // adding to an array here
1690 $ar = $this->me['array'];
1691 $ar[] = new XML_RPC_Values($val, $type);
1692 $this->me['array'] = $ar;
1693 }
1694 else
1695 {
1696 // a scalar, so set the value and remember we're scalar
1697 $this->me[$type] = $val;
1698 $this->mytype = $typeof;
1699 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001700
Derek Allard2067d1a2008-11-13 22:59:24 +00001701 return 1;
1702 }
1703
Andrey Andreevc8709832012-04-04 13:43:53 +03001704 // --------------------------------------------------------------------
1705
1706 /**
1707 * Add array value
1708 *
1709 * @param array
1710 * @return int
1711 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001712 public function addArray($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001713 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001714 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001715 {
Andrey Andreev3ca060a2013-11-27 16:30:31 +02001716 echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
Derek Allard2067d1a2008-11-13 22:59:24 +00001717 return 0;
1718 }
1719
1720 $this->mytype = $this->xmlrpcTypes['array'];
1721 $this->me['array'] = $vals;
1722 return 1;
1723 }
1724
Andrey Andreevc8709832012-04-04 13:43:53 +03001725 // --------------------------------------------------------------------
1726
1727 /**
1728 * Add struct value
1729 *
1730 * @param object
1731 * @return int
1732 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001733 public function addStruct($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001734 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001735 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001736 {
Andrey Andreev3ca060a2013-11-27 16:30:31 +02001737 echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
Derek Allard2067d1a2008-11-13 22:59:24 +00001738 return 0;
1739 }
1740 $this->mytype = $this->xmlrpcTypes['struct'];
1741 $this->me['struct'] = $vals;
1742 return 1;
1743 }
1744
Andrey Andreevc8709832012-04-04 13:43:53 +03001745 // --------------------------------------------------------------------
1746
1747 /**
1748 * Get value type
1749 *
1750 * @return string
1751 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001752 public function kindOf()
Derek Allard2067d1a2008-11-13 22:59:24 +00001753 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001754 switch ($this->mytype)
Derek Allard2067d1a2008-11-13 22:59:24 +00001755 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001756 case 3: return 'struct';
1757 case 2: return 'array';
1758 case 1: return 'scalar';
1759 default: return 'undef';
Derek Allard2067d1a2008-11-13 22:59:24 +00001760 }
1761 }
1762
Andrey Andreevc8709832012-04-04 13:43:53 +03001763 // --------------------------------------------------------------------
1764
1765 /**
1766 * Serialize data
1767 *
1768 * @param string
1769 * @param mixed
1770 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001771 public function serializedata($typ, $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001772 {
1773 $rs = '';
Derek Jonesa9647e82010-03-02 22:59:07 -06001774
Andrey Andreevc8709832012-04-04 13:43:53 +03001775 switch ($this->xmlrpcTypes[$typ])
Derek Allard2067d1a2008-11-13 22:59:24 +00001776 {
1777 case 3:
1778 // struct
1779 $rs .= "<struct>\n";
1780 reset($val);
Pascal Kriete14287f32011-02-14 13:39:34 -05001781 while (list($key2, $val2) = each($val))
Derek Allard2067d1a2008-11-13 22:59:24 +00001782 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001783 $rs .= "<member>\n<name>{$key2}</name>\n".$this->serializeval($val2)."</member>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001784 }
1785 $rs .= '</struct>';
Andrey Andreevc8709832012-04-04 13:43:53 +03001786 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001787 case 2:
1788 // array
1789 $rs .= "<array>\n<data>\n";
Andrey Andreevc8709832012-04-04 13:43:53 +03001790 for ($i = 0, $c = count($val); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001791 {
1792 $rs .= $this->serializeval($val[$i]);
1793 }
Andrey Andreeva30faf92011-12-25 18:15:34 +02001794 $rs .= "</data>\n</array>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001795 break;
1796 case 1:
1797 // others
1798 switch ($typ)
1799 {
1800 case $this->xmlrpcBase64:
Andrey Andreevc8709832012-04-04 13:43:53 +03001801 $rs .= '<'.$typ.'>'.base64_encode( (string) $val).'</'.$typ.">\n";
1802 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001803 case $this->xmlrpcBoolean:
Andrey Andreevc8709832012-04-04 13:43:53 +03001804 $rs .= '<'.$typ.'>'.( (bool) $val ? '1' : '0').'</'.$typ.">\n";
1805 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001806 case $this->xmlrpcString:
Andrey Andreevc8709832012-04-04 13:43:53 +03001807 $rs .= '<'.$typ.'>'.htmlspecialchars( (string) $val).'</'.$typ.">\n";
1808 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001809 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001810 $rs .= '<'.$typ.'>'.$val.'</'.$typ.">\n";
1811 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001812 }
1813 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001814 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001815 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001816
Derek Allard2067d1a2008-11-13 22:59:24 +00001817 return $rs;
1818 }
1819
Andrey Andreevc8709832012-04-04 13:43:53 +03001820 // --------------------------------------------------------------------
1821
1822 /**
1823 * Serialize class
1824 *
1825 * @return string
1826 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001827 public function serialize_class()
Derek Allard2067d1a2008-11-13 22:59:24 +00001828 {
1829 return $this->serializeval($this);
1830 }
1831
Andrey Andreevc8709832012-04-04 13:43:53 +03001832 // --------------------------------------------------------------------
1833
1834 /**
1835 * Serialize value
1836 *
1837 * @param object
1838 * @return string
1839 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001840 public function serializeval($o)
Derek Allard2067d1a2008-11-13 22:59:24 +00001841 {
1842 $ar = $o->me;
1843 reset($ar);
Barry Mienydd671972010-10-04 16:33:58 +02001844
Derek Allard2067d1a2008-11-13 22:59:24 +00001845 list($typ, $val) = each($ar);
Andrey Andreeva30faf92011-12-25 18:15:34 +02001846 return "<value>\n".$this->serializedata($typ, $val)."</value>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001847 }
Barry Mienydd671972010-10-04 16:33:58 +02001848
Andrey Andreevc8709832012-04-04 13:43:53 +03001849 // --------------------------------------------------------------------
1850
1851 /**
1852 * Scalar value
1853 *
1854 * @return mixed
1855 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001856 public function scalarval()
Derek Allard2067d1a2008-11-13 22:59:24 +00001857 {
1858 reset($this->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001859 return current($this->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001860 }
1861
Andrey Andreevc8709832012-04-04 13:43:53 +03001862 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001863
Andrey Andreevc8709832012-04-04 13:43:53 +03001864 /**
1865 * Encode time in ISO-8601 form.
1866 * Useful for sending time in XML-RPC
1867 *
1868 * @param int unix timestamp
1869 * @param bool
1870 * @return string
1871 */
1872 public function iso8601_encode($time, $utc = FALSE)
Barry Mienydd671972010-10-04 16:33:58 +02001873 {
Andrey Andreev62090152011-12-30 12:49:27 +02001874 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 +00001875 }
Barry Mienydd671972010-10-04 16:33:58 +02001876
Andrey Andreevc8709832012-04-04 13:43:53 +03001877} // END XML_RPC_Values Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001878
1879/* End of file Xmlrpc.php */
Andrey Andreevc5a7c5f2013-07-17 20:10:09 +03001880/* Location: ./system/libraries/Xmlrpc.php */