blob: 690b245be98765550a71a898d2b8355c7ec26534 [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Andrey Andreevfe9309d2015-01-09 17:48:58 +02005 * An open source application development framework for PHP
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +02007 * This content is released under the MIT License (MIT)
Andrey Andreeva30faf92011-12-25 18:15:34 +02008 *
Instructor, BCIT0e59db62019-01-01 08:34:36 -08009 * Copyright (c) 2014 - 2019, British Columbia Institute of Technology
Andrey Andreeva30faf92011-12-25 18:15:34 +020010 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020011 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
Derek Jonesf4a4bd82011-10-20 12:18:42 -050017 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020018 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 *
29 * @package CodeIgniter
30 * @author EllisLab Dev Team
Andrey Andreev1924e872016-01-11 12:55:34 +020031 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
Instructor, BCIT0e59db62019-01-01 08:34:36 -080032 * @copyright Copyright (c) 2014 - 2019, British Columbia Institute of Technology (https://bcit.ca/)
33 * @license https://opensource.org/licenses/MIT MIT License
Andrey Andreevbd202c92016-01-11 12:50:18 +020034 * @link https://codeigniter.com
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020035 * @since Version 1.0.0
Derek Allard2067d1a2008-11-13 22:59:24 +000036 * @filesource
37 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020038defined('BASEPATH') OR exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +000039
Andrey Andreevf5ccd122012-11-02 00:17:39 +020040if ( ! function_exists('xml_parser_create'))
41{
42 show_error('Your PHP installation does not support XML');
43}
44
45// ------------------------------------------------------------------------
46
Derek Allard2067d1a2008-11-13 22:59:24 +000047/**
48 * XML-RPC request handler class
49 *
50 * @package CodeIgniter
51 * @subpackage Libraries
52 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -050053 * @author EllisLab Dev Team
Andrey Andreevbd202c92016-01-11 12:50:18 +020054 * @link https://codeigniter.com/user_guide/libraries/xmlrpc.html
Derek Allard2067d1a2008-11-13 22:59:24 +000055 */
56class CI_Xmlrpc {
57
Andrey Andreevf5ccd122012-11-02 00:17:39 +020058 /**
59 * Debug flag
60 *
61 * @var bool
62 */
63 public $debug = FALSE;
64
65 /**
66 * I4 data type
67 *
68 * @var string
69 */
Andrey Andreeva30faf92011-12-25 18:15:34 +020070 public $xmlrpcI4 = 'i4';
Andrey Andreevf5ccd122012-11-02 00:17:39 +020071
72 /**
73 * Integer data type
74 *
75 * @var string
76 */
Andrey Andreeva30faf92011-12-25 18:15:34 +020077 public $xmlrpcInt = 'int';
Andrey Andreevf5ccd122012-11-02 00:17:39 +020078
79 /**
80 * Boolean data type
81 *
82 * @var string
83 */
Andrey Andreeva30faf92011-12-25 18:15:34 +020084 public $xmlrpcBoolean = 'boolean';
Andrey Andreevf5ccd122012-11-02 00:17:39 +020085
86 /**
87 * Double data type
88 *
89 * @var string
90 */
Andrey Andreeva30faf92011-12-25 18:15:34 +020091 public $xmlrpcDouble = 'double';
Andrey Andreevf5ccd122012-11-02 00:17:39 +020092
93 /**
94 * String data type
95 *
96 * @var string
97 */
Andrey Andreeva30faf92011-12-25 18:15:34 +020098 public $xmlrpcString = 'string';
Andrey Andreevf5ccd122012-11-02 00:17:39 +020099
100 /**
101 * DateTime format
102 *
103 * @var string
104 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200105 public $xmlrpcDateTime = 'dateTime.iso8601';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200106
107 /**
108 * Base64 data type
109 *
110 * @var string
111 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200112 public $xmlrpcBase64 = 'base64';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200113
114 /**
115 * Array data type
116 *
117 * @var string
118 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200119 public $xmlrpcArray = 'array';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200120
121 /**
122 * Struct data type
123 *
124 * @var string
125 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200126 public $xmlrpcStruct = 'struct';
Barry Mienydd671972010-10-04 16:33:58 +0200127
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200128 /**
129 * Data types list
130 *
131 * @var array
132 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200133 public $xmlrpcTypes = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200134
135 /**
136 * Valid parents list
137 *
138 * @var array
139 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200140 public $valid_parents = array();
Barry Mienydd671972010-10-04 16:33:58 +0200141
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200142 /**
143 * Response error numbers list
144 *
145 * @var array
146 */
147 public $xmlrpcerr = array();
148
149 /**
150 * Response error messages list
151 *
152 * @var string[]
153 */
154 public $xmlrpcstr = array();
155
156 /**
157 * Encoding charset
158 *
159 * @var string
160 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200161 public $xmlrpc_defencoding = 'UTF-8';
Barry Mienydd671972010-10-04 16:33:58 +0200162
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200163 /**
164 * XML-RPC client name
165 *
166 * @var string
167 */
168 public $xmlrpcName = 'XML-RPC for CodeIgniter';
169
170 /**
171 * XML-RPC version
172 *
173 * @var string
174 */
175 public $xmlrpcVersion = '1.1';
176
177 /**
178 * Start of user errors
179 *
180 * @var int
181 */
182 public $xmlrpcerruser = 800;
183
184 /**
185 * Start of XML parse errors
186 *
187 * @var int
188 */
189 public $xmlrpcerrxml = 100;
190
191 /**
192 * Backslash replacement value
193 *
194 * @var string
195 */
196 public $xmlrpc_backslash = '';
197
198 /**
199 * XML-RPC Client object
200 *
201 * @var object
202 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200203 public $client;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200204
205 /**
206 * XML-RPC Method name
207 *
208 * @var string
209 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200210 public $method;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200211
212 /**
213 * XML-RPC Data
214 *
215 * @var array
216 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200217 public $data;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200218
219 /**
220 * XML-RPC Message
221 *
222 * @var string
223 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200224 public $message = '';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200225
226 /**
227 * Request error message
228 *
229 * @var string
230 */
231 public $error = '';
232
233 /**
234 * XML-RPC result object
235 *
236 * @var object
237 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200238 public $result;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200239
240 /**
Andrey Andreev71d8f722017-01-17 12:01:00 +0200241 * XML-RPC Response
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200242 *
243 * @var array
244 */
vkeranovb497d2b2012-11-23 23:27:33 +0200245 public $response = array(); // Response from remote server
Derek Allard2067d1a2008-11-13 22:59:24 +0000246
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200247 /**
248 * XSS Filter flag
249 *
250 * @var bool
251 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200252 public $xss_clean = TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000253
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200254 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000255
Andrey Andreevc8709832012-04-04 13:43:53 +0300256 /**
257 * Constructor
258 *
259 * Initializes property default values
260 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200261 * @param array $config
Andrey Andreevc8709832012-04-04 13:43:53 +0300262 * @return void
263 */
Greg Akera9263282010-11-10 15:26:43 -0600264 public function __construct($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000265 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000266 $this->xmlrpc_backslash = chr(92).chr(92);
Barry Mienydd671972010-10-04 16:33:58 +0200267
Derek Allard2067d1a2008-11-13 22:59:24 +0000268 // Types for info sent back and forth
269 $this->xmlrpcTypes = array(
Barry Mienydd671972010-10-04 16:33:58 +0200270 $this->xmlrpcI4 => '1',
271 $this->xmlrpcInt => '1',
272 $this->xmlrpcBoolean => '1',
273 $this->xmlrpcString => '1',
274 $this->xmlrpcDouble => '1',
275 $this->xmlrpcDateTime => '1',
276 $this->xmlrpcBase64 => '1',
277 $this->xmlrpcArray => '2',
278 $this->xmlrpcStruct => '3'
vkeranovb497d2b2012-11-23 23:27:33 +0200279 );
Barry Mienydd671972010-10-04 16:33:58 +0200280
Derek Allard2067d1a2008-11-13 22:59:24 +0000281 // Array of Valid Parents for Various XML-RPC elements
Timothy Warren0688ac92012-04-20 10:25:04 -0400282 $this->valid_parents = array('BOOLEAN' => array('VALUE'),
283 'I4' => array('VALUE'),
284 'INT' => array('VALUE'),
285 'STRING' => array('VALUE'),
286 'DOUBLE' => array('VALUE'),
287 'DATETIME.ISO8601' => array('VALUE'),
288 'BASE64' => array('VALUE'),
289 'ARRAY' => array('VALUE'),
290 'STRUCT' => array('VALUE'),
291 'PARAM' => array('PARAMS'),
292 'METHODNAME' => array('METHODCALL'),
293 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'),
294 'MEMBER' => array('STRUCT'),
295 'NAME' => array('MEMBER'),
296 'DATA' => array('ARRAY'),
297 'FAULT' => array('METHODRESPONSE'),
298 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT')
vkeranovb497d2b2012-11-23 23:27:33 +0200299 );
Barry Mienydd671972010-10-04 16:33:58 +0200300
Derek Allard2067d1a2008-11-13 22:59:24 +0000301 // XML-RPC Responses
302 $this->xmlrpcerr['unknown_method'] = '1';
303 $this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server';
304 $this->xmlrpcerr['invalid_return'] = '2';
vkeranovb497d2b2012-11-23 23:27:33 +0200305 $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 +0000306 $this->xmlrpcerr['incorrect_params'] = '3';
307 $this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method';
308 $this->xmlrpcerr['introspect_unknown'] = '4';
Andrey Andreeva30faf92011-12-25 18:15:34 +0200309 $this->xmlrpcstr['introspect_unknown'] = 'Cannot inspect signature for request: method unknown';
Derek Allard2067d1a2008-11-13 22:59:24 +0000310 $this->xmlrpcerr['http_error'] = '5';
311 $this->xmlrpcstr['http_error'] = "Did not receive a '200 OK' response from remote server.";
312 $this->xmlrpcerr['no_data'] = '6';
vkeranovb497d2b2012-11-23 23:27:33 +0200313 $this->xmlrpcstr['no_data'] = 'No data received from server.';
Barry Mienydd671972010-10-04 16:33:58 +0200314
Derek Allard2067d1a2008-11-13 22:59:24 +0000315 $this->initialize($config);
Barry Mienydd671972010-10-04 16:33:58 +0200316
Andrey Andreev90726b82015-01-20 12:39:22 +0200317 log_message('info', 'XML-RPC Class Initialized');
Derek Allard2067d1a2008-11-13 22:59:24 +0000318 }
Barry Mienydd671972010-10-04 16:33:58 +0200319
Andrey Andreevc8709832012-04-04 13:43:53 +0300320 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000321
Andrey Andreevc8709832012-04-04 13:43:53 +0300322 /**
323 * Initialize
324 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200325 * @param array $config
Andrey Andreevc8709832012-04-04 13:43:53 +0300326 * @return void
327 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200328 public function initialize($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000329 {
Derek Jones33559102009-02-02 18:50:38 +0000330 if (count($config) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000331 {
332 foreach ($config as $key => $val)
333 {
334 if (isset($this->$key))
335 {
Barry Mienydd671972010-10-04 16:33:58 +0200336 $this->$key = $val;
Derek Allard2067d1a2008-11-13 22:59:24 +0000337 }
338 }
339 }
340 }
Barry Mienydd671972010-10-04 16:33:58 +0200341
Andrey Andreevc8709832012-04-04 13:43:53 +0300342 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000343
Andrey Andreevc8709832012-04-04 13:43:53 +0300344 /**
345 * Parse server URL
346 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300347 * @param string $url
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200348 * @param int $port
349 * @param string $proxy
350 * @param int $proxy_port
Andrey Andreevc8709832012-04-04 13:43:53 +0300351 * @return void
352 */
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300353 public function server($url, $port = 80, $proxy = FALSE, $proxy_port = 8080)
Derek Allard2067d1a2008-11-13 22:59:24 +0000354 {
Andrey Andreeve33c82d2016-08-10 15:18:31 +0300355 if (stripos($url, 'http') !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000356 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300357 $url = 'http://'.$url;
Derek Allard2067d1a2008-11-13 22:59:24 +0000358 }
Barry Mienydd671972010-10-04 16:33:58 +0200359
Derek Allard2067d1a2008-11-13 22:59:24 +0000360 $parts = parse_url($url);
Barry Mienydd671972010-10-04 16:33:58 +0200361
Andrey Andreevdc53d7b2014-01-07 12:12:11 +0200362 if (isset($parts['user'], $parts['pass']))
363 {
364 $parts['host'] = $parts['user'].':'.$parts['pass'].'@'.$parts['host'];
365 }
366
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300367 $path = isset($parts['path']) ? $parts['path'] : '/';
Barry Mienydd671972010-10-04 16:33:58 +0200368
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300369 if ( ! empty($parts['query']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000370 {
371 $path .= '?'.$parts['query'];
Barry Mienydd671972010-10-04 16:33:58 +0200372 }
373
Valio9dee5352012-07-02 10:42:28 +0300374 $this->client = new XML_RPC_Client($path, $parts['host'], $port, $proxy, $proxy_port);
Derek Allard2067d1a2008-11-13 22:59:24 +0000375 }
Barry Mienydd671972010-10-04 16:33:58 +0200376
Andrey Andreevc8709832012-04-04 13:43:53 +0300377 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000378
Andrey Andreevc8709832012-04-04 13:43:53 +0300379 /**
380 * Set Timeout
381 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200382 * @param int $seconds
Andrey Andreevc8709832012-04-04 13:43:53 +0300383 * @return void
384 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200385 public function timeout($seconds = 5)
Derek Allard2067d1a2008-11-13 22:59:24 +0000386 {
vlakoff1228fe22013-01-14 01:30:09 +0100387 if ($this->client !== NULL && is_int($seconds))
Derek Allard2067d1a2008-11-13 22:59:24 +0000388 {
389 $this->client->timeout = $seconds;
390 }
391 }
Barry Mienydd671972010-10-04 16:33:58 +0200392
Andrey Andreevc8709832012-04-04 13:43:53 +0300393 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000394
Andrey Andreevc8709832012-04-04 13:43:53 +0300395 /**
396 * Set Methods
397 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200398 * @param string $function Method name
Andrey Andreevc8709832012-04-04 13:43:53 +0300399 * @return void
400 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200401 public function method($function)
Derek Allard2067d1a2008-11-13 22:59:24 +0000402 {
403 $this->method = $function;
404 }
Barry Mienydd671972010-10-04 16:33:58 +0200405
Andrey Andreevc8709832012-04-04 13:43:53 +0300406 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000407
Andrey Andreevc8709832012-04-04 13:43:53 +0300408 /**
409 * Take Array of Data and Create Objects
410 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200411 * @param array $incoming
Andrey Andreevc8709832012-04-04 13:43:53 +0300412 * @return void
413 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200414 public function request($incoming)
Derek Allard2067d1a2008-11-13 22:59:24 +0000415 {
416 if ( ! is_array($incoming))
417 {
418 // Send Error
Andrey Andreevc8709832012-04-04 13:43:53 +0300419 return;
Derek Allard2067d1a2008-11-13 22:59:24 +0000420 }
Barry Mienydd671972010-10-04 16:33:58 +0200421
Derek Allard2067d1a2008-11-13 22:59:24 +0000422 $this->data = array();
Barry Mienydd671972010-10-04 16:33:58 +0200423
Pascal Kriete14287f32011-02-14 13:39:34 -0500424 foreach ($incoming as $key => $value)
Derek Allard2067d1a2008-11-13 22:59:24 +0000425 {
426 $this->data[$key] = $this->values_parsing($value);
427 }
428 }
Barry Mienydd671972010-10-04 16:33:58 +0200429
Andrey Andreevc8709832012-04-04 13:43:53 +0300430 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200431
Andrey Andreevc8709832012-04-04 13:43:53 +0300432 /**
433 * Set Debug
434 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200435 * @param bool $flag
Andrey Andreevc8709832012-04-04 13:43:53 +0300436 * @return void
437 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200438 public function set_debug($flag = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000439 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100440 $this->debug = ($flag === TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000441 }
Barry Mienydd671972010-10-04 16:33:58 +0200442
Andrey Andreevc8709832012-04-04 13:43:53 +0300443 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000444
Andrey Andreevc8709832012-04-04 13:43:53 +0300445 /**
446 * Values Parsing
447 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200448 * @param mixed $value
Andrey Andreevc8709832012-04-04 13:43:53 +0300449 * @return object
450 */
451 public function values_parsing($value)
Derek Allard2067d1a2008-11-13 22:59:24 +0000452 {
Derek Jones8c4b5e72010-01-06 22:21:41 +0000453 if (is_array($value) && array_key_exists(0, $value))
Derek Allard2067d1a2008-11-13 22:59:24 +0000454 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300455 if ( ! isset($value[1], $this->xmlrpcTypes[$value[1]]))
Derek Allard2067d1a2008-11-13 22:59:24 +0000456 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200457 $temp = new XML_RPC_Values($value[0], (is_array($value[0]) ? 'array' : 'string'));
Derek Allard2067d1a2008-11-13 22:59:24 +0000458 }
459 else
460 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100461 if (is_array($value[0]) && ($value[1] === 'struct' OR $value[1] === 'array'))
Andrey Andreeva30faf92011-12-25 18:15:34 +0200462 {
Andrey Andreev4316a152017-01-20 15:46:17 +0200463 foreach (array_keys($value[0]) as $k)
Andrey Andreeva30faf92011-12-25 18:15:34 +0200464 {
Rasmus Lerdorf99860702013-05-18 10:27:12 -0400465 $value[0][$k] = $this->values_parsing($value[0][$k]);
Andrey Andreeva30faf92011-12-25 18:15:34 +0200466 }
467 }
468
469 $temp = new XML_RPC_Values($value[0], $value[1]);
Derek Allard2067d1a2008-11-13 22:59:24 +0000470 }
471 }
472 else
473 {
474 $temp = new XML_RPC_Values($value, 'string');
475 }
476
477 return $temp;
478 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000479
Andrey Andreevc8709832012-04-04 13:43:53 +0300480 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000481
Andrey Andreevc8709832012-04-04 13:43:53 +0300482 /**
483 * Sends XML-RPC Request
484 *
485 * @return bool
486 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200487 public function send_request()
Derek Allard2067d1a2008-11-13 22:59:24 +0000488 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300489 $this->message = new XML_RPC_Message($this->method, $this->data);
Derek Allard2067d1a2008-11-13 22:59:24 +0000490 $this->message->debug = $this->debug;
Barry Mienydd671972010-10-04 16:33:58 +0200491
Andrey Andreeva30faf92011-12-25 18:15:34 +0200492 if ( ! $this->result = $this->client->send($this->message) OR ! is_object($this->result->val))
Derek Allard2067d1a2008-11-13 22:59:24 +0000493 {
494 $this->error = $this->result->errstr;
495 return FALSE;
496 }
Barry Mienydd671972010-10-04 16:33:58 +0200497
Derek Allard2067d1a2008-11-13 22:59:24 +0000498 $this->response = $this->result->decode();
Derek Allard2067d1a2008-11-13 22:59:24 +0000499 return TRUE;
500 }
Barry Mienydd671972010-10-04 16:33:58 +0200501
Andrey Andreevc8709832012-04-04 13:43:53 +0300502 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000503
Andrey Andreevc8709832012-04-04 13:43:53 +0300504 /**
505 * Returns Error
506 *
507 * @return string
508 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200509 public function display_error()
Derek Allard2067d1a2008-11-13 22:59:24 +0000510 {
511 return $this->error;
512 }
Barry Mienydd671972010-10-04 16:33:58 +0200513
Andrey Andreevc8709832012-04-04 13:43:53 +0300514 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000515
Andrey Andreevc8709832012-04-04 13:43:53 +0300516 /**
517 * Returns Remote Server Response
518 *
519 * @return string
520 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200521 public function display_response()
Derek Allard2067d1a2008-11-13 22:59:24 +0000522 {
523 return $this->response;
524 }
Barry Mienydd671972010-10-04 16:33:58 +0200525
Andrey Andreevc8709832012-04-04 13:43:53 +0300526 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200527
Andrey Andreevc8709832012-04-04 13:43:53 +0300528 /**
529 * Sends an Error Message for Server Request
530 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200531 * @param int $number
532 * @param string $message
Andrey Andreevc8709832012-04-04 13:43:53 +0300533 * @return object
534 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200535 public function send_error_message($number, $message)
Derek Allard2067d1a2008-11-13 22:59:24 +0000536 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200537 return new XML_RPC_Response(0, $number, $message);
Derek Allard2067d1a2008-11-13 22:59:24 +0000538 }
Barry Mienydd671972010-10-04 16:33:58 +0200539
Andrey Andreevc8709832012-04-04 13:43:53 +0300540 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200541
Andrey Andreevc8709832012-04-04 13:43:53 +0300542 /**
543 * Send Response for Server Request
544 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200545 * @param array $response
Andrey Andreevc8709832012-04-04 13:43:53 +0300546 * @return object
547 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200548 public function send_response($response)
Derek Allard2067d1a2008-11-13 22:59:24 +0000549 {
550 // $response should be array of values, which will be parsed
551 // based on their data and type into a valid group of XML-RPC values
Andrey Andreeva30faf92011-12-25 18:15:34 +0200552 return new XML_RPC_Response($this->values_parsing($response));
Derek Allard2067d1a2008-11-13 22:59:24 +0000553 }
Barry Mienydd671972010-10-04 16:33:58 +0200554
Derek Allard2067d1a2008-11-13 22:59:24 +0000555} // END XML_RPC Class
556
Derek Allard2067d1a2008-11-13 22:59:24 +0000557/**
558 * XML-RPC Client class
559 *
560 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500561 * @author EllisLab Dev Team
Andrey Andreevbd202c92016-01-11 12:50:18 +0200562 * @link https://codeigniter.com/user_guide/libraries/xmlrpc.html
Derek Allard2067d1a2008-11-13 22:59:24 +0000563 */
564class XML_RPC_Client extends CI_Xmlrpc
565{
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200566 /**
567 * Path
568 *
569 * @var string
570 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200571 public $path = '';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200572
573 /**
574 * Server hostname
575 *
576 * @var string
577 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200578 public $server = '';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200579
580 /**
581 * Server port
582 *
583 * @var int
584 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200585 public $port = 80;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200586
587 /**
Andrey Andreevdc53d7b2014-01-07 12:12:11 +0200588 *
589 * Server username
590 *
591 * @var string
592 */
593 public $username;
594
595 /**
596 * Server password
597 *
598 * @var string
599 */
600 public $password;
601
602 /**
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200603 * Proxy hostname
604 *
605 * @var string
606 */
Valio9dee5352012-07-02 10:42:28 +0300607 public $proxy = FALSE;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200608
609 /**
610 * Proxy port
611 *
612 * @var int
613 */
Valio9dee5352012-07-02 10:42:28 +0300614 public $proxy_port = 8080;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200615
616 /**
617 * Error number
618 *
619 * @var string
620 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200621 public $errno = '';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200622
623 /**
624 * Error message
625 *
626 * @var string
627 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200628 public $errstring = '';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200629
630 /**
631 * Timeout in seconds
632 *
633 * @var int
634 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200635 public $timeout = 5;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200636
637 /**
638 * No Multicall flag
639 *
640 * @var bool
641 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200642 public $no_multicall = FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000643
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200644 // --------------------------------------------------------------------
645
Andrey Andreevc8709832012-04-04 13:43:53 +0300646 /**
647 * Constructor
648 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300649 * @param string $path
650 * @param object $server
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200651 * @param int $port
652 * @param string $proxy
653 * @param int $proxy_port
Andrey Andreevc8709832012-04-04 13:43:53 +0300654 * @return void
655 */
Valio9dee5352012-07-02 10:42:28 +0300656 public function __construct($path, $server, $port = 80, $proxy = FALSE, $proxy_port = 8080)
Derek Allard2067d1a2008-11-13 22:59:24 +0000657 {
Greg Akera9263282010-11-10 15:26:43 -0600658 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +0200659
Andrey Andreevdc53d7b2014-01-07 12:12:11 +0200660 $url = parse_url('http://'.$server);
661
662 if (isset($url['user'], $url['pass']))
663 {
664 $this->username = $url['user'];
665 $this->password = $url['pass'];
666 }
667
Derek Allard2067d1a2008-11-13 22:59:24 +0000668 $this->port = $port;
Andrey Andreevdc53d7b2014-01-07 12:12:11 +0200669 $this->server = $url['host'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000670 $this->path = $path;
Valio9dee5352012-07-02 10:42:28 +0300671 $this->proxy = $proxy;
672 $this->proxy_port = $proxy_port;
Derek Allard2067d1a2008-11-13 22:59:24 +0000673 }
Barry Mienydd671972010-10-04 16:33:58 +0200674
Andrey Andreevc8709832012-04-04 13:43:53 +0300675 // --------------------------------------------------------------------
676
677 /**
678 * Send message
679 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200680 * @param mixed $msg
Andrey Andreevc8709832012-04-04 13:43:53 +0300681 * @return object
682 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200683 public function send($msg)
Derek Allard2067d1a2008-11-13 22:59:24 +0000684 {
685 if (is_array($msg))
686 {
687 // Multi-call disabled
Andrey Andreevc8709832012-04-04 13:43:53 +0300688 return new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'], $this->xmlrpcstr['multicall_recursion']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000689 }
690
691 return $this->sendPayload($msg);
692 }
693
Andrey Andreevc8709832012-04-04 13:43:53 +0300694 // --------------------------------------------------------------------
695
696 /**
697 * Send payload
698 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200699 * @param object $msg
Andrey Andreevc8709832012-04-04 13:43:53 +0300700 * @return object
701 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200702 public function sendPayload($msg)
Barry Mienydd671972010-10-04 16:33:58 +0200703 {
Andrey Andreevc02e7c52012-07-02 16:43:43 +0300704 if ($this->proxy === FALSE)
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300705 {
706 $server = $this->server;
707 $port = $this->port;
Valentin Sheyretski09217ce2012-07-02 16:27:01 +0300708 }
709 else
710 {
Valio9dee5352012-07-02 10:42:28 +0300711 $server = $this->proxy;
712 $port = $this->proxy_port;
713 }
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300714
Valio9dee5352012-07-02 10:42:28 +0300715 $fp = @fsockopen($server, $port, $this->errno, $this->errstring, $this->timeout);
Barry Mienydd671972010-10-04 16:33:58 +0200716
Derek Allard2067d1a2008-11-13 22:59:24 +0000717 if ( ! is_resource($fp))
718 {
719 error_log($this->xmlrpcstr['http_error']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300720 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000721 }
Barry Mienydd671972010-10-04 16:33:58 +0200722
Pascal Kriete14287f32011-02-14 13:39:34 -0500723 if (empty($msg->payload))
Derek Allard2067d1a2008-11-13 22:59:24 +0000724 {
725 // $msg = XML_RPC_Messages
726 $msg->createPayload();
727 }
Barry Mienydd671972010-10-04 16:33:58 +0200728
Derek Allard2067d1a2008-11-13 22:59:24 +0000729 $r = "\r\n";
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300730 $op = 'POST '.$this->path.' HTTP/1.0'.$r
731 .'Host: '.$this->server.$r
732 .'Content-Type: text/xml'.$r
Andrey Andreevdc53d7b2014-01-07 12:12:11 +0200733 .(isset($this->username, $this->password) ? 'Authorization: Basic '.base64_encode($this->username.':'.$this->password).$r : '')
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300734 .'User-Agent: '.$this->xmlrpcName.$r
735 .'Content-Length: '.strlen($msg->payload).$r.$r
736 .$msg->payload;
Andrey Andreevdc44b922016-10-20 11:56:20 +0300737
738 stream_set_timeout($fp, $this->timeout); // set timeout for subsequent operations
Barry Mienydd671972010-10-04 16:33:58 +0200739
Andrey Andreev4e0496e2015-06-22 12:34:38 +0300740 for ($written = $timestamp = 0, $length = strlen($op); $written < $length; $written += $result)
Andrey Andreevd8b1ad32014-01-15 17:42:52 +0200741 {
742 if (($result = fwrite($fp, substr($op, $written))) === FALSE)
743 {
744 break;
745 }
Andrey Andreev4e0496e2015-06-22 12:34:38 +0300746 // See https://bugs.php.net/bug.php?id=39598 and http://php.net/manual/en/function.fwrite.php#96951
747 elseif ($result === 0)
748 {
749 if ($timestamp === 0)
750 {
751 $timestamp = time();
752 }
753 elseif ($timestamp < (time() - $this->timeout))
754 {
755 $result = FALSE;
756 break;
757 }
Andrey Andreev4e0496e2015-06-22 12:34:38 +0300758 }
759 else
760 {
761 $timestamp = 0;
762 }
Andrey Andreevd8b1ad32014-01-15 17:42:52 +0200763 }
764
765 if ($result === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000766 {
767 error_log($this->xmlrpcstr['http_error']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300768 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000769 }
Andrey Andreevc8709832012-04-04 13:43:53 +0300770
Derek Allard2067d1a2008-11-13 22:59:24 +0000771 $resp = $msg->parseResponse($fp);
772 fclose($fp);
773 return $resp;
774 }
775
Andrey Andreevc8709832012-04-04 13:43:53 +0300776} // END XML_RPC_Client Class
Derek Allard2067d1a2008-11-13 22:59:24 +0000777
778/**
779 * XML-RPC Response class
780 *
781 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500782 * @author EllisLab Dev Team
Andrey Andreevbd202c92016-01-11 12:50:18 +0200783 * @link https://codeigniter.com/user_guide/libraries/xmlrpc.html
Derek Allard2067d1a2008-11-13 22:59:24 +0000784 */
785class XML_RPC_Response
786{
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200787
788 /**
789 * Value
790 *
791 * @var mixed
792 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300793 public $val = 0;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200794
795 /**
796 * Error number
797 *
798 * @var int
799 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300800 public $errno = 0;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200801
802 /**
803 * Error message
804 *
805 * @var string
806 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300807 public $errstr = '';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200808
809 /**
810 * Headers list
811 *
812 * @var array
813 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300814 public $headers = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200815
816 /**
817 * XSS Filter flag
818 *
819 * @var bool
820 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300821 public $xss_clean = TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000822
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200823 // --------------------------------------------------------------------
824
Andrey Andreevc8709832012-04-04 13:43:53 +0300825 /**
826 * Constructor
827 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200828 * @param mixed $val
829 * @param int $code
830 * @param string $fstr
Andrey Andreevc8709832012-04-04 13:43:53 +0300831 * @return void
832 */
Greg Akera9263282010-11-10 15:26:43 -0600833 public function __construct($val, $code = 0, $fstr = '')
Barry Mienydd671972010-10-04 16:33:58 +0200834 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100835 if ($code !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000836 {
837 // error
838 $this->errno = $code;
Andrey Andreevc8709832012-04-04 13:43:53 +0300839 $this->errstr = htmlspecialchars($fstr,
840 (is_php('5.4') ? ENT_XML1 | ENT_NOQUOTES : ENT_NOQUOTES),
841 'UTF-8');
Derek Allard2067d1a2008-11-13 22:59:24 +0000842 }
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300843 elseif ( ! is_object($val))
Derek Allard2067d1a2008-11-13 22:59:24 +0000844 {
845 // programmer error, not an object
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300846 error_log("Invalid type '".gettype($val)."' (value: ".$val.') passed to XML_RPC_Response. Defaulting to empty value.');
Derek Allard2067d1a2008-11-13 22:59:24 +0000847 $this->val = new XML_RPC_Values();
848 }
849 else
850 {
851 $this->val = $val;
852 }
853 }
854
Andrey Andreevc8709832012-04-04 13:43:53 +0300855 // --------------------------------------------------------------------
856
857 /**
858 * Fault code
859 *
860 * @return int
861 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200862 public function faultCode()
Derek Allard2067d1a2008-11-13 22:59:24 +0000863 {
864 return $this->errno;
865 }
866
Andrey Andreevc8709832012-04-04 13:43:53 +0300867 // --------------------------------------------------------------------
868
869 /**
870 * Fault string
871 *
872 * @return string
873 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200874 public function faultString()
Derek Allard2067d1a2008-11-13 22:59:24 +0000875 {
876 return $this->errstr;
877 }
878
Andrey Andreevc8709832012-04-04 13:43:53 +0300879 // --------------------------------------------------------------------
880
881 /**
882 * Value
883 *
884 * @return mixed
885 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200886 public function value()
Derek Allard2067d1a2008-11-13 22:59:24 +0000887 {
888 return $this->val;
889 }
Barry Mienydd671972010-10-04 16:33:58 +0200890
Andrey Andreevc8709832012-04-04 13:43:53 +0300891 // --------------------------------------------------------------------
892
893 /**
894 * Prepare response
895 *
896 * @return string xml
897 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200898 public function prepare_response()
Derek Allard2067d1a2008-11-13 22:59:24 +0000899 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200900 return "<methodResponse>\n"
Andrey Andreevc8709832012-04-04 13:43:53 +0300901 .($this->errno
902 ? '<fault>
Derek Allard2067d1a2008-11-13 22:59:24 +0000903 <value>
904 <struct>
905 <member>
906 <name>faultCode</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300907 <value><int>'.$this->errno.'</int></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000908 </member>
909 <member>
910 <name>faultString</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300911 <value><string>'.$this->errstr.'</string></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000912 </member>
913 </struct>
914 </value>
Andrey Andreeva30faf92011-12-25 18:15:34 +0200915</fault>'
Andrey Andreevc8709832012-04-04 13:43:53 +0300916 : "<params>\n<param>\n".$this->val->serialize_class()."</param>\n</params>")
917 ."\n</methodResponse>";
Derek Allard2067d1a2008-11-13 22:59:24 +0000918 }
Barry Mienydd671972010-10-04 16:33:58 +0200919
Andrey Andreevc8709832012-04-04 13:43:53 +0300920 // --------------------------------------------------------------------
921
922 /**
923 * Decode
924 *
Andrey Andreeve417f042014-01-08 14:48:01 +0200925 * @param mixed $array
Andrey Andreevc8709832012-04-04 13:43:53 +0300926 * @return array
927 */
Andrey Andreeve417f042014-01-08 14:48:01 +0200928 public function decode($array = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000929 {
930 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +0200931
932 if (is_array($array))
Derek Allard2067d1a2008-11-13 22:59:24 +0000933 {
Andrey Andreev4316a152017-01-20 15:46:17 +0200934 foreach ($array as $key => &$value)
Derek Allard2067d1a2008-11-13 22:59:24 +0000935 {
Andrey Andreev4316a152017-01-20 15:46:17 +0200936 if (is_array($value))
Derek Allard2067d1a2008-11-13 22:59:24 +0000937 {
Andrey Andreev4316a152017-01-20 15:46:17 +0200938 $array[$key] = $this->decode($value);
Derek Allard2067d1a2008-11-13 22:59:24 +0000939 }
Andrey Andreeve417f042014-01-08 14:48:01 +0200940 elseif ($this->xss_clean)
Derek Allard2067d1a2008-11-13 22:59:24 +0000941 {
Andrey Andreev4316a152017-01-20 15:46:17 +0200942 $array[$key] = $CI->security->xss_clean($value);
Derek Allard2067d1a2008-11-13 22:59:24 +0000943 }
944 }
Barry Mienydd671972010-10-04 16:33:58 +0200945
Andrey Andreevc8709832012-04-04 13:43:53 +0300946 return $array;
947 }
948
949 $result = $this->xmlrpc_decoder($this->val);
950
951 if (is_array($result))
952 {
953 $result = $this->decode($result);
Derek Allard2067d1a2008-11-13 22:59:24 +0000954 }
Andrey Andreeve417f042014-01-08 14:48:01 +0200955 elseif ($this->xss_clean)
Derek Allard2067d1a2008-11-13 22:59:24 +0000956 {
Andrey Andreeve417f042014-01-08 14:48:01 +0200957 $result = $CI->security->xss_clean($result);
Derek Allard2067d1a2008-11-13 22:59:24 +0000958 }
Barry Mienydd671972010-10-04 16:33:58 +0200959
Derek Allard2067d1a2008-11-13 22:59:24 +0000960 return $result;
961 }
962
Andrey Andreevc8709832012-04-04 13:43:53 +0300963 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000964
Andrey Andreevc8709832012-04-04 13:43:53 +0300965 /**
966 * XML-RPC Object to PHP Types
967 *
968 * @param object
969 * @return array
970 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200971 public function xmlrpc_decoder($xmlrpc_val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000972 {
973 $kind = $xmlrpc_val->kindOf();
974
Alex Bilbied261b1e2012-06-02 11:12:16 +0100975 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +0000976 {
977 return $xmlrpc_val->scalarval();
978 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100979 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +0000980 {
981 reset($xmlrpc_val->me);
Andrey Andreevadc11752011-12-30 14:46:08 +0200982 $b = current($xmlrpc_val->me);
Derek Allard2067d1a2008-11-13 22:59:24 +0000983 $arr = array();
984
Andrey Andreeva30faf92011-12-25 18:15:34 +0200985 for ($i = 0, $size = count($b); $i < $size; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000986 {
987 $arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);
988 }
989 return $arr;
990 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100991 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +0000992 {
993 reset($xmlrpc_val->me['struct']);
994 $arr = array();
995
Andrey Andreev4316a152017-01-20 15:46:17 +0200996 foreach ($xmlrpc_val->me['struct'] as $key => &$value)
Derek Allard2067d1a2008-11-13 22:59:24 +0000997 {
998 $arr[$key] = $this->xmlrpc_decoder($value);
999 }
Andrey Andreev4316a152017-01-20 15:46:17 +02001000
Derek Allard2067d1a2008-11-13 22:59:24 +00001001 return $arr;
1002 }
1003 }
Barry Mienydd671972010-10-04 16:33:58 +02001004
Andrey Andreevc8709832012-04-04 13:43:53 +03001005 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001006
Andrey Andreevc8709832012-04-04 13:43:53 +03001007 /**
1008 * ISO-8601 time to server or UTC time
1009 *
1010 * @param string
1011 * @param bool
1012 * @return int unix timestamp
1013 */
1014 public function iso8601_decode($time, $utc = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001015 {
vkeranovb497d2b2012-11-23 23:27:33 +02001016 // Return a time in the localtime, or UTC
Derek Allard2067d1a2008-11-13 22:59:24 +00001017 $t = 0;
1018 if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))
1019 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001020 $fnc = ($utc === TRUE) ? 'gmmktime' : 'mktime';
Pascal Kriete14287f32011-02-14 13:39:34 -05001021 $t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001022 }
1023 return $t;
1024 }
Barry Mienydd671972010-10-04 16:33:58 +02001025
Andrey Andreevc8709832012-04-04 13:43:53 +03001026} // END XML_RPC_Response Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001027
1028/**
1029 * XML-RPC Message class
1030 *
1031 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -05001032 * @author EllisLab Dev Team
Andrey Andreevbd202c92016-01-11 12:50:18 +02001033 * @link https://codeigniter.com/user_guide/libraries/xmlrpc.html
Derek Allard2067d1a2008-11-13 22:59:24 +00001034 */
1035class XML_RPC_Message extends CI_Xmlrpc
1036{
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001037
1038 /**
1039 * Payload
1040 *
1041 * @var string
1042 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001043 public $payload;
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001044
1045 /**
1046 * Method name
1047 *
1048 * @var string
1049 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001050 public $method_name;
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001051
1052 /**
1053 * Parameter list
1054 *
1055 * @var array
1056 */
Andrey Andreevc8709832012-04-04 13:43:53 +03001057 public $params = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001058
1059 /**
1060 * XH?
1061 *
1062 * @var array
1063 */
Andrey Andreevc8709832012-04-04 13:43:53 +03001064 public $xh = array();
Derek Allard2067d1a2008-11-13 22:59:24 +00001065
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001066 // --------------------------------------------------------------------
1067
Andrey Andreevc8709832012-04-04 13:43:53 +03001068 /**
1069 * Constructor
1070 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001071 * @param string $method
1072 * @param array $pars
Andrey Andreevc8709832012-04-04 13:43:53 +03001073 * @return void
1074 */
1075 public function __construct($method, $pars = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001076 {
Greg Akera9263282010-11-10 15:26:43 -06001077 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +02001078
Derek Allard2067d1a2008-11-13 22:59:24 +00001079 $this->method_name = $method;
Derek Jones33559102009-02-02 18:50:38 +00001080 if (is_array($pars) && count($pars) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001081 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001082 for ($i = 0, $c = count($pars); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001083 {
1084 // $pars[$i] = XML_RPC_Values
1085 $this->params[] = $pars[$i];
1086 }
1087 }
1088 }
Barry Mienydd671972010-10-04 16:33:58 +02001089
Andrey Andreevc8709832012-04-04 13:43:53 +03001090 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001091
Andrey Andreevc8709832012-04-04 13:43:53 +03001092 /**
1093 * Create Payload to Send
1094 *
1095 * @return void
1096 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001097 public function createPayload()
Derek Allard2067d1a2008-11-13 22:59:24 +00001098 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001099 $this->payload = '<?xml version="1.0"?'.">\r\n<methodCall>\r\n"
1100 .'<methodName>'.$this->method_name."</methodName>\r\n"
1101 ."<params>\r\n";
Barry Mienydd671972010-10-04 16:33:58 +02001102
Andrey Andreeva30faf92011-12-25 18:15:34 +02001103 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001104 {
1105 // $p = XML_RPC_Values
1106 $p = $this->params[$i];
1107 $this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n";
1108 }
Barry Mienydd671972010-10-04 16:33:58 +02001109
Derek Allard2067d1a2008-11-13 22:59:24 +00001110 $this->payload .= "</params>\r\n</methodCall>\r\n";
1111 }
Barry Mienydd671972010-10-04 16:33:58 +02001112
Andrey Andreevc8709832012-04-04 13:43:53 +03001113 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001114
Andrey Andreevc8709832012-04-04 13:43:53 +03001115 /**
1116 * Parse External XML-RPC Server's Response
1117 *
1118 * @param resource
1119 * @return object
1120 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001121 public function parseResponse($fp)
Derek Allard2067d1a2008-11-13 22:59:24 +00001122 {
1123 $data = '';
Barry Mienydd671972010-10-04 16:33:58 +02001124
Pascal Kriete14287f32011-02-14 13:39:34 -05001125 while ($datum = fread($fp, 4096))
Derek Allard2067d1a2008-11-13 22:59:24 +00001126 {
1127 $data .= $datum;
1128 }
Barry Mienydd671972010-10-04 16:33:58 +02001129
Andrey Andreevc8709832012-04-04 13:43:53 +03001130 // Display HTTP content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +00001131 if ($this->debug === TRUE)
1132 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001133 echo "<pre>---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n</pre>";
Derek Allard2067d1a2008-11-13 22:59:24 +00001134 }
Barry Mienydd671972010-10-04 16:33:58 +02001135
Andrey Andreevc8709832012-04-04 13:43:53 +03001136 // Check for data
Andrey Andreeva30faf92011-12-25 18:15:34 +02001137 if ($data === '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001138 {
1139 error_log($this->xmlrpcstr['no_data']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001140 return new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001141 }
Barry Mienydd671972010-10-04 16:33:58 +02001142
Andrey Andreevc8709832012-04-04 13:43:53 +03001143 // Check for HTTP 200 Response
Andrey Andreev3dad2e72012-06-14 15:10:56 +03001144 if (strpos($data, 'HTTP') === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
Derek Allard2067d1a2008-11-13 22:59:24 +00001145 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001146 $errstr = substr($data, 0, strpos($data, "\n")-1);
1147 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');
Derek Allard2067d1a2008-11-13 22:59:24 +00001148 }
Barry Mienydd671972010-10-04 16:33:58 +02001149
Derek Allard2067d1a2008-11-13 22:59:24 +00001150 //-------------------------------------
vkeranovb497d2b2012-11-23 23:27:33 +02001151 // Create and Set Up XML Parser
Derek Allard2067d1a2008-11-13 22:59:24 +00001152 //-------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001153
Derek Allard2067d1a2008-11-13 22:59:24 +00001154 $parser = xml_parser_create($this->xmlrpc_defencoding);
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001155 $pname = (string) $parser;
1156 $this->xh[$pname] = array(
1157 'isf' => 0,
1158 'ac' => '',
1159 'headers' => array(),
1160 'stack' => array(),
1161 'valuestack' => array(),
1162 'isf_reason' => 0
1163 );
Derek Allard2067d1a2008-11-13 22:59:24 +00001164
1165 xml_set_object($parser, $this);
Andrey Andreevc8709832012-04-04 13:43:53 +03001166 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +00001167 xml_set_element_handler($parser, 'open_tag', 'closing_tag');
1168 xml_set_character_data_handler($parser, 'character_data');
1169 //xml_set_default_handler($parser, 'default_handler');
1170
Andrey Andreevc8709832012-04-04 13:43:53 +03001171 // Get headers
Derek Allard2067d1a2008-11-13 22:59:24 +00001172 $lines = explode("\r\n", $data);
1173 while (($line = array_shift($lines)))
1174 {
1175 if (strlen($line) < 1)
1176 {
1177 break;
1178 }
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001179 $this->xh[$pname]['headers'][] = $line;
Derek Allard2067d1a2008-11-13 22:59:24 +00001180 }
1181 $data = implode("\r\n", $lines);
Barry Mienydd671972010-10-04 16:33:58 +02001182
Andrey Andreevc8709832012-04-04 13:43:53 +03001183 // Parse XML data
Andrey Andreev8ff2b102018-02-28 22:44:09 +02001184 if ( ! xml_parse($parser, $data, TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +00001185 {
1186 $errstr = sprintf('XML error: %s at line %d',
Andrey Andreevc8709832012-04-04 13:43:53 +03001187 xml_error_string(xml_get_error_code($parser)),
1188 xml_get_current_line_number($parser));
vkeranovb497d2b2012-11-23 23:27:33 +02001189
Derek Allard2067d1a2008-11-13 22:59:24 +00001190 $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
1191 xml_parser_free($parser);
1192 return $r;
1193 }
1194 xml_parser_free($parser);
Barry Mienydd671972010-10-04 16:33:58 +02001195
Andrey Andreevc8709832012-04-04 13:43:53 +03001196 // Got ourselves some badness, it seems
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001197 if ($this->xh[$pname]['isf'] > 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001198 {
1199 if ($this->debug === TRUE)
1200 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001201 echo "---Invalid Return---\n".$this->xh[$pname]['isf_reason']."---Invalid Return---\n\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001202 }
Barry Mienydd671972010-10-04 16:33:58 +02001203
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001204 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 +00001205 }
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001206 elseif ( ! is_object($this->xh[$pname]['value']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001207 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001208 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 +00001209 }
Barry Mienydd671972010-10-04 16:33:58 +02001210
Andrey Andreevc8709832012-04-04 13:43:53 +03001211 // Display XML content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +00001212 if ($this->debug === TRUE)
1213 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001214 echo '<pre>';
Barry Mienydd671972010-10-04 16:33:58 +02001215
Andrey Andreev058102d2018-08-22 14:49:15 +03001216 if (count($this->xh[$pname]['headers']) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001217 {
1218 echo "---HEADERS---\n";
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001219 foreach ($this->xh[$pname]['headers'] as $header)
Derek Allard2067d1a2008-11-13 22:59:24 +00001220 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001221 echo $header."\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001222 }
1223 echo "---END HEADERS---\n\n";
1224 }
Barry Mienydd671972010-10-04 16:33:58 +02001225
Andrey Andreeva30faf92011-12-25 18:15:34 +02001226 echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n---PARSED---\n";
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001227 var_dump($this->xh[$pname]['value']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001228 echo "\n---END PARSED---</pre>";
1229 }
Barry Mienydd671972010-10-04 16:33:58 +02001230
Andrey Andreevc8709832012-04-04 13:43:53 +03001231 // Send response
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001232 $v = $this->xh[$pname]['value'];
1233 if ($this->xh[$pname]['isf'])
Derek Allard2067d1a2008-11-13 22:59:24 +00001234 {
1235 $errno_v = $v->me['struct']['faultCode'];
1236 $errstr_v = $v->me['struct']['faultString'];
1237 $errno = $errno_v->scalarval();
1238
Alex Bilbied261b1e2012-06-02 11:12:16 +01001239 if ($errno === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001240 {
1241 // FAULT returned, errno needs to reflect that
1242 $errno = -1;
1243 }
1244
1245 $r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
1246 }
1247 else
1248 {
1249 $r = new XML_RPC_Response($v);
1250 }
1251
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001252 $r->headers = $this->xh[$pname]['headers'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001253 return $r;
1254 }
Barry Mienydd671972010-10-04 16:33:58 +02001255
Andrey Andreevc8709832012-04-04 13:43:53 +03001256 // --------------------------------------------------------------------
1257
Derek Allard2067d1a2008-11-13 22:59:24 +00001258 // ------------------------------------
Derek Jones37f4b9c2011-07-01 17:56:50 -05001259 // Begin Return Message Parsing section
Derek Allard2067d1a2008-11-13 22:59:24 +00001260 // ------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001261
Derek Allard2067d1a2008-11-13 22:59:24 +00001262 // quick explanation of components:
Derek Jones37f4b9c2011-07-01 17:56:50 -05001263 // ac - used to accumulate values
1264 // isf - used to indicate a fault
1265 // lv - used to indicate "looking for a value": implements
Derek Allard2067d1a2008-11-13 22:59:24 +00001266 // the logic to allow values with no types to be strings
Derek Jones37f4b9c2011-07-01 17:56:50 -05001267 // params - used to store parameters in method calls
1268 // method - used to store method name
Derek Allard2067d1a2008-11-13 22:59:24 +00001269 // stack - array with parent tree of the xml element,
1270 // used to validate the nesting of elements
1271
Andrey Andreevc8709832012-04-04 13:43:53 +03001272 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001273
Andrey Andreevc8709832012-04-04 13:43:53 +03001274 /**
1275 * Start Element Handler
1276 *
1277 * @param string
1278 * @param string
1279 * @return void
1280 */
1281 public function open_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001282 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001283 $the_parser = (string) $the_parser;
1284
Derek Allard2067d1a2008-11-13 22:59:24 +00001285 // If invalid nesting, then return
1286 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001287
Derek Allard2067d1a2008-11-13 22:59:24 +00001288 // Evaluate and check for correct nesting of XML elements
Alex Bilbied261b1e2012-06-02 11:12:16 +01001289 if (count($this->xh[$the_parser]['stack']) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001290 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001291 if ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')
Derek Allard2067d1a2008-11-13 22:59:24 +00001292 {
1293 $this->xh[$the_parser]['isf'] = 2;
1294 $this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
1295 return;
1296 }
1297 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001298 // not top level element: see if parent is OK
1299 elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +00001300 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001301 $this->xh[$the_parser]['isf'] = 2;
vkeranovb497d2b2012-11-23 23:27:33 +02001302 $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 +03001303 return;
Derek Allard2067d1a2008-11-13 22:59:24 +00001304 }
Barry Mienydd671972010-10-04 16:33:58 +02001305
Andrey Andreevc8709832012-04-04 13:43:53 +03001306 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001307 {
1308 case 'STRUCT':
1309 case 'ARRAY':
1310 // Creates array for child elements
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001311 $cur_val = array('value' => array(), 'type' => $name);
Derek Allard2067d1a2008-11-13 22:59:24 +00001312 array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
Andrey Andreevc8709832012-04-04 13:43:53 +03001313 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001314 case 'METHODNAME':
1315 case 'NAME':
1316 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +03001317 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001318 case 'FAULT':
1319 $this->xh[$the_parser]['isf'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +03001320 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001321 case 'PARAM':
Pascal Kriete8761ef52011-02-14 13:13:52 -05001322 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +03001323 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001324 case 'VALUE':
1325 $this->xh[$the_parser]['vt'] = 'value';
1326 $this->xh[$the_parser]['ac'] = '';
1327 $this->xh[$the_parser]['lv'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +03001328 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001329 case 'I4':
1330 case 'INT':
1331 case 'STRING':
1332 case 'BOOLEAN':
1333 case 'DOUBLE':
1334 case 'DATETIME.ISO8601':
1335 case 'BASE64':
Alex Bilbied261b1e2012-06-02 11:12:16 +01001336 if ($this->xh[$the_parser]['vt'] !== 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +00001337 {
1338 //two data elements inside a value: an error occurred!
1339 $this->xh[$the_parser]['isf'] = 2;
vkeranovb497d2b2012-11-23 23:27:33 +02001340 $this->xh[$the_parser]['isf_reason'] = 'There is a '.$name.' element following a '
Andrey Andreevc8709832012-04-04 13:43:53 +03001341 .$this->xh[$the_parser]['vt'].' element inside a single value';
Derek Allard2067d1a2008-11-13 22:59:24 +00001342 return;
1343 }
Barry Mienydd671972010-10-04 16:33:58 +02001344
Derek Allard2067d1a2008-11-13 22:59:24 +00001345 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +03001346 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001347 case 'MEMBER':
1348 // Set name of <member> to nothing to prevent errors later if no <name> is found
1349 $this->xh[$the_parser]['valuestack'][0]['name'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001350
Derek Allard2067d1a2008-11-13 22:59:24 +00001351 // Set NULL value to check to see if value passed for this param/member
Pascal Kriete8761ef52011-02-14 13:13:52 -05001352 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +03001353 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001354 case 'DATA':
1355 case 'METHODCALL':
1356 case 'METHODRESPONSE':
1357 case 'PARAMS':
1358 // valid elements that add little to processing
Andrey Andreevc8709832012-04-04 13:43:53 +03001359 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001360 default:
1361 /// An Invalid Element is Found, so we have trouble
1362 $this->xh[$the_parser]['isf'] = 2;
Andrey Andreevc8709832012-04-04 13:43:53 +03001363 $this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;
1364 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001365 }
Barry Mienydd671972010-10-04 16:33:58 +02001366
Derek Allard2067d1a2008-11-13 22:59:24 +00001367 // Add current element name to stack, to allow validation of nesting
1368 array_unshift($this->xh[$the_parser]['stack'], $name);
1369
Alex Bilbied261b1e2012-06-02 11:12:16 +01001370 $name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001371 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001372
Andrey Andreevc8709832012-04-04 13:43:53 +03001373 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001374
Andrey Andreevc8709832012-04-04 13:43:53 +03001375 /**
1376 * End Element Handler
1377 *
1378 * @param string
1379 * @param string
1380 * @return void
1381 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001382 public function closing_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001383 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001384 $the_parser = (string) $the_parser;
1385
Derek Allard2067d1a2008-11-13 22:59:24 +00001386 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001387
Derek Allard2067d1a2008-11-13 22:59:24 +00001388 // Remove current element from stack and set variable
1389 // NOTE: If the XML validates, then we do not have to worry about
Andrey Andreevc8709832012-04-04 13:43:53 +03001390 // the opening and closing of elements. Nesting is checked on the opening
Derek Allard2067d1a2008-11-13 22:59:24 +00001391 // tag so we be safe there as well.
Barry Mienydd671972010-10-04 16:33:58 +02001392
Derek Allard2067d1a2008-11-13 22:59:24 +00001393 $curr_elem = array_shift($this->xh[$the_parser]['stack']);
Barry Mienydd671972010-10-04 16:33:58 +02001394
Andrey Andreevc8709832012-04-04 13:43:53 +03001395 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001396 {
1397 case 'STRUCT':
1398 case 'ARRAY':
1399 $cur_val = array_shift($this->xh[$the_parser]['valuestack']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001400 $this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();
Derek Allard2067d1a2008-11-13 22:59:24 +00001401 $this->xh[$the_parser]['vt'] = strtolower($name);
Andrey Andreevc8709832012-04-04 13:43:53 +03001402 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001403 case 'NAME':
1404 $this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
Andrey Andreevc8709832012-04-04 13:43:53 +03001405 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001406 case 'BOOLEAN':
1407 case 'I4':
1408 case 'INT':
1409 case 'STRING':
1410 case 'DOUBLE':
1411 case 'DATETIME.ISO8601':
1412 case 'BASE64':
1413 $this->xh[$the_parser]['vt'] = strtolower($name);
Barry Mienydd671972010-10-04 16:33:58 +02001414
Alex Bilbied261b1e2012-06-02 11:12:16 +01001415 if ($name === 'STRING')
Derek Allard2067d1a2008-11-13 22:59:24 +00001416 {
1417 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1418 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001419 elseif ($name === 'DATETIME.ISO8601')
Derek Allard2067d1a2008-11-13 22:59:24 +00001420 {
1421 $this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime;
1422 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1423 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001424 elseif ($name === 'BASE64')
Derek Allard2067d1a2008-11-13 22:59:24 +00001425 {
1426 $this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
1427 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001428 elseif ($name === 'BOOLEAN')
Derek Allard2067d1a2008-11-13 22:59:24 +00001429 {
1430 // Translated BOOLEAN values to TRUE AND FALSE
Andrey Andreevc8709832012-04-04 13:43:53 +03001431 $this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001432 }
1433 elseif ($name=='DOUBLE')
1434 {
1435 // we have a DOUBLE
1436 // we must check that only 0123456789-.<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001437 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])
1438 ? (float) $this->xh[$the_parser]['ac']
1439 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001440 }
1441 else
1442 {
1443 // we have an I4/INT
1444 // we must check that only 0123456789-<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001445 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])
George Petsagourakis306b3782012-05-02 20:31:08 +03001446 ? (int) $this->xh[$the_parser]['ac']
Andrey Andreevc8709832012-04-04 13:43:53 +03001447 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001448 }
1449 $this->xh[$the_parser]['ac'] = '';
1450 $this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
Andrey Andreevc8709832012-04-04 13:43:53 +03001451 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001452 case 'VALUE':
1453 // This if() detects if no scalar was inside <VALUE></VALUE>
vkeranovb497d2b2012-11-23 23:27:33 +02001454 if ($this->xh[$the_parser]['vt'] == 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +00001455 {
1456 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1457 $this->xh[$the_parser]['vt'] = $this->xmlrpcString;
1458 }
Barry Mienydd671972010-10-04 16:33:58 +02001459
Derek Allard2067d1a2008-11-13 22:59:24 +00001460 // build the XML-RPC value out of the data received, and substitute it
1461 $temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
Barry Mienydd671972010-10-04 16:33:58 +02001462
Alex Bilbied261b1e2012-06-02 11:12:16 +01001463 if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')
Derek Allard2067d1a2008-11-13 22:59:24 +00001464 {
1465 // Array
1466 $this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
1467 }
1468 else
1469 {
1470 // Struct
1471 $this->xh[$the_parser]['value'] = $temp;
1472 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001473 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001474 case 'MEMBER':
Andrey Andreevc8709832012-04-04 13:43:53 +03001475 $this->xh[$the_parser]['ac'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001476
Derek Allard2067d1a2008-11-13 22:59:24 +00001477 // If value add to array in the stack for the last element built
1478 if ($this->xh[$the_parser]['value'])
1479 {
1480 $this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
1481 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001482 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001483 case 'DATA':
Andrey Andreevc8709832012-04-04 13:43:53 +03001484 $this->xh[$the_parser]['ac'] = '';
1485 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001486 case 'PARAM':
1487 if ($this->xh[$the_parser]['value'])
1488 {
1489 $this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
1490 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001491 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001492 case 'METHODNAME':
1493 $this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001494 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001495 case 'PARAMS':
1496 case 'FAULT':
1497 case 'METHODCALL':
1498 case 'METHORESPONSE':
1499 // We're all good kids with nuthin' to do
Andrey Andreevc8709832012-04-04 13:43:53 +03001500 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001501 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001502 // End of an Invalid Element. Taken care of during the opening tag though
1503 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001504 }
1505 }
1506
Andrey Andreevc8709832012-04-04 13:43:53 +03001507 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001508
Andrey Andreevc8709832012-04-04 13:43:53 +03001509 /**
1510 * Parse character data
1511 *
1512 * @param string
1513 * @param string
1514 * @return void
1515 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001516 public function character_data($the_parser, $data)
Derek Allard2067d1a2008-11-13 22:59:24 +00001517 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001518 $the_parser = (string) $the_parser;
1519
Derek Allard2067d1a2008-11-13 22:59:24 +00001520 if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
Barry Mienydd671972010-10-04 16:33:58 +02001521
Derek Allard2067d1a2008-11-13 22:59:24 +00001522 // If a value has not been found
Alex Bilbied261b1e2012-06-02 11:12:16 +01001523 if ($this->xh[$the_parser]['lv'] !== 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001524 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001525 if ($this->xh[$the_parser]['lv'] === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001526 {
1527 $this->xh[$the_parser]['lv'] = 2; // Found a value
1528 }
Barry Mienydd671972010-10-04 16:33:58 +02001529
Andrey Andreevc8709832012-04-04 13:43:53 +03001530 if ( ! isset($this->xh[$the_parser]['ac']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001531 {
1532 $this->xh[$the_parser]['ac'] = '';
1533 }
Barry Mienydd671972010-10-04 16:33:58 +02001534
Derek Allard2067d1a2008-11-13 22:59:24 +00001535 $this->xh[$the_parser]['ac'] .= $data;
1536 }
1537 }
Barry Mienydd671972010-10-04 16:33:58 +02001538
Andrey Andreevc8709832012-04-04 13:43:53 +03001539 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001540
Andrey Andreevc8709832012-04-04 13:43:53 +03001541 /**
1542 * Add parameter
1543 *
1544 * @param mixed
1545 * @return void
1546 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001547 public function addParam($par)
1548 {
1549 $this->params[] = $par;
1550 }
Barry Mienydd671972010-10-04 16:33:58 +02001551
Andrey Andreevc8709832012-04-04 13:43:53 +03001552 // --------------------------------------------------------------------
1553
1554 /**
1555 * Output parameters
1556 *
Andrey Andreeve417f042014-01-08 14:48:01 +02001557 * @param array $array
Andrey Andreevc8709832012-04-04 13:43:53 +03001558 * @return array
1559 */
Andrey Andreeve417f042014-01-08 14:48:01 +02001560 public function output_parameters(array $array = array())
Derek Allard2067d1a2008-11-13 22:59:24 +00001561 {
Barry Mienydd671972010-10-04 16:33:58 +02001562 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +02001563
Andrey Andreeve417f042014-01-08 14:48:01 +02001564 if ( ! empty($array))
Derek Allard2067d1a2008-11-13 22:59:24 +00001565 {
Andrey Andreev4316a152017-01-20 15:46:17 +02001566 foreach ($array as $key => &$value)
Derek Allard2067d1a2008-11-13 22:59:24 +00001567 {
Andrey Andreev4316a152017-01-20 15:46:17 +02001568 if (is_array($value))
Derek Allard2067d1a2008-11-13 22:59:24 +00001569 {
Andrey Andreev4316a152017-01-20 15:46:17 +02001570 $array[$key] = $this->output_parameters($value);
Derek Allard2067d1a2008-11-13 22:59:24 +00001571 }
Andrey Andreeve417f042014-01-08 14:48:01 +02001572 elseif ($key !== 'bits' && $this->xss_clean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001573 {
Derek Jonesa9647e82010-03-02 22:59:07 -06001574 // 'bits' is for the MetaWeblog API image bits
1575 // @todo - this needs to be made more general purpose
Andrey Andreev4316a152017-01-20 15:46:17 +02001576 $array[$key] = $CI->security->xss_clean($value);
Derek Allard2067d1a2008-11-13 22:59:24 +00001577 }
1578 }
Barry Mienydd671972010-10-04 16:33:58 +02001579
Andrey Andreevc8709832012-04-04 13:43:53 +03001580 return $array;
Derek Allard2067d1a2008-11-13 22:59:24 +00001581 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001582
1583 $parameters = array();
1584
1585 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001586 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001587 $a_param = $this->decode_message($this->params[$i]);
Barry Mienydd671972010-10-04 16:33:58 +02001588
Andrey Andreevc8709832012-04-04 13:43:53 +03001589 if (is_array($a_param))
Derek Allard2067d1a2008-11-13 22:59:24 +00001590 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001591 $parameters[] = $this->output_parameters($a_param);
1592 }
1593 else
1594 {
1595 $parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;
Barry Mienydd671972010-10-04 16:33:58 +02001596 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001597 }
Barry Mienydd671972010-10-04 16:33:58 +02001598
Derek Allard2067d1a2008-11-13 22:59:24 +00001599 return $parameters;
1600 }
Barry Mienydd671972010-10-04 16:33:58 +02001601
Andrey Andreevc8709832012-04-04 13:43:53 +03001602 // --------------------------------------------------------------------
1603
1604 /**
1605 * Decode message
1606 *
1607 * @param object
1608 * @return mixed
1609 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001610 public function decode_message($param)
Derek Allard2067d1a2008-11-13 22:59:24 +00001611 {
1612 $kind = $param->kindOf();
1613
Alex Bilbied261b1e2012-06-02 11:12:16 +01001614 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +00001615 {
1616 return $param->scalarval();
1617 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001618 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +00001619 {
1620 reset($param->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001621 $b = current($param->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001622 $arr = array();
1623
Andrey Andreevc8709832012-04-04 13:43:53 +03001624 for ($i = 0, $c = count($b); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001625 {
1626 $arr[] = $this->decode_message($param->me['array'][$i]);
1627 }
Barry Mienydd671972010-10-04 16:33:58 +02001628
Derek Allard2067d1a2008-11-13 22:59:24 +00001629 return $arr;
1630 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001631 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +00001632 {
1633 reset($param->me['struct']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001634 $arr = array();
1635
Andrey Andreev4316a152017-01-20 15:46:17 +02001636 foreach ($param->me['struct'] as $key => &$value)
Derek Allard2067d1a2008-11-13 22:59:24 +00001637 {
1638 $arr[$key] = $this->decode_message($value);
1639 }
Barry Mienydd671972010-10-04 16:33:58 +02001640
Derek Allard2067d1a2008-11-13 22:59:24 +00001641 return $arr;
1642 }
1643 }
Barry Mienydd671972010-10-04 16:33:58 +02001644
Andrey Andreevc8709832012-04-04 13:43:53 +03001645} // END XML_RPC_Message Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001646
1647/**
1648 * XML-RPC Values class
1649 *
1650 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -05001651 * @author EllisLab Dev Team
Andrey Andreevbd202c92016-01-11 12:50:18 +02001652 * @link https://codeigniter.com/user_guide/libraries/xmlrpc.html
Derek Allard2067d1a2008-11-13 22:59:24 +00001653 */
1654class XML_RPC_Values extends CI_Xmlrpc
1655{
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001656 /**
1657 * Value data
1658 *
1659 * @var array
1660 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001661 public $me = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001662
1663 /**
1664 * Value type
1665 *
1666 * @var int
1667 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001668 public $mytype = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001669
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001670 // --------------------------------------------------------------------
1671
Andrey Andreevc8709832012-04-04 13:43:53 +03001672 /**
1673 * Constructor
1674 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001675 * @param mixed $val
1676 * @param string $type
Andrey Andreevc8709832012-04-04 13:43:53 +03001677 * @return void
1678 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001679 public function __construct($val = -1, $type = '')
Barry Mienydd671972010-10-04 16:33:58 +02001680 {
Greg Akera9263282010-11-10 15:26:43 -06001681 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +02001682
Alex Bilbied261b1e2012-06-02 11:12:16 +01001683 if ($val !== -1 OR $type !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001684 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001685 $type = $type === '' ? 'string' : $type;
Barry Mienydd671972010-10-04 16:33:58 +02001686
Dimitar740480a2012-10-05 13:24:59 +03001687 if ($this->xmlrpcTypes[$type] == 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001688 {
vkeranovb497d2b2012-11-23 23:27:33 +02001689 $this->addScalar($val, $type);
Derek Allard2067d1a2008-11-13 22:59:24 +00001690 }
Dimitar740480a2012-10-05 13:24:59 +03001691 elseif ($this->xmlrpcTypes[$type] == 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001692 {
1693 $this->addArray($val);
1694 }
Dimitar740480a2012-10-05 13:24:59 +03001695 elseif ($this->xmlrpcTypes[$type] == 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001696 {
1697 $this->addStruct($val);
1698 }
1699 }
1700 }
1701
Andrey Andreevc8709832012-04-04 13:43:53 +03001702 // --------------------------------------------------------------------
1703
1704 /**
1705 * Add scalar value
1706 *
1707 * @param scalar
1708 * @param string
1709 * @return int
1710 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001711 public function addScalar($val, $type = 'string')
Derek Allard2067d1a2008-11-13 22:59:24 +00001712 {
1713 $typeof = $this->xmlrpcTypes[$type];
Barry Mienydd671972010-10-04 16:33:58 +02001714
Alex Bilbied261b1e2012-06-02 11:12:16 +01001715 if ($this->mytype === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001716 {
1717 echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
1718 return 0;
1719 }
Barry Mienydd671972010-10-04 16:33:58 +02001720
Dimitar740480a2012-10-05 13:24:59 +03001721 if ($typeof != 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001722 {
1723 echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';
1724 return 0;
1725 }
1726
Alex Bilbied261b1e2012-06-02 11:12:16 +01001727 if ($type === $this->xmlrpcBoolean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001728 {
Andrey Andreev3f3f1352012-09-05 16:39:28 +03001729 $val = (int) (strcasecmp($val, 'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
Derek Allard2067d1a2008-11-13 22:59:24 +00001730 }
1731
Alex Bilbied261b1e2012-06-02 11:12:16 +01001732 if ($this->mytype === 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001733 {
1734 // adding to an array here
1735 $ar = $this->me['array'];
1736 $ar[] = new XML_RPC_Values($val, $type);
1737 $this->me['array'] = $ar;
1738 }
1739 else
1740 {
1741 // a scalar, so set the value and remember we're scalar
1742 $this->me[$type] = $val;
1743 $this->mytype = $typeof;
1744 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001745
Derek Allard2067d1a2008-11-13 22:59:24 +00001746 return 1;
1747 }
1748
Andrey Andreevc8709832012-04-04 13:43:53 +03001749 // --------------------------------------------------------------------
1750
1751 /**
1752 * Add array value
1753 *
1754 * @param array
1755 * @return int
1756 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001757 public function addArray($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001758 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001759 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001760 {
Andrey Andreev3ca060a2013-11-27 16:30:31 +02001761 echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
Derek Allard2067d1a2008-11-13 22:59:24 +00001762 return 0;
1763 }
1764
1765 $this->mytype = $this->xmlrpcTypes['array'];
1766 $this->me['array'] = $vals;
1767 return 1;
1768 }
1769
Andrey Andreevc8709832012-04-04 13:43:53 +03001770 // --------------------------------------------------------------------
1771
1772 /**
1773 * Add struct value
1774 *
1775 * @param object
1776 * @return int
1777 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001778 public function addStruct($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001779 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001780 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001781 {
Andrey Andreev3ca060a2013-11-27 16:30:31 +02001782 echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
Derek Allard2067d1a2008-11-13 22:59:24 +00001783 return 0;
1784 }
1785 $this->mytype = $this->xmlrpcTypes['struct'];
1786 $this->me['struct'] = $vals;
1787 return 1;
1788 }
1789
Andrey Andreevc8709832012-04-04 13:43:53 +03001790 // --------------------------------------------------------------------
1791
1792 /**
1793 * Get value type
1794 *
1795 * @return string
1796 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001797 public function kindOf()
Derek Allard2067d1a2008-11-13 22:59:24 +00001798 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001799 switch ($this->mytype)
Derek Allard2067d1a2008-11-13 22:59:24 +00001800 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001801 case 3: return 'struct';
1802 case 2: return 'array';
1803 case 1: return 'scalar';
1804 default: return 'undef';
Derek Allard2067d1a2008-11-13 22:59:24 +00001805 }
1806 }
1807
Andrey Andreevc8709832012-04-04 13:43:53 +03001808 // --------------------------------------------------------------------
1809
1810 /**
1811 * Serialize data
1812 *
1813 * @param string
1814 * @param mixed
Gabriel Potkánye8a27922015-02-04 09:52:50 +01001815 * @return string
Andrey Andreevc8709832012-04-04 13:43:53 +03001816 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001817 public function serializedata($typ, $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001818 {
1819 $rs = '';
Derek Jonesa9647e82010-03-02 22:59:07 -06001820
Andrey Andreevc8709832012-04-04 13:43:53 +03001821 switch ($this->xmlrpcTypes[$typ])
Derek Allard2067d1a2008-11-13 22:59:24 +00001822 {
1823 case 3:
1824 // struct
1825 $rs .= "<struct>\n";
1826 reset($val);
Andrey Andreev4316a152017-01-20 15:46:17 +02001827 foreach ($val as $key2 => &$val2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001828 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001829 $rs .= "<member>\n<name>{$key2}</name>\n".$this->serializeval($val2)."</member>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001830 }
1831 $rs .= '</struct>';
Andrey Andreevc8709832012-04-04 13:43:53 +03001832 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001833 case 2:
1834 // array
1835 $rs .= "<array>\n<data>\n";
Andrey Andreevc8709832012-04-04 13:43:53 +03001836 for ($i = 0, $c = count($val); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001837 {
1838 $rs .= $this->serializeval($val[$i]);
1839 }
Andrey Andreeva30faf92011-12-25 18:15:34 +02001840 $rs .= "</data>\n</array>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001841 break;
1842 case 1:
1843 // others
1844 switch ($typ)
1845 {
1846 case $this->xmlrpcBase64:
Andrey Andreevc8709832012-04-04 13:43:53 +03001847 $rs .= '<'.$typ.'>'.base64_encode( (string) $val).'</'.$typ.">\n";
1848 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001849 case $this->xmlrpcBoolean:
Andrey Andreevc8709832012-04-04 13:43:53 +03001850 $rs .= '<'.$typ.'>'.( (bool) $val ? '1' : '0').'</'.$typ.">\n";
1851 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001852 case $this->xmlrpcString:
Andrey Andreevc8709832012-04-04 13:43:53 +03001853 $rs .= '<'.$typ.'>'.htmlspecialchars( (string) $val).'</'.$typ.">\n";
1854 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001855 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001856 $rs .= '<'.$typ.'>'.$val.'</'.$typ.">\n";
1857 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001858 }
1859 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001860 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001861 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001862
Derek Allard2067d1a2008-11-13 22:59:24 +00001863 return $rs;
1864 }
1865
Andrey Andreevc8709832012-04-04 13:43:53 +03001866 // --------------------------------------------------------------------
1867
1868 /**
1869 * Serialize class
1870 *
1871 * @return string
1872 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001873 public function serialize_class()
Derek Allard2067d1a2008-11-13 22:59:24 +00001874 {
1875 return $this->serializeval($this);
1876 }
1877
Andrey Andreevc8709832012-04-04 13:43:53 +03001878 // --------------------------------------------------------------------
1879
1880 /**
1881 * Serialize value
1882 *
1883 * @param object
1884 * @return string
1885 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001886 public function serializeval($o)
Derek Allard2067d1a2008-11-13 22:59:24 +00001887 {
Andrey Andreev4316a152017-01-20 15:46:17 +02001888 $array = $o->me;
Instructor, Computer Systems Technology11d59d72017-04-15 13:35:10 -07001889 list($value, $type) = array(reset($array), key($array));
Andrey Andreev4316a152017-01-20 15:46:17 +02001890 return "<value>\n".$this->serializedata($type, $value)."</value>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001891 }
Barry Mienydd671972010-10-04 16:33:58 +02001892
Andrey Andreevc8709832012-04-04 13:43:53 +03001893 // --------------------------------------------------------------------
1894
1895 /**
1896 * Scalar value
1897 *
1898 * @return mixed
1899 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001900 public function scalarval()
Derek Allard2067d1a2008-11-13 22:59:24 +00001901 {
Andrey Andreev4316a152017-01-20 15:46:17 +02001902 return reset($this->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001903 }
1904
Andrey Andreevc8709832012-04-04 13:43:53 +03001905 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001906
Andrey Andreevc8709832012-04-04 13:43:53 +03001907 /**
1908 * Encode time in ISO-8601 form.
1909 * Useful for sending time in XML-RPC
1910 *
1911 * @param int unix timestamp
1912 * @param bool
1913 * @return string
1914 */
1915 public function iso8601_encode($time, $utc = FALSE)
Barry Mienydd671972010-10-04 16:33:58 +02001916 {
Andrey Andreev62090152011-12-30 12:49:27 +02001917 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 +00001918 }
Barry Mienydd671972010-10-04 16:33:58 +02001919
Andrey Andreevc8709832012-04-04 13:43:53 +03001920} // END XML_RPC_Values Class