blob: ab907e706aab17a67b39f16fc9b4445b9bad4421 [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
Andrey Andreevd8b1ad32014-01-15 17:42:52 +0200727 for ($written = 0, $length = strlen($op); $written < $length; $written += $result)
728 {
729 if (($result = fwrite($fp, substr($op, $written))) === FALSE)
730 {
731 break;
732 }
733 }
734
735 if ($result === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000736 {
737 error_log($this->xmlrpcstr['http_error']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300738 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000739 }
Andrey Andreevc8709832012-04-04 13:43:53 +0300740
Derek Allard2067d1a2008-11-13 22:59:24 +0000741 $resp = $msg->parseResponse($fp);
742 fclose($fp);
743 return $resp;
744 }
745
Andrey Andreevc8709832012-04-04 13:43:53 +0300746} // END XML_RPC_Client Class
Derek Allard2067d1a2008-11-13 22:59:24 +0000747
748/**
749 * XML-RPC Response class
750 *
751 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500752 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000753 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
754 */
755class XML_RPC_Response
756{
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200757
758 /**
759 * Value
760 *
761 * @var mixed
762 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300763 public $val = 0;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200764
765 /**
766 * Error number
767 *
768 * @var int
769 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300770 public $errno = 0;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200771
772 /**
773 * Error message
774 *
775 * @var string
776 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300777 public $errstr = '';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200778
779 /**
780 * Headers list
781 *
782 * @var array
783 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300784 public $headers = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200785
786 /**
787 * XSS Filter flag
788 *
789 * @var bool
790 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300791 public $xss_clean = TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000792
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200793 // --------------------------------------------------------------------
794
Andrey Andreevc8709832012-04-04 13:43:53 +0300795 /**
796 * Constructor
797 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200798 * @param mixed $val
799 * @param int $code
800 * @param string $fstr
Andrey Andreevc8709832012-04-04 13:43:53 +0300801 * @return void
802 */
Greg Akera9263282010-11-10 15:26:43 -0600803 public function __construct($val, $code = 0, $fstr = '')
Barry Mienydd671972010-10-04 16:33:58 +0200804 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100805 if ($code !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000806 {
807 // error
808 $this->errno = $code;
Andrey Andreevc8709832012-04-04 13:43:53 +0300809 $this->errstr = htmlspecialchars($fstr,
810 (is_php('5.4') ? ENT_XML1 | ENT_NOQUOTES : ENT_NOQUOTES),
811 'UTF-8');
Derek Allard2067d1a2008-11-13 22:59:24 +0000812 }
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300813 elseif ( ! is_object($val))
Derek Allard2067d1a2008-11-13 22:59:24 +0000814 {
815 // programmer error, not an object
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300816 error_log("Invalid type '".gettype($val)."' (value: ".$val.') passed to XML_RPC_Response. Defaulting to empty value.');
Derek Allard2067d1a2008-11-13 22:59:24 +0000817 $this->val = new XML_RPC_Values();
818 }
819 else
820 {
821 $this->val = $val;
822 }
823 }
824
Andrey Andreevc8709832012-04-04 13:43:53 +0300825 // --------------------------------------------------------------------
826
827 /**
828 * Fault code
829 *
830 * @return int
831 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200832 public function faultCode()
Derek Allard2067d1a2008-11-13 22:59:24 +0000833 {
834 return $this->errno;
835 }
836
Andrey Andreevc8709832012-04-04 13:43:53 +0300837 // --------------------------------------------------------------------
838
839 /**
840 * Fault string
841 *
842 * @return string
843 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200844 public function faultString()
Derek Allard2067d1a2008-11-13 22:59:24 +0000845 {
846 return $this->errstr;
847 }
848
Andrey Andreevc8709832012-04-04 13:43:53 +0300849 // --------------------------------------------------------------------
850
851 /**
852 * Value
853 *
854 * @return mixed
855 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200856 public function value()
Derek Allard2067d1a2008-11-13 22:59:24 +0000857 {
858 return $this->val;
859 }
Barry Mienydd671972010-10-04 16:33:58 +0200860
Andrey Andreevc8709832012-04-04 13:43:53 +0300861 // --------------------------------------------------------------------
862
863 /**
864 * Prepare response
865 *
866 * @return string xml
867 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200868 public function prepare_response()
Derek Allard2067d1a2008-11-13 22:59:24 +0000869 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200870 return "<methodResponse>\n"
Andrey Andreevc8709832012-04-04 13:43:53 +0300871 .($this->errno
872 ? '<fault>
Derek Allard2067d1a2008-11-13 22:59:24 +0000873 <value>
874 <struct>
875 <member>
876 <name>faultCode</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300877 <value><int>'.$this->errno.'</int></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000878 </member>
879 <member>
880 <name>faultString</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300881 <value><string>'.$this->errstr.'</string></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000882 </member>
883 </struct>
884 </value>
Andrey Andreeva30faf92011-12-25 18:15:34 +0200885</fault>'
Andrey Andreevc8709832012-04-04 13:43:53 +0300886 : "<params>\n<param>\n".$this->val->serialize_class()."</param>\n</params>")
887 ."\n</methodResponse>";
Derek Allard2067d1a2008-11-13 22:59:24 +0000888 }
Barry Mienydd671972010-10-04 16:33:58 +0200889
Andrey Andreevc8709832012-04-04 13:43:53 +0300890 // --------------------------------------------------------------------
891
892 /**
893 * Decode
894 *
Andrey Andreeve417f042014-01-08 14:48:01 +0200895 * @param mixed $array
Andrey Andreevc8709832012-04-04 13:43:53 +0300896 * @return array
897 */
Andrey Andreeve417f042014-01-08 14:48:01 +0200898 public function decode($array = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000899 {
900 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +0200901
902 if (is_array($array))
Derek Allard2067d1a2008-11-13 22:59:24 +0000903 {
904 while (list($key) = each($array))
905 {
906 if (is_array($array[$key]))
907 {
908 $array[$key] = $this->decode($array[$key]);
909 }
Andrey Andreeve417f042014-01-08 14:48:01 +0200910 elseif ($this->xss_clean)
Derek Allard2067d1a2008-11-13 22:59:24 +0000911 {
Andrey Andreeve417f042014-01-08 14:48:01 +0200912 $array[$key] = $CI->security->xss_clean($array[$key]);
Derek Allard2067d1a2008-11-13 22:59:24 +0000913 }
914 }
Barry Mienydd671972010-10-04 16:33:58 +0200915
Andrey Andreevc8709832012-04-04 13:43:53 +0300916 return $array;
917 }
918
919 $result = $this->xmlrpc_decoder($this->val);
920
921 if (is_array($result))
922 {
923 $result = $this->decode($result);
Derek Allard2067d1a2008-11-13 22:59:24 +0000924 }
Andrey Andreeve417f042014-01-08 14:48:01 +0200925 elseif ($this->xss_clean)
Derek Allard2067d1a2008-11-13 22:59:24 +0000926 {
Andrey Andreeve417f042014-01-08 14:48:01 +0200927 $result = $CI->security->xss_clean($result);
Derek Allard2067d1a2008-11-13 22:59:24 +0000928 }
Barry Mienydd671972010-10-04 16:33:58 +0200929
Derek Allard2067d1a2008-11-13 22:59:24 +0000930 return $result;
931 }
932
Andrey Andreevc8709832012-04-04 13:43:53 +0300933 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000934
Andrey Andreevc8709832012-04-04 13:43:53 +0300935 /**
936 * XML-RPC Object to PHP Types
937 *
938 * @param object
939 * @return array
940 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200941 public function xmlrpc_decoder($xmlrpc_val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000942 {
943 $kind = $xmlrpc_val->kindOf();
944
Alex Bilbied261b1e2012-06-02 11:12:16 +0100945 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +0000946 {
947 return $xmlrpc_val->scalarval();
948 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100949 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +0000950 {
951 reset($xmlrpc_val->me);
Andrey Andreevadc11752011-12-30 14:46:08 +0200952 $b = current($xmlrpc_val->me);
Derek Allard2067d1a2008-11-13 22:59:24 +0000953 $arr = array();
954
Andrey Andreeva30faf92011-12-25 18:15:34 +0200955 for ($i = 0, $size = count($b); $i < $size; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000956 {
957 $arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);
958 }
959 return $arr;
960 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100961 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +0000962 {
963 reset($xmlrpc_val->me['struct']);
964 $arr = array();
965
Pascal Kriete14287f32011-02-14 13:39:34 -0500966 while (list($key,$value) = each($xmlrpc_val->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000967 {
968 $arr[$key] = $this->xmlrpc_decoder($value);
969 }
970 return $arr;
971 }
972 }
Barry Mienydd671972010-10-04 16:33:58 +0200973
Andrey Andreevc8709832012-04-04 13:43:53 +0300974 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000975
Andrey Andreevc8709832012-04-04 13:43:53 +0300976 /**
977 * ISO-8601 time to server or UTC time
978 *
979 * @param string
980 * @param bool
981 * @return int unix timestamp
982 */
983 public function iso8601_decode($time, $utc = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000984 {
vkeranovb497d2b2012-11-23 23:27:33 +0200985 // Return a time in the localtime, or UTC
Derek Allard2067d1a2008-11-13 22:59:24 +0000986 $t = 0;
987 if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))
988 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100989 $fnc = ($utc === TRUE) ? 'gmmktime' : 'mktime';
Pascal Kriete14287f32011-02-14 13:39:34 -0500990 $t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
Derek Allard2067d1a2008-11-13 22:59:24 +0000991 }
992 return $t;
993 }
Barry Mienydd671972010-10-04 16:33:58 +0200994
Andrey Andreevc8709832012-04-04 13:43:53 +0300995} // END XML_RPC_Response Class
Derek Allard2067d1a2008-11-13 22:59:24 +0000996
997/**
998 * XML-RPC Message class
999 *
1000 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -05001001 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +00001002 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
1003 */
1004class XML_RPC_Message extends CI_Xmlrpc
1005{
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001006
1007 /**
1008 * Payload
1009 *
1010 * @var string
1011 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001012 public $payload;
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001013
1014 /**
1015 * Method name
1016 *
1017 * @var string
1018 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001019 public $method_name;
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001020
1021 /**
1022 * Parameter list
1023 *
1024 * @var array
1025 */
Andrey Andreevc8709832012-04-04 13:43:53 +03001026 public $params = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001027
1028 /**
1029 * XH?
1030 *
1031 * @var array
1032 */
Andrey Andreevc8709832012-04-04 13:43:53 +03001033 public $xh = array();
Derek Allard2067d1a2008-11-13 22:59:24 +00001034
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001035 // --------------------------------------------------------------------
1036
Andrey Andreevc8709832012-04-04 13:43:53 +03001037 /**
1038 * Constructor
1039 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001040 * @param string $method
1041 * @param array $pars
Andrey Andreevc8709832012-04-04 13:43:53 +03001042 * @return void
1043 */
1044 public function __construct($method, $pars = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001045 {
Greg Akera9263282010-11-10 15:26:43 -06001046 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +02001047
Derek Allard2067d1a2008-11-13 22:59:24 +00001048 $this->method_name = $method;
Derek Jones33559102009-02-02 18:50:38 +00001049 if (is_array($pars) && count($pars) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001050 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001051 for ($i = 0, $c = count($pars); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001052 {
1053 // $pars[$i] = XML_RPC_Values
1054 $this->params[] = $pars[$i];
1055 }
1056 }
1057 }
Barry Mienydd671972010-10-04 16:33:58 +02001058
Andrey Andreevc8709832012-04-04 13:43:53 +03001059 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001060
Andrey Andreevc8709832012-04-04 13:43:53 +03001061 /**
1062 * Create Payload to Send
1063 *
1064 * @return void
1065 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001066 public function createPayload()
Derek Allard2067d1a2008-11-13 22:59:24 +00001067 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001068 $this->payload = '<?xml version="1.0"?'.">\r\n<methodCall>\r\n"
1069 .'<methodName>'.$this->method_name."</methodName>\r\n"
1070 ."<params>\r\n";
Barry Mienydd671972010-10-04 16:33:58 +02001071
Andrey Andreeva30faf92011-12-25 18:15:34 +02001072 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001073 {
1074 // $p = XML_RPC_Values
1075 $p = $this->params[$i];
1076 $this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n";
1077 }
Barry Mienydd671972010-10-04 16:33:58 +02001078
Derek Allard2067d1a2008-11-13 22:59:24 +00001079 $this->payload .= "</params>\r\n</methodCall>\r\n";
1080 }
Barry Mienydd671972010-10-04 16:33:58 +02001081
Andrey Andreevc8709832012-04-04 13:43:53 +03001082 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001083
Andrey Andreevc8709832012-04-04 13:43:53 +03001084 /**
1085 * Parse External XML-RPC Server's Response
1086 *
1087 * @param resource
1088 * @return object
1089 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001090 public function parseResponse($fp)
Derek Allard2067d1a2008-11-13 22:59:24 +00001091 {
1092 $data = '';
Barry Mienydd671972010-10-04 16:33:58 +02001093
Pascal Kriete14287f32011-02-14 13:39:34 -05001094 while ($datum = fread($fp, 4096))
Derek Allard2067d1a2008-11-13 22:59:24 +00001095 {
1096 $data .= $datum;
1097 }
Barry Mienydd671972010-10-04 16:33:58 +02001098
Andrey Andreevc8709832012-04-04 13:43:53 +03001099 // Display HTTP content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +00001100 if ($this->debug === TRUE)
1101 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001102 echo "<pre>---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n</pre>";
Derek Allard2067d1a2008-11-13 22:59:24 +00001103 }
Barry Mienydd671972010-10-04 16:33:58 +02001104
Andrey Andreevc8709832012-04-04 13:43:53 +03001105 // Check for data
Andrey Andreeva30faf92011-12-25 18:15:34 +02001106 if ($data === '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001107 {
1108 error_log($this->xmlrpcstr['no_data']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001109 return new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001110 }
Barry Mienydd671972010-10-04 16:33:58 +02001111
Andrey Andreevc8709832012-04-04 13:43:53 +03001112 // Check for HTTP 200 Response
Andrey Andreev3dad2e72012-06-14 15:10:56 +03001113 if (strpos($data, 'HTTP') === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
Derek Allard2067d1a2008-11-13 22:59:24 +00001114 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001115 $errstr = substr($data, 0, strpos($data, "\n")-1);
1116 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');
Derek Allard2067d1a2008-11-13 22:59:24 +00001117 }
Barry Mienydd671972010-10-04 16:33:58 +02001118
Derek Allard2067d1a2008-11-13 22:59:24 +00001119 //-------------------------------------
vkeranovb497d2b2012-11-23 23:27:33 +02001120 // Create and Set Up XML Parser
Derek Allard2067d1a2008-11-13 22:59:24 +00001121 //-------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001122
Derek Allard2067d1a2008-11-13 22:59:24 +00001123 $parser = xml_parser_create($this->xmlrpc_defencoding);
1124
Andrey Andreeva30faf92011-12-25 18:15:34 +02001125 $this->xh[$parser] = array(
Andrey Andreevc8709832012-04-04 13:43:53 +03001126 'isf' => 0,
1127 'ac' => '',
1128 'headers' => array(),
1129 'stack' => array(),
1130 'valuestack' => array(),
1131 'isf_reason' => 0
Andrey Andreeva30faf92011-12-25 18:15:34 +02001132 );
Derek Allard2067d1a2008-11-13 22:59:24 +00001133
1134 xml_set_object($parser, $this);
Andrey Andreevc8709832012-04-04 13:43:53 +03001135 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +00001136 xml_set_element_handler($parser, 'open_tag', 'closing_tag');
1137 xml_set_character_data_handler($parser, 'character_data');
1138 //xml_set_default_handler($parser, 'default_handler');
1139
Andrey Andreevc8709832012-04-04 13:43:53 +03001140 // Get headers
Derek Allard2067d1a2008-11-13 22:59:24 +00001141 $lines = explode("\r\n", $data);
1142 while (($line = array_shift($lines)))
1143 {
1144 if (strlen($line) < 1)
1145 {
1146 break;
1147 }
1148 $this->xh[$parser]['headers'][] = $line;
1149 }
1150 $data = implode("\r\n", $lines);
Barry Mienydd671972010-10-04 16:33:58 +02001151
Andrey Andreevc8709832012-04-04 13:43:53 +03001152 // Parse XML data
Derek Jones33559102009-02-02 18:50:38 +00001153 if ( ! xml_parse($parser, $data, count($data)))
Derek Allard2067d1a2008-11-13 22:59:24 +00001154 {
1155 $errstr = sprintf('XML error: %s at line %d',
Andrey Andreevc8709832012-04-04 13:43:53 +03001156 xml_error_string(xml_get_error_code($parser)),
1157 xml_get_current_line_number($parser));
vkeranovb497d2b2012-11-23 23:27:33 +02001158
Derek Allard2067d1a2008-11-13 22:59:24 +00001159 $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
1160 xml_parser_free($parser);
1161 return $r;
1162 }
1163 xml_parser_free($parser);
Barry Mienydd671972010-10-04 16:33:58 +02001164
Andrey Andreevc8709832012-04-04 13:43:53 +03001165 // Got ourselves some badness, it seems
Derek Allard2067d1a2008-11-13 22:59:24 +00001166 if ($this->xh[$parser]['isf'] > 1)
1167 {
1168 if ($this->debug === TRUE)
1169 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001170 echo "---Invalid Return---\n".$this->xh[$parser]['isf_reason']."---Invalid Return---\n\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001171 }
Barry Mienydd671972010-10-04 16:33:58 +02001172
Andrey Andreevc8709832012-04-04 13:43:53 +03001173 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 +00001174 }
1175 elseif ( ! is_object($this->xh[$parser]['value']))
1176 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001177 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 +00001178 }
Barry Mienydd671972010-10-04 16:33:58 +02001179
Andrey Andreevc8709832012-04-04 13:43:53 +03001180 // Display XML content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +00001181 if ($this->debug === TRUE)
1182 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001183 echo '<pre>';
Barry Mienydd671972010-10-04 16:33:58 +02001184
Derek Allard2067d1a2008-11-13 22:59:24 +00001185 if (count($this->xh[$parser]['headers'] > 0))
1186 {
1187 echo "---HEADERS---\n";
1188 foreach ($this->xh[$parser]['headers'] as $header)
1189 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001190 echo $header."\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001191 }
1192 echo "---END HEADERS---\n\n";
1193 }
Barry Mienydd671972010-10-04 16:33:58 +02001194
Andrey Andreeva30faf92011-12-25 18:15:34 +02001195 echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n---PARSED---\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001196 var_dump($this->xh[$parser]['value']);
1197 echo "\n---END PARSED---</pre>";
1198 }
Barry Mienydd671972010-10-04 16:33:58 +02001199
Andrey Andreevc8709832012-04-04 13:43:53 +03001200 // Send response
Derek Allard2067d1a2008-11-13 22:59:24 +00001201 $v = $this->xh[$parser]['value'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001202 if ($this->xh[$parser]['isf'])
1203 {
1204 $errno_v = $v->me['struct']['faultCode'];
1205 $errstr_v = $v->me['struct']['faultString'];
1206 $errno = $errno_v->scalarval();
1207
Alex Bilbied261b1e2012-06-02 11:12:16 +01001208 if ($errno === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001209 {
1210 // FAULT returned, errno needs to reflect that
1211 $errno = -1;
1212 }
1213
1214 $r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
1215 }
1216 else
1217 {
1218 $r = new XML_RPC_Response($v);
1219 }
1220
1221 $r->headers = $this->xh[$parser]['headers'];
1222 return $r;
1223 }
Barry Mienydd671972010-10-04 16:33:58 +02001224
Andrey Andreevc8709832012-04-04 13:43:53 +03001225 // --------------------------------------------------------------------
1226
Derek Allard2067d1a2008-11-13 22:59:24 +00001227 // ------------------------------------
Derek Jones37f4b9c2011-07-01 17:56:50 -05001228 // Begin Return Message Parsing section
Derek Allard2067d1a2008-11-13 22:59:24 +00001229 // ------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001230
Derek Allard2067d1a2008-11-13 22:59:24 +00001231 // quick explanation of components:
Derek Jones37f4b9c2011-07-01 17:56:50 -05001232 // ac - used to accumulate values
1233 // isf - used to indicate a fault
1234 // lv - used to indicate "looking for a value": implements
Derek Allard2067d1a2008-11-13 22:59:24 +00001235 // the logic to allow values with no types to be strings
Derek Jones37f4b9c2011-07-01 17:56:50 -05001236 // params - used to store parameters in method calls
1237 // method - used to store method name
Derek Allard2067d1a2008-11-13 22:59:24 +00001238 // stack - array with parent tree of the xml element,
1239 // used to validate the nesting of elements
1240
Andrey Andreevc8709832012-04-04 13:43:53 +03001241 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001242
Andrey Andreevc8709832012-04-04 13:43:53 +03001243 /**
1244 * Start Element Handler
1245 *
1246 * @param string
1247 * @param string
1248 * @return void
1249 */
1250 public function open_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001251 {
1252 // If invalid nesting, then return
1253 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001254
Derek Allard2067d1a2008-11-13 22:59:24 +00001255 // Evaluate and check for correct nesting of XML elements
Alex Bilbied261b1e2012-06-02 11:12:16 +01001256 if (count($this->xh[$the_parser]['stack']) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001257 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001258 if ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')
Derek Allard2067d1a2008-11-13 22:59:24 +00001259 {
1260 $this->xh[$the_parser]['isf'] = 2;
1261 $this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
1262 return;
1263 }
1264 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001265 // not top level element: see if parent is OK
1266 elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +00001267 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001268 $this->xh[$the_parser]['isf'] = 2;
vkeranovb497d2b2012-11-23 23:27:33 +02001269 $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 +03001270 return;
Derek Allard2067d1a2008-11-13 22:59:24 +00001271 }
Barry Mienydd671972010-10-04 16:33:58 +02001272
Andrey Andreevc8709832012-04-04 13:43:53 +03001273 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001274 {
1275 case 'STRUCT':
1276 case 'ARRAY':
1277 // Creates array for child elements
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001278 $cur_val = array('value' => array(), 'type' => $name);
Derek Allard2067d1a2008-11-13 22:59:24 +00001279 array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
Andrey Andreevc8709832012-04-04 13:43:53 +03001280 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001281 case 'METHODNAME':
1282 case 'NAME':
1283 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +03001284 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001285 case 'FAULT':
1286 $this->xh[$the_parser]['isf'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +03001287 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001288 case 'PARAM':
Pascal Kriete8761ef52011-02-14 13:13:52 -05001289 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +03001290 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001291 case 'VALUE':
1292 $this->xh[$the_parser]['vt'] = 'value';
1293 $this->xh[$the_parser]['ac'] = '';
1294 $this->xh[$the_parser]['lv'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +03001295 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001296 case 'I4':
1297 case 'INT':
1298 case 'STRING':
1299 case 'BOOLEAN':
1300 case 'DOUBLE':
1301 case 'DATETIME.ISO8601':
1302 case 'BASE64':
Alex Bilbied261b1e2012-06-02 11:12:16 +01001303 if ($this->xh[$the_parser]['vt'] !== 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +00001304 {
1305 //two data elements inside a value: an error occurred!
1306 $this->xh[$the_parser]['isf'] = 2;
vkeranovb497d2b2012-11-23 23:27:33 +02001307 $this->xh[$the_parser]['isf_reason'] = 'There is a '.$name.' element following a '
Andrey Andreevc8709832012-04-04 13:43:53 +03001308 .$this->xh[$the_parser]['vt'].' element inside a single value';
Derek Allard2067d1a2008-11-13 22:59:24 +00001309 return;
1310 }
Barry Mienydd671972010-10-04 16:33:58 +02001311
Derek Allard2067d1a2008-11-13 22:59:24 +00001312 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +03001313 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001314 case 'MEMBER':
1315 // Set name of <member> to nothing to prevent errors later if no <name> is found
1316 $this->xh[$the_parser]['valuestack'][0]['name'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001317
Derek Allard2067d1a2008-11-13 22:59:24 +00001318 // Set NULL value to check to see if value passed for this param/member
Pascal Kriete8761ef52011-02-14 13:13:52 -05001319 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +03001320 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001321 case 'DATA':
1322 case 'METHODCALL':
1323 case 'METHODRESPONSE':
1324 case 'PARAMS':
1325 // valid elements that add little to processing
Andrey Andreevc8709832012-04-04 13:43:53 +03001326 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001327 default:
1328 /// An Invalid Element is Found, so we have trouble
1329 $this->xh[$the_parser]['isf'] = 2;
Andrey Andreevc8709832012-04-04 13:43:53 +03001330 $this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;
1331 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001332 }
Barry Mienydd671972010-10-04 16:33:58 +02001333
Derek Allard2067d1a2008-11-13 22:59:24 +00001334 // Add current element name to stack, to allow validation of nesting
1335 array_unshift($this->xh[$the_parser]['stack'], $name);
1336
Alex Bilbied261b1e2012-06-02 11:12:16 +01001337 $name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001338 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001339
Andrey Andreevc8709832012-04-04 13:43:53 +03001340 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001341
Andrey Andreevc8709832012-04-04 13:43:53 +03001342 /**
1343 * End Element Handler
1344 *
1345 * @param string
1346 * @param string
1347 * @return void
1348 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001349 public function closing_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001350 {
1351 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001352
Derek Allard2067d1a2008-11-13 22:59:24 +00001353 // Remove current element from stack and set variable
1354 // NOTE: If the XML validates, then we do not have to worry about
Andrey Andreevc8709832012-04-04 13:43:53 +03001355 // the opening and closing of elements. Nesting is checked on the opening
Derek Allard2067d1a2008-11-13 22:59:24 +00001356 // tag so we be safe there as well.
Barry Mienydd671972010-10-04 16:33:58 +02001357
Derek Allard2067d1a2008-11-13 22:59:24 +00001358 $curr_elem = array_shift($this->xh[$the_parser]['stack']);
Barry Mienydd671972010-10-04 16:33:58 +02001359
Andrey Andreevc8709832012-04-04 13:43:53 +03001360 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001361 {
1362 case 'STRUCT':
1363 case 'ARRAY':
1364 $cur_val = array_shift($this->xh[$the_parser]['valuestack']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001365 $this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();
Derek Allard2067d1a2008-11-13 22:59:24 +00001366 $this->xh[$the_parser]['vt'] = strtolower($name);
Andrey Andreevc8709832012-04-04 13:43:53 +03001367 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001368 case 'NAME':
1369 $this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
Andrey Andreevc8709832012-04-04 13:43:53 +03001370 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001371 case 'BOOLEAN':
1372 case 'I4':
1373 case 'INT':
1374 case 'STRING':
1375 case 'DOUBLE':
1376 case 'DATETIME.ISO8601':
1377 case 'BASE64':
1378 $this->xh[$the_parser]['vt'] = strtolower($name);
Barry Mienydd671972010-10-04 16:33:58 +02001379
Alex Bilbied261b1e2012-06-02 11:12:16 +01001380 if ($name === 'STRING')
Derek Allard2067d1a2008-11-13 22:59:24 +00001381 {
1382 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1383 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001384 elseif ($name === 'DATETIME.ISO8601')
Derek Allard2067d1a2008-11-13 22:59:24 +00001385 {
1386 $this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime;
1387 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1388 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001389 elseif ($name === 'BASE64')
Derek Allard2067d1a2008-11-13 22:59:24 +00001390 {
1391 $this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
1392 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001393 elseif ($name === 'BOOLEAN')
Derek Allard2067d1a2008-11-13 22:59:24 +00001394 {
1395 // Translated BOOLEAN values to TRUE AND FALSE
Andrey Andreevc8709832012-04-04 13:43:53 +03001396 $this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001397 }
1398 elseif ($name=='DOUBLE')
1399 {
1400 // we have a DOUBLE
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('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])
1403 ? (float) $this->xh[$the_parser]['ac']
1404 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001405 }
1406 else
1407 {
1408 // we have an I4/INT
1409 // we must check that only 0123456789-<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001410 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])
George Petsagourakis306b3782012-05-02 20:31:08 +03001411 ? (int) $this->xh[$the_parser]['ac']
Andrey Andreevc8709832012-04-04 13:43:53 +03001412 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001413 }
1414 $this->xh[$the_parser]['ac'] = '';
1415 $this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
Andrey Andreevc8709832012-04-04 13:43:53 +03001416 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001417 case 'VALUE':
1418 // This if() detects if no scalar was inside <VALUE></VALUE>
vkeranovb497d2b2012-11-23 23:27:33 +02001419 if ($this->xh[$the_parser]['vt'] == 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +00001420 {
1421 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1422 $this->xh[$the_parser]['vt'] = $this->xmlrpcString;
1423 }
Barry Mienydd671972010-10-04 16:33:58 +02001424
Derek Allard2067d1a2008-11-13 22:59:24 +00001425 // build the XML-RPC value out of the data received, and substitute it
1426 $temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
Barry Mienydd671972010-10-04 16:33:58 +02001427
Alex Bilbied261b1e2012-06-02 11:12:16 +01001428 if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')
Derek Allard2067d1a2008-11-13 22:59:24 +00001429 {
1430 // Array
1431 $this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
1432 }
1433 else
1434 {
1435 // Struct
1436 $this->xh[$the_parser]['value'] = $temp;
1437 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001438 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001439 case 'MEMBER':
Andrey Andreevc8709832012-04-04 13:43:53 +03001440 $this->xh[$the_parser]['ac'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001441
Derek Allard2067d1a2008-11-13 22:59:24 +00001442 // If value add to array in the stack for the last element built
1443 if ($this->xh[$the_parser]['value'])
1444 {
1445 $this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
1446 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001447 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001448 case 'DATA':
Andrey Andreevc8709832012-04-04 13:43:53 +03001449 $this->xh[$the_parser]['ac'] = '';
1450 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001451 case 'PARAM':
1452 if ($this->xh[$the_parser]['value'])
1453 {
1454 $this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
1455 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001456 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001457 case 'METHODNAME':
1458 $this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001459 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001460 case 'PARAMS':
1461 case 'FAULT':
1462 case 'METHODCALL':
1463 case 'METHORESPONSE':
1464 // We're all good kids with nuthin' to do
Andrey Andreevc8709832012-04-04 13:43:53 +03001465 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001466 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001467 // End of an Invalid Element. Taken care of during the opening tag though
1468 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001469 }
1470 }
1471
Andrey Andreevc8709832012-04-04 13:43:53 +03001472 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001473
Andrey Andreevc8709832012-04-04 13:43:53 +03001474 /**
1475 * Parse character data
1476 *
1477 * @param string
1478 * @param string
1479 * @return void
1480 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001481 public function character_data($the_parser, $data)
Derek Allard2067d1a2008-11-13 22:59:24 +00001482 {
1483 if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
Barry Mienydd671972010-10-04 16:33:58 +02001484
Derek Allard2067d1a2008-11-13 22:59:24 +00001485 // If a value has not been found
Alex Bilbied261b1e2012-06-02 11:12:16 +01001486 if ($this->xh[$the_parser]['lv'] !== 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001487 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001488 if ($this->xh[$the_parser]['lv'] === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001489 {
1490 $this->xh[$the_parser]['lv'] = 2; // Found a value
1491 }
Barry Mienydd671972010-10-04 16:33:58 +02001492
Andrey Andreevc8709832012-04-04 13:43:53 +03001493 if ( ! isset($this->xh[$the_parser]['ac']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001494 {
1495 $this->xh[$the_parser]['ac'] = '';
1496 }
Barry Mienydd671972010-10-04 16:33:58 +02001497
Derek Allard2067d1a2008-11-13 22:59:24 +00001498 $this->xh[$the_parser]['ac'] .= $data;
1499 }
1500 }
Barry Mienydd671972010-10-04 16:33:58 +02001501
Andrey Andreevc8709832012-04-04 13:43:53 +03001502 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001503
Andrey Andreevc8709832012-04-04 13:43:53 +03001504 /**
1505 * Add parameter
1506 *
1507 * @param mixed
1508 * @return void
1509 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001510 public function addParam($par)
1511 {
1512 $this->params[] = $par;
1513 }
Barry Mienydd671972010-10-04 16:33:58 +02001514
Andrey Andreevc8709832012-04-04 13:43:53 +03001515 // --------------------------------------------------------------------
1516
1517 /**
1518 * Output parameters
1519 *
Andrey Andreeve417f042014-01-08 14:48:01 +02001520 * @param array $array
Andrey Andreevc8709832012-04-04 13:43:53 +03001521 * @return array
1522 */
Andrey Andreeve417f042014-01-08 14:48:01 +02001523 public function output_parameters(array $array = array())
Derek Allard2067d1a2008-11-13 22:59:24 +00001524 {
Barry Mienydd671972010-10-04 16:33:58 +02001525 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +02001526
Andrey Andreeve417f042014-01-08 14:48:01 +02001527 if ( ! empty($array))
Derek Allard2067d1a2008-11-13 22:59:24 +00001528 {
1529 while (list($key) = each($array))
1530 {
1531 if (is_array($array[$key]))
1532 {
1533 $array[$key] = $this->output_parameters($array[$key]);
1534 }
Andrey Andreeve417f042014-01-08 14:48:01 +02001535 elseif ($key !== 'bits' && $this->xss_clean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001536 {
Derek Jonesa9647e82010-03-02 22:59:07 -06001537 // 'bits' is for the MetaWeblog API image bits
1538 // @todo - this needs to be made more general purpose
Andrey Andreeve417f042014-01-08 14:48:01 +02001539 $array[$key] = $CI->security->xss_clean($array[$key]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001540 }
1541 }
Barry Mienydd671972010-10-04 16:33:58 +02001542
Andrey Andreevc8709832012-04-04 13:43:53 +03001543 return $array;
Derek Allard2067d1a2008-11-13 22:59:24 +00001544 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001545
1546 $parameters = array();
1547
1548 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001549 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001550 $a_param = $this->decode_message($this->params[$i]);
Barry Mienydd671972010-10-04 16:33:58 +02001551
Andrey Andreevc8709832012-04-04 13:43:53 +03001552 if (is_array($a_param))
Derek Allard2067d1a2008-11-13 22:59:24 +00001553 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001554 $parameters[] = $this->output_parameters($a_param);
1555 }
1556 else
1557 {
1558 $parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;
Barry Mienydd671972010-10-04 16:33:58 +02001559 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001560 }
Barry Mienydd671972010-10-04 16:33:58 +02001561
Derek Allard2067d1a2008-11-13 22:59:24 +00001562 return $parameters;
1563 }
Barry Mienydd671972010-10-04 16:33:58 +02001564
Andrey Andreevc8709832012-04-04 13:43:53 +03001565 // --------------------------------------------------------------------
1566
1567 /**
1568 * Decode message
1569 *
1570 * @param object
1571 * @return mixed
1572 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001573 public function decode_message($param)
Derek Allard2067d1a2008-11-13 22:59:24 +00001574 {
1575 $kind = $param->kindOf();
1576
Alex Bilbied261b1e2012-06-02 11:12:16 +01001577 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +00001578 {
1579 return $param->scalarval();
1580 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001581 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +00001582 {
1583 reset($param->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001584 $b = current($param->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001585 $arr = array();
1586
Andrey Andreevc8709832012-04-04 13:43:53 +03001587 for ($i = 0, $c = count($b); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001588 {
1589 $arr[] = $this->decode_message($param->me['array'][$i]);
1590 }
Barry Mienydd671972010-10-04 16:33:58 +02001591
Derek Allard2067d1a2008-11-13 22:59:24 +00001592 return $arr;
1593 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001594 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +00001595 {
1596 reset($param->me['struct']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001597 $arr = array();
1598
Pascal Kriete14287f32011-02-14 13:39:34 -05001599 while (list($key,$value) = each($param->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001600 {
1601 $arr[$key] = $this->decode_message($value);
1602 }
Barry Mienydd671972010-10-04 16:33:58 +02001603
Derek Allard2067d1a2008-11-13 22:59:24 +00001604 return $arr;
1605 }
1606 }
Barry Mienydd671972010-10-04 16:33:58 +02001607
Andrey Andreevc8709832012-04-04 13:43:53 +03001608} // END XML_RPC_Message Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001609
1610/**
1611 * XML-RPC Values class
1612 *
1613 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -05001614 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +00001615 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
1616 */
1617class XML_RPC_Values extends CI_Xmlrpc
1618{
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001619 /**
1620 * Value data
1621 *
1622 * @var array
1623 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001624 public $me = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001625
1626 /**
1627 * Value type
1628 *
1629 * @var int
1630 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001631 public $mytype = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001632
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001633 // --------------------------------------------------------------------
1634
Andrey Andreevc8709832012-04-04 13:43:53 +03001635 /**
1636 * Constructor
1637 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001638 * @param mixed $val
1639 * @param string $type
Andrey Andreevc8709832012-04-04 13:43:53 +03001640 * @return void
1641 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001642 public function __construct($val = -1, $type = '')
Barry Mienydd671972010-10-04 16:33:58 +02001643 {
Greg Akera9263282010-11-10 15:26:43 -06001644 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +02001645
Alex Bilbied261b1e2012-06-02 11:12:16 +01001646 if ($val !== -1 OR $type !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001647 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001648 $type = $type === '' ? 'string' : $type;
Barry Mienydd671972010-10-04 16:33:58 +02001649
Dimitar740480a2012-10-05 13:24:59 +03001650 if ($this->xmlrpcTypes[$type] == 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001651 {
vkeranovb497d2b2012-11-23 23:27:33 +02001652 $this->addScalar($val, $type);
Derek Allard2067d1a2008-11-13 22:59:24 +00001653 }
Dimitar740480a2012-10-05 13:24:59 +03001654 elseif ($this->xmlrpcTypes[$type] == 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001655 {
1656 $this->addArray($val);
1657 }
Dimitar740480a2012-10-05 13:24:59 +03001658 elseif ($this->xmlrpcTypes[$type] == 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001659 {
1660 $this->addStruct($val);
1661 }
1662 }
1663 }
1664
Andrey Andreevc8709832012-04-04 13:43:53 +03001665 // --------------------------------------------------------------------
1666
1667 /**
1668 * Add scalar value
1669 *
1670 * @param scalar
1671 * @param string
1672 * @return int
1673 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001674 public function addScalar($val, $type = 'string')
Derek Allard2067d1a2008-11-13 22:59:24 +00001675 {
1676 $typeof = $this->xmlrpcTypes[$type];
Barry Mienydd671972010-10-04 16:33:58 +02001677
Alex Bilbied261b1e2012-06-02 11:12:16 +01001678 if ($this->mytype === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001679 {
1680 echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
1681 return 0;
1682 }
Barry Mienydd671972010-10-04 16:33:58 +02001683
Dimitar740480a2012-10-05 13:24:59 +03001684 if ($typeof != 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001685 {
1686 echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';
1687 return 0;
1688 }
1689
Alex Bilbied261b1e2012-06-02 11:12:16 +01001690 if ($type === $this->xmlrpcBoolean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001691 {
Andrey Andreev3f3f1352012-09-05 16:39:28 +03001692 $val = (int) (strcasecmp($val, 'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
Derek Allard2067d1a2008-11-13 22:59:24 +00001693 }
1694
Alex Bilbied261b1e2012-06-02 11:12:16 +01001695 if ($this->mytype === 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001696 {
1697 // adding to an array here
1698 $ar = $this->me['array'];
1699 $ar[] = new XML_RPC_Values($val, $type);
1700 $this->me['array'] = $ar;
1701 }
1702 else
1703 {
1704 // a scalar, so set the value and remember we're scalar
1705 $this->me[$type] = $val;
1706 $this->mytype = $typeof;
1707 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001708
Derek Allard2067d1a2008-11-13 22:59:24 +00001709 return 1;
1710 }
1711
Andrey Andreevc8709832012-04-04 13:43:53 +03001712 // --------------------------------------------------------------------
1713
1714 /**
1715 * Add array value
1716 *
1717 * @param array
1718 * @return int
1719 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001720 public function addArray($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001721 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001722 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001723 {
Andrey Andreev3ca060a2013-11-27 16:30:31 +02001724 echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
Derek Allard2067d1a2008-11-13 22:59:24 +00001725 return 0;
1726 }
1727
1728 $this->mytype = $this->xmlrpcTypes['array'];
1729 $this->me['array'] = $vals;
1730 return 1;
1731 }
1732
Andrey Andreevc8709832012-04-04 13:43:53 +03001733 // --------------------------------------------------------------------
1734
1735 /**
1736 * Add struct value
1737 *
1738 * @param object
1739 * @return int
1740 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001741 public function addStruct($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001742 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001743 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001744 {
Andrey Andreev3ca060a2013-11-27 16:30:31 +02001745 echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
Derek Allard2067d1a2008-11-13 22:59:24 +00001746 return 0;
1747 }
1748 $this->mytype = $this->xmlrpcTypes['struct'];
1749 $this->me['struct'] = $vals;
1750 return 1;
1751 }
1752
Andrey Andreevc8709832012-04-04 13:43:53 +03001753 // --------------------------------------------------------------------
1754
1755 /**
1756 * Get value type
1757 *
1758 * @return string
1759 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001760 public function kindOf()
Derek Allard2067d1a2008-11-13 22:59:24 +00001761 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001762 switch ($this->mytype)
Derek Allard2067d1a2008-11-13 22:59:24 +00001763 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001764 case 3: return 'struct';
1765 case 2: return 'array';
1766 case 1: return 'scalar';
1767 default: return 'undef';
Derek Allard2067d1a2008-11-13 22:59:24 +00001768 }
1769 }
1770
Andrey Andreevc8709832012-04-04 13:43:53 +03001771 // --------------------------------------------------------------------
1772
1773 /**
1774 * Serialize data
1775 *
1776 * @param string
1777 * @param mixed
1778 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001779 public function serializedata($typ, $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001780 {
1781 $rs = '';
Derek Jonesa9647e82010-03-02 22:59:07 -06001782
Andrey Andreevc8709832012-04-04 13:43:53 +03001783 switch ($this->xmlrpcTypes[$typ])
Derek Allard2067d1a2008-11-13 22:59:24 +00001784 {
1785 case 3:
1786 // struct
1787 $rs .= "<struct>\n";
1788 reset($val);
Pascal Kriete14287f32011-02-14 13:39:34 -05001789 while (list($key2, $val2) = each($val))
Derek Allard2067d1a2008-11-13 22:59:24 +00001790 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001791 $rs .= "<member>\n<name>{$key2}</name>\n".$this->serializeval($val2)."</member>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001792 }
1793 $rs .= '</struct>';
Andrey Andreevc8709832012-04-04 13:43:53 +03001794 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001795 case 2:
1796 // array
1797 $rs .= "<array>\n<data>\n";
Andrey Andreevc8709832012-04-04 13:43:53 +03001798 for ($i = 0, $c = count($val); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001799 {
1800 $rs .= $this->serializeval($val[$i]);
1801 }
Andrey Andreeva30faf92011-12-25 18:15:34 +02001802 $rs .= "</data>\n</array>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001803 break;
1804 case 1:
1805 // others
1806 switch ($typ)
1807 {
1808 case $this->xmlrpcBase64:
Andrey Andreevc8709832012-04-04 13:43:53 +03001809 $rs .= '<'.$typ.'>'.base64_encode( (string) $val).'</'.$typ.">\n";
1810 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001811 case $this->xmlrpcBoolean:
Andrey Andreevc8709832012-04-04 13:43:53 +03001812 $rs .= '<'.$typ.'>'.( (bool) $val ? '1' : '0').'</'.$typ.">\n";
1813 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001814 case $this->xmlrpcString:
Andrey Andreevc8709832012-04-04 13:43:53 +03001815 $rs .= '<'.$typ.'>'.htmlspecialchars( (string) $val).'</'.$typ.">\n";
1816 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001817 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001818 $rs .= '<'.$typ.'>'.$val.'</'.$typ.">\n";
1819 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001820 }
1821 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001822 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001823 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001824
Derek Allard2067d1a2008-11-13 22:59:24 +00001825 return $rs;
1826 }
1827
Andrey Andreevc8709832012-04-04 13:43:53 +03001828 // --------------------------------------------------------------------
1829
1830 /**
1831 * Serialize class
1832 *
1833 * @return string
1834 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001835 public function serialize_class()
Derek Allard2067d1a2008-11-13 22:59:24 +00001836 {
1837 return $this->serializeval($this);
1838 }
1839
Andrey Andreevc8709832012-04-04 13:43:53 +03001840 // --------------------------------------------------------------------
1841
1842 /**
1843 * Serialize value
1844 *
1845 * @param object
1846 * @return string
1847 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001848 public function serializeval($o)
Derek Allard2067d1a2008-11-13 22:59:24 +00001849 {
1850 $ar = $o->me;
1851 reset($ar);
Barry Mienydd671972010-10-04 16:33:58 +02001852
Derek Allard2067d1a2008-11-13 22:59:24 +00001853 list($typ, $val) = each($ar);
Andrey Andreeva30faf92011-12-25 18:15:34 +02001854 return "<value>\n".$this->serializedata($typ, $val)."</value>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001855 }
Barry Mienydd671972010-10-04 16:33:58 +02001856
Andrey Andreevc8709832012-04-04 13:43:53 +03001857 // --------------------------------------------------------------------
1858
1859 /**
1860 * Scalar value
1861 *
1862 * @return mixed
1863 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001864 public function scalarval()
Derek Allard2067d1a2008-11-13 22:59:24 +00001865 {
1866 reset($this->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001867 return current($this->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001868 }
1869
Andrey Andreevc8709832012-04-04 13:43:53 +03001870 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001871
Andrey Andreevc8709832012-04-04 13:43:53 +03001872 /**
1873 * Encode time in ISO-8601 form.
1874 * Useful for sending time in XML-RPC
1875 *
1876 * @param int unix timestamp
1877 * @param bool
1878 * @return string
1879 */
1880 public function iso8601_encode($time, $utc = FALSE)
Barry Mienydd671972010-10-04 16:33:58 +02001881 {
Andrey Andreev62090152011-12-30 12:49:27 +02001882 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 +00001883 }
Barry Mienydd671972010-10-04 16:33:58 +02001884
Andrey Andreevc8709832012-04-04 13:43:53 +03001885} // END XML_RPC_Values Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001886
1887/* End of file Xmlrpc.php */
Andrey Andreevc5a7c5f2013-07-17 20:10:09 +03001888/* Location: ./system/libraries/Xmlrpc.php */