blob: d0f6d83b392806f388686b27e235a374ddde47b0 [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);
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001124 $pname = (string) $parser;
1125 $this->xh[$pname] = array(
1126 'isf' => 0,
1127 'ac' => '',
1128 'headers' => array(),
1129 'stack' => array(),
1130 'valuestack' => array(),
1131 'isf_reason' => 0
1132 );
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 }
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001148 $this->xh[$pname]['headers'][] = $line;
Derek Allard2067d1a2008-11-13 22:59:24 +00001149 }
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
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001166 if ($this->xh[$pname]['isf'] > 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001167 {
1168 if ($this->debug === TRUE)
1169 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001170 echo "---Invalid Return---\n".$this->xh[$pname]['isf_reason']."---Invalid Return---\n\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001171 }
Barry Mienydd671972010-10-04 16:33:58 +02001172
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001173 return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['isf_reason']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001174 }
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001175 elseif ( ! is_object($this->xh[$pname]['value']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001176 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001177 return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['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
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001185 if (count($this->xh[$pname]['headers'] > 0))
Derek Allard2067d1a2008-11-13 22:59:24 +00001186 {
1187 echo "---HEADERS---\n";
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001188 foreach ($this->xh[$pname]['headers'] as $header)
Derek Allard2067d1a2008-11-13 22:59:24 +00001189 {
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";
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001196 var_dump($this->xh[$pname]['value']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001197 echo "\n---END PARSED---</pre>";
1198 }
Barry Mienydd671972010-10-04 16:33:58 +02001199
Andrey Andreevc8709832012-04-04 13:43:53 +03001200 // Send response
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001201 $v = $this->xh[$pname]['value'];
1202 if ($this->xh[$pname]['isf'])
Derek Allard2067d1a2008-11-13 22:59:24 +00001203 {
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
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001221 $r->headers = $this->xh[$pname]['headers'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001222 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 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001252 $the_parser = (string) $the_parser;
1253
Derek Allard2067d1a2008-11-13 22:59:24 +00001254 // If invalid nesting, then return
1255 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001256
Derek Allard2067d1a2008-11-13 22:59:24 +00001257 // Evaluate and check for correct nesting of XML elements
Alex Bilbied261b1e2012-06-02 11:12:16 +01001258 if (count($this->xh[$the_parser]['stack']) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001259 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001260 if ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')
Derek Allard2067d1a2008-11-13 22:59:24 +00001261 {
1262 $this->xh[$the_parser]['isf'] = 2;
1263 $this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
1264 return;
1265 }
1266 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001267 // not top level element: see if parent is OK
1268 elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +00001269 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001270 $this->xh[$the_parser]['isf'] = 2;
vkeranovb497d2b2012-11-23 23:27:33 +02001271 $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 +03001272 return;
Derek Allard2067d1a2008-11-13 22:59:24 +00001273 }
Barry Mienydd671972010-10-04 16:33:58 +02001274
Andrey Andreevc8709832012-04-04 13:43:53 +03001275 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001276 {
1277 case 'STRUCT':
1278 case 'ARRAY':
1279 // Creates array for child elements
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001280 $cur_val = array('value' => array(), 'type' => $name);
Derek Allard2067d1a2008-11-13 22:59:24 +00001281 array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
Andrey Andreevc8709832012-04-04 13:43:53 +03001282 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001283 case 'METHODNAME':
1284 case 'NAME':
1285 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +03001286 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001287 case 'FAULT':
1288 $this->xh[$the_parser]['isf'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +03001289 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001290 case 'PARAM':
Pascal Kriete8761ef52011-02-14 13:13:52 -05001291 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +03001292 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001293 case 'VALUE':
1294 $this->xh[$the_parser]['vt'] = 'value';
1295 $this->xh[$the_parser]['ac'] = '';
1296 $this->xh[$the_parser]['lv'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +03001297 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001298 case 'I4':
1299 case 'INT':
1300 case 'STRING':
1301 case 'BOOLEAN':
1302 case 'DOUBLE':
1303 case 'DATETIME.ISO8601':
1304 case 'BASE64':
Alex Bilbied261b1e2012-06-02 11:12:16 +01001305 if ($this->xh[$the_parser]['vt'] !== 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +00001306 {
1307 //two data elements inside a value: an error occurred!
1308 $this->xh[$the_parser]['isf'] = 2;
vkeranovb497d2b2012-11-23 23:27:33 +02001309 $this->xh[$the_parser]['isf_reason'] = 'There is a '.$name.' element following a '
Andrey Andreevc8709832012-04-04 13:43:53 +03001310 .$this->xh[$the_parser]['vt'].' element inside a single value';
Derek Allard2067d1a2008-11-13 22:59:24 +00001311 return;
1312 }
Barry Mienydd671972010-10-04 16:33:58 +02001313
Derek Allard2067d1a2008-11-13 22:59:24 +00001314 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +03001315 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001316 case 'MEMBER':
1317 // Set name of <member> to nothing to prevent errors later if no <name> is found
1318 $this->xh[$the_parser]['valuestack'][0]['name'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001319
Derek Allard2067d1a2008-11-13 22:59:24 +00001320 // Set NULL value to check to see if value passed for this param/member
Pascal Kriete8761ef52011-02-14 13:13:52 -05001321 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +03001322 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001323 case 'DATA':
1324 case 'METHODCALL':
1325 case 'METHODRESPONSE':
1326 case 'PARAMS':
1327 // valid elements that add little to processing
Andrey Andreevc8709832012-04-04 13:43:53 +03001328 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001329 default:
1330 /// An Invalid Element is Found, so we have trouble
1331 $this->xh[$the_parser]['isf'] = 2;
Andrey Andreevc8709832012-04-04 13:43:53 +03001332 $this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;
1333 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001334 }
Barry Mienydd671972010-10-04 16:33:58 +02001335
Derek Allard2067d1a2008-11-13 22:59:24 +00001336 // Add current element name to stack, to allow validation of nesting
1337 array_unshift($this->xh[$the_parser]['stack'], $name);
1338
Alex Bilbied261b1e2012-06-02 11:12:16 +01001339 $name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001340 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001341
Andrey Andreevc8709832012-04-04 13:43:53 +03001342 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001343
Andrey Andreevc8709832012-04-04 13:43:53 +03001344 /**
1345 * End Element Handler
1346 *
1347 * @param string
1348 * @param string
1349 * @return void
1350 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001351 public function closing_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001352 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001353 $the_parser = (string) $the_parser;
1354
Derek Allard2067d1a2008-11-13 22:59:24 +00001355 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001356
Derek Allard2067d1a2008-11-13 22:59:24 +00001357 // Remove current element from stack and set variable
1358 // NOTE: If the XML validates, then we do not have to worry about
Andrey Andreevc8709832012-04-04 13:43:53 +03001359 // the opening and closing of elements. Nesting is checked on the opening
Derek Allard2067d1a2008-11-13 22:59:24 +00001360 // tag so we be safe there as well.
Barry Mienydd671972010-10-04 16:33:58 +02001361
Derek Allard2067d1a2008-11-13 22:59:24 +00001362 $curr_elem = array_shift($this->xh[$the_parser]['stack']);
Barry Mienydd671972010-10-04 16:33:58 +02001363
Andrey Andreevc8709832012-04-04 13:43:53 +03001364 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001365 {
1366 case 'STRUCT':
1367 case 'ARRAY':
1368 $cur_val = array_shift($this->xh[$the_parser]['valuestack']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001369 $this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();
Derek Allard2067d1a2008-11-13 22:59:24 +00001370 $this->xh[$the_parser]['vt'] = strtolower($name);
Andrey Andreevc8709832012-04-04 13:43:53 +03001371 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001372 case 'NAME':
1373 $this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
Andrey Andreevc8709832012-04-04 13:43:53 +03001374 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001375 case 'BOOLEAN':
1376 case 'I4':
1377 case 'INT':
1378 case 'STRING':
1379 case 'DOUBLE':
1380 case 'DATETIME.ISO8601':
1381 case 'BASE64':
1382 $this->xh[$the_parser]['vt'] = strtolower($name);
Barry Mienydd671972010-10-04 16:33:58 +02001383
Alex Bilbied261b1e2012-06-02 11:12:16 +01001384 if ($name === 'STRING')
Derek Allard2067d1a2008-11-13 22:59:24 +00001385 {
1386 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1387 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001388 elseif ($name === 'DATETIME.ISO8601')
Derek Allard2067d1a2008-11-13 22:59:24 +00001389 {
1390 $this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime;
1391 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1392 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001393 elseif ($name === 'BASE64')
Derek Allard2067d1a2008-11-13 22:59:24 +00001394 {
1395 $this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
1396 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001397 elseif ($name === 'BOOLEAN')
Derek Allard2067d1a2008-11-13 22:59:24 +00001398 {
1399 // Translated BOOLEAN values to TRUE AND FALSE
Andrey Andreevc8709832012-04-04 13:43:53 +03001400 $this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001401 }
1402 elseif ($name=='DOUBLE')
1403 {
1404 // we have a DOUBLE
1405 // we must check that only 0123456789-.<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001406 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])
1407 ? (float) $this->xh[$the_parser]['ac']
1408 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001409 }
1410 else
1411 {
1412 // we have an I4/INT
1413 // we must check that only 0123456789-<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001414 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])
George Petsagourakis306b3782012-05-02 20:31:08 +03001415 ? (int) $this->xh[$the_parser]['ac']
Andrey Andreevc8709832012-04-04 13:43:53 +03001416 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001417 }
1418 $this->xh[$the_parser]['ac'] = '';
1419 $this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
Andrey Andreevc8709832012-04-04 13:43:53 +03001420 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001421 case 'VALUE':
1422 // This if() detects if no scalar was inside <VALUE></VALUE>
vkeranovb497d2b2012-11-23 23:27:33 +02001423 if ($this->xh[$the_parser]['vt'] == 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +00001424 {
1425 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1426 $this->xh[$the_parser]['vt'] = $this->xmlrpcString;
1427 }
Barry Mienydd671972010-10-04 16:33:58 +02001428
Derek Allard2067d1a2008-11-13 22:59:24 +00001429 // build the XML-RPC value out of the data received, and substitute it
1430 $temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
Barry Mienydd671972010-10-04 16:33:58 +02001431
Alex Bilbied261b1e2012-06-02 11:12:16 +01001432 if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')
Derek Allard2067d1a2008-11-13 22:59:24 +00001433 {
1434 // Array
1435 $this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
1436 }
1437 else
1438 {
1439 // Struct
1440 $this->xh[$the_parser]['value'] = $temp;
1441 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001442 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001443 case 'MEMBER':
Andrey Andreevc8709832012-04-04 13:43:53 +03001444 $this->xh[$the_parser]['ac'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001445
Derek Allard2067d1a2008-11-13 22:59:24 +00001446 // If value add to array in the stack for the last element built
1447 if ($this->xh[$the_parser]['value'])
1448 {
1449 $this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
1450 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001451 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001452 case 'DATA':
Andrey Andreevc8709832012-04-04 13:43:53 +03001453 $this->xh[$the_parser]['ac'] = '';
1454 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001455 case 'PARAM':
1456 if ($this->xh[$the_parser]['value'])
1457 {
1458 $this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
1459 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001460 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001461 case 'METHODNAME':
1462 $this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001463 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001464 case 'PARAMS':
1465 case 'FAULT':
1466 case 'METHODCALL':
1467 case 'METHORESPONSE':
1468 // We're all good kids with nuthin' to do
Andrey Andreevc8709832012-04-04 13:43:53 +03001469 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001470 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001471 // End of an Invalid Element. Taken care of during the opening tag though
1472 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001473 }
1474 }
1475
Andrey Andreevc8709832012-04-04 13:43:53 +03001476 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001477
Andrey Andreevc8709832012-04-04 13:43:53 +03001478 /**
1479 * Parse character data
1480 *
1481 * @param string
1482 * @param string
1483 * @return void
1484 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001485 public function character_data($the_parser, $data)
Derek Allard2067d1a2008-11-13 22:59:24 +00001486 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001487 $the_parser = (string) $the_parser;
1488
Derek Allard2067d1a2008-11-13 22:59:24 +00001489 if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
Barry Mienydd671972010-10-04 16:33:58 +02001490
Derek Allard2067d1a2008-11-13 22:59:24 +00001491 // If a value has not been found
Alex Bilbied261b1e2012-06-02 11:12:16 +01001492 if ($this->xh[$the_parser]['lv'] !== 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001493 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001494 if ($this->xh[$the_parser]['lv'] === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001495 {
1496 $this->xh[$the_parser]['lv'] = 2; // Found a value
1497 }
Barry Mienydd671972010-10-04 16:33:58 +02001498
Andrey Andreevc8709832012-04-04 13:43:53 +03001499 if ( ! isset($this->xh[$the_parser]['ac']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001500 {
1501 $this->xh[$the_parser]['ac'] = '';
1502 }
Barry Mienydd671972010-10-04 16:33:58 +02001503
Derek Allard2067d1a2008-11-13 22:59:24 +00001504 $this->xh[$the_parser]['ac'] .= $data;
1505 }
1506 }
Barry Mienydd671972010-10-04 16:33:58 +02001507
Andrey Andreevc8709832012-04-04 13:43:53 +03001508 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001509
Andrey Andreevc8709832012-04-04 13:43:53 +03001510 /**
1511 * Add parameter
1512 *
1513 * @param mixed
1514 * @return void
1515 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001516 public function addParam($par)
1517 {
1518 $this->params[] = $par;
1519 }
Barry Mienydd671972010-10-04 16:33:58 +02001520
Andrey Andreevc8709832012-04-04 13:43:53 +03001521 // --------------------------------------------------------------------
1522
1523 /**
1524 * Output parameters
1525 *
Andrey Andreeve417f042014-01-08 14:48:01 +02001526 * @param array $array
Andrey Andreevc8709832012-04-04 13:43:53 +03001527 * @return array
1528 */
Andrey Andreeve417f042014-01-08 14:48:01 +02001529 public function output_parameters(array $array = array())
Derek Allard2067d1a2008-11-13 22:59:24 +00001530 {
Barry Mienydd671972010-10-04 16:33:58 +02001531 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +02001532
Andrey Andreeve417f042014-01-08 14:48:01 +02001533 if ( ! empty($array))
Derek Allard2067d1a2008-11-13 22:59:24 +00001534 {
1535 while (list($key) = each($array))
1536 {
1537 if (is_array($array[$key]))
1538 {
1539 $array[$key] = $this->output_parameters($array[$key]);
1540 }
Andrey Andreeve417f042014-01-08 14:48:01 +02001541 elseif ($key !== 'bits' && $this->xss_clean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001542 {
Derek Jonesa9647e82010-03-02 22:59:07 -06001543 // 'bits' is for the MetaWeblog API image bits
1544 // @todo - this needs to be made more general purpose
Andrey Andreeve417f042014-01-08 14:48:01 +02001545 $array[$key] = $CI->security->xss_clean($array[$key]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001546 }
1547 }
Barry Mienydd671972010-10-04 16:33:58 +02001548
Andrey Andreevc8709832012-04-04 13:43:53 +03001549 return $array;
Derek Allard2067d1a2008-11-13 22:59:24 +00001550 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001551
1552 $parameters = array();
1553
1554 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001555 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001556 $a_param = $this->decode_message($this->params[$i]);
Barry Mienydd671972010-10-04 16:33:58 +02001557
Andrey Andreevc8709832012-04-04 13:43:53 +03001558 if (is_array($a_param))
Derek Allard2067d1a2008-11-13 22:59:24 +00001559 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001560 $parameters[] = $this->output_parameters($a_param);
1561 }
1562 else
1563 {
1564 $parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;
Barry Mienydd671972010-10-04 16:33:58 +02001565 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001566 }
Barry Mienydd671972010-10-04 16:33:58 +02001567
Derek Allard2067d1a2008-11-13 22:59:24 +00001568 return $parameters;
1569 }
Barry Mienydd671972010-10-04 16:33:58 +02001570
Andrey Andreevc8709832012-04-04 13:43:53 +03001571 // --------------------------------------------------------------------
1572
1573 /**
1574 * Decode message
1575 *
1576 * @param object
1577 * @return mixed
1578 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001579 public function decode_message($param)
Derek Allard2067d1a2008-11-13 22:59:24 +00001580 {
1581 $kind = $param->kindOf();
1582
Alex Bilbied261b1e2012-06-02 11:12:16 +01001583 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +00001584 {
1585 return $param->scalarval();
1586 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001587 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +00001588 {
1589 reset($param->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001590 $b = current($param->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001591 $arr = array();
1592
Andrey Andreevc8709832012-04-04 13:43:53 +03001593 for ($i = 0, $c = count($b); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001594 {
1595 $arr[] = $this->decode_message($param->me['array'][$i]);
1596 }
Barry Mienydd671972010-10-04 16:33:58 +02001597
Derek Allard2067d1a2008-11-13 22:59:24 +00001598 return $arr;
1599 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001600 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +00001601 {
1602 reset($param->me['struct']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001603 $arr = array();
1604
Pascal Kriete14287f32011-02-14 13:39:34 -05001605 while (list($key,$value) = each($param->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001606 {
1607 $arr[$key] = $this->decode_message($value);
1608 }
Barry Mienydd671972010-10-04 16:33:58 +02001609
Derek Allard2067d1a2008-11-13 22:59:24 +00001610 return $arr;
1611 }
1612 }
Barry Mienydd671972010-10-04 16:33:58 +02001613
Andrey Andreevc8709832012-04-04 13:43:53 +03001614} // END XML_RPC_Message Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001615
1616/**
1617 * XML-RPC Values class
1618 *
1619 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -05001620 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +00001621 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
1622 */
1623class XML_RPC_Values extends CI_Xmlrpc
1624{
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001625 /**
1626 * Value data
1627 *
1628 * @var array
1629 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001630 public $me = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001631
1632 /**
1633 * Value type
1634 *
1635 * @var int
1636 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001637 public $mytype = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001638
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001639 // --------------------------------------------------------------------
1640
Andrey Andreevc8709832012-04-04 13:43:53 +03001641 /**
1642 * Constructor
1643 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001644 * @param mixed $val
1645 * @param string $type
Andrey Andreevc8709832012-04-04 13:43:53 +03001646 * @return void
1647 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001648 public function __construct($val = -1, $type = '')
Barry Mienydd671972010-10-04 16:33:58 +02001649 {
Greg Akera9263282010-11-10 15:26:43 -06001650 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +02001651
Alex Bilbied261b1e2012-06-02 11:12:16 +01001652 if ($val !== -1 OR $type !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001653 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001654 $type = $type === '' ? 'string' : $type;
Barry Mienydd671972010-10-04 16:33:58 +02001655
Dimitar740480a2012-10-05 13:24:59 +03001656 if ($this->xmlrpcTypes[$type] == 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001657 {
vkeranovb497d2b2012-11-23 23:27:33 +02001658 $this->addScalar($val, $type);
Derek Allard2067d1a2008-11-13 22:59:24 +00001659 }
Dimitar740480a2012-10-05 13:24:59 +03001660 elseif ($this->xmlrpcTypes[$type] == 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001661 {
1662 $this->addArray($val);
1663 }
Dimitar740480a2012-10-05 13:24:59 +03001664 elseif ($this->xmlrpcTypes[$type] == 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001665 {
1666 $this->addStruct($val);
1667 }
1668 }
1669 }
1670
Andrey Andreevc8709832012-04-04 13:43:53 +03001671 // --------------------------------------------------------------------
1672
1673 /**
1674 * Add scalar value
1675 *
1676 * @param scalar
1677 * @param string
1678 * @return int
1679 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001680 public function addScalar($val, $type = 'string')
Derek Allard2067d1a2008-11-13 22:59:24 +00001681 {
1682 $typeof = $this->xmlrpcTypes[$type];
Barry Mienydd671972010-10-04 16:33:58 +02001683
Alex Bilbied261b1e2012-06-02 11:12:16 +01001684 if ($this->mytype === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001685 {
1686 echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
1687 return 0;
1688 }
Barry Mienydd671972010-10-04 16:33:58 +02001689
Dimitar740480a2012-10-05 13:24:59 +03001690 if ($typeof != 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001691 {
1692 echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';
1693 return 0;
1694 }
1695
Alex Bilbied261b1e2012-06-02 11:12:16 +01001696 if ($type === $this->xmlrpcBoolean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001697 {
Andrey Andreev3f3f1352012-09-05 16:39:28 +03001698 $val = (int) (strcasecmp($val, 'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
Derek Allard2067d1a2008-11-13 22:59:24 +00001699 }
1700
Alex Bilbied261b1e2012-06-02 11:12:16 +01001701 if ($this->mytype === 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001702 {
1703 // adding to an array here
1704 $ar = $this->me['array'];
1705 $ar[] = new XML_RPC_Values($val, $type);
1706 $this->me['array'] = $ar;
1707 }
1708 else
1709 {
1710 // a scalar, so set the value and remember we're scalar
1711 $this->me[$type] = $val;
1712 $this->mytype = $typeof;
1713 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001714
Derek Allard2067d1a2008-11-13 22:59:24 +00001715 return 1;
1716 }
1717
Andrey Andreevc8709832012-04-04 13:43:53 +03001718 // --------------------------------------------------------------------
1719
1720 /**
1721 * Add array value
1722 *
1723 * @param array
1724 * @return int
1725 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001726 public function addArray($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001727 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001728 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001729 {
Andrey Andreev3ca060a2013-11-27 16:30:31 +02001730 echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
Derek Allard2067d1a2008-11-13 22:59:24 +00001731 return 0;
1732 }
1733
1734 $this->mytype = $this->xmlrpcTypes['array'];
1735 $this->me['array'] = $vals;
1736 return 1;
1737 }
1738
Andrey Andreevc8709832012-04-04 13:43:53 +03001739 // --------------------------------------------------------------------
1740
1741 /**
1742 * Add struct value
1743 *
1744 * @param object
1745 * @return int
1746 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001747 public function addStruct($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001748 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001749 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001750 {
Andrey Andreev3ca060a2013-11-27 16:30:31 +02001751 echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
Derek Allard2067d1a2008-11-13 22:59:24 +00001752 return 0;
1753 }
1754 $this->mytype = $this->xmlrpcTypes['struct'];
1755 $this->me['struct'] = $vals;
1756 return 1;
1757 }
1758
Andrey Andreevc8709832012-04-04 13:43:53 +03001759 // --------------------------------------------------------------------
1760
1761 /**
1762 * Get value type
1763 *
1764 * @return string
1765 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001766 public function kindOf()
Derek Allard2067d1a2008-11-13 22:59:24 +00001767 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001768 switch ($this->mytype)
Derek Allard2067d1a2008-11-13 22:59:24 +00001769 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001770 case 3: return 'struct';
1771 case 2: return 'array';
1772 case 1: return 'scalar';
1773 default: return 'undef';
Derek Allard2067d1a2008-11-13 22:59:24 +00001774 }
1775 }
1776
Andrey Andreevc8709832012-04-04 13:43:53 +03001777 // --------------------------------------------------------------------
1778
1779 /**
1780 * Serialize data
1781 *
1782 * @param string
1783 * @param mixed
1784 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001785 public function serializedata($typ, $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001786 {
1787 $rs = '';
Derek Jonesa9647e82010-03-02 22:59:07 -06001788
Andrey Andreevc8709832012-04-04 13:43:53 +03001789 switch ($this->xmlrpcTypes[$typ])
Derek Allard2067d1a2008-11-13 22:59:24 +00001790 {
1791 case 3:
1792 // struct
1793 $rs .= "<struct>\n";
1794 reset($val);
Pascal Kriete14287f32011-02-14 13:39:34 -05001795 while (list($key2, $val2) = each($val))
Derek Allard2067d1a2008-11-13 22:59:24 +00001796 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001797 $rs .= "<member>\n<name>{$key2}</name>\n".$this->serializeval($val2)."</member>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001798 }
1799 $rs .= '</struct>';
Andrey Andreevc8709832012-04-04 13:43:53 +03001800 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001801 case 2:
1802 // array
1803 $rs .= "<array>\n<data>\n";
Andrey Andreevc8709832012-04-04 13:43:53 +03001804 for ($i = 0, $c = count($val); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001805 {
1806 $rs .= $this->serializeval($val[$i]);
1807 }
Andrey Andreeva30faf92011-12-25 18:15:34 +02001808 $rs .= "</data>\n</array>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001809 break;
1810 case 1:
1811 // others
1812 switch ($typ)
1813 {
1814 case $this->xmlrpcBase64:
Andrey Andreevc8709832012-04-04 13:43:53 +03001815 $rs .= '<'.$typ.'>'.base64_encode( (string) $val).'</'.$typ.">\n";
1816 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001817 case $this->xmlrpcBoolean:
Andrey Andreevc8709832012-04-04 13:43:53 +03001818 $rs .= '<'.$typ.'>'.( (bool) $val ? '1' : '0').'</'.$typ.">\n";
1819 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001820 case $this->xmlrpcString:
Andrey Andreevc8709832012-04-04 13:43:53 +03001821 $rs .= '<'.$typ.'>'.htmlspecialchars( (string) $val).'</'.$typ.">\n";
1822 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001823 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001824 $rs .= '<'.$typ.'>'.$val.'</'.$typ.">\n";
1825 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001826 }
1827 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001828 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001829 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001830
Derek Allard2067d1a2008-11-13 22:59:24 +00001831 return $rs;
1832 }
1833
Andrey Andreevc8709832012-04-04 13:43:53 +03001834 // --------------------------------------------------------------------
1835
1836 /**
1837 * Serialize class
1838 *
1839 * @return string
1840 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001841 public function serialize_class()
Derek Allard2067d1a2008-11-13 22:59:24 +00001842 {
1843 return $this->serializeval($this);
1844 }
1845
Andrey Andreevc8709832012-04-04 13:43:53 +03001846 // --------------------------------------------------------------------
1847
1848 /**
1849 * Serialize value
1850 *
1851 * @param object
1852 * @return string
1853 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001854 public function serializeval($o)
Derek Allard2067d1a2008-11-13 22:59:24 +00001855 {
1856 $ar = $o->me;
1857 reset($ar);
Barry Mienydd671972010-10-04 16:33:58 +02001858
Derek Allard2067d1a2008-11-13 22:59:24 +00001859 list($typ, $val) = each($ar);
Andrey Andreeva30faf92011-12-25 18:15:34 +02001860 return "<value>\n".$this->serializedata($typ, $val)."</value>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001861 }
Barry Mienydd671972010-10-04 16:33:58 +02001862
Andrey Andreevc8709832012-04-04 13:43:53 +03001863 // --------------------------------------------------------------------
1864
1865 /**
1866 * Scalar value
1867 *
1868 * @return mixed
1869 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001870 public function scalarval()
Derek Allard2067d1a2008-11-13 22:59:24 +00001871 {
1872 reset($this->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001873 return current($this->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001874 }
1875
Andrey Andreevc8709832012-04-04 13:43:53 +03001876 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001877
Andrey Andreevc8709832012-04-04 13:43:53 +03001878 /**
1879 * Encode time in ISO-8601 form.
1880 * Useful for sending time in XML-RPC
1881 *
1882 * @param int unix timestamp
1883 * @param bool
1884 * @return string
1885 */
1886 public function iso8601_encode($time, $utc = FALSE)
Barry Mienydd671972010-10-04 16:33:58 +02001887 {
Andrey Andreev62090152011-12-30 12:49:27 +02001888 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 +00001889 }
Barry Mienydd671972010-10-04 16:33:58 +02001890
Andrey Andreevc8709832012-04-04 13:43:53 +03001891} // END XML_RPC_Values Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001892
1893/* End of file Xmlrpc.php */
Andrey Andreevc5a7c5f2013-07-17 20:10:09 +03001894/* Location: ./system/libraries/Xmlrpc.php */