blob: 7186646dac97a71b7ae67e73f2d025799914a547 [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 *
Andrey Andreev125ef472016-01-11 12:33:00 +02009 * Copyright (c) 2014 - 2016, 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/)
Andrey Andreev125ef472016-01-11 12:33:00 +020032 * @copyright Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020033 * @license http://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 /**
241 * XML-RPC Reponse
242 *
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 {
463 while (list($k) = each($value[0]))
464 {
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 {
934 while (list($key) = each($array))
935 {
936 if (is_array($array[$key]))
937 {
938 $array[$key] = $this->decode($array[$key]);
939 }
Andrey Andreeve417f042014-01-08 14:48:01 +0200940 elseif ($this->xss_clean)
Derek Allard2067d1a2008-11-13 22:59:24 +0000941 {
Andrey Andreeve417f042014-01-08 14:48:01 +0200942 $array[$key] = $CI->security->xss_clean($array[$key]);
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
Pascal Kriete14287f32011-02-14 13:39:34 -0500996 while (list($key,$value) = each($xmlrpc_val->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000997 {
998 $arr[$key] = $this->xmlrpc_decoder($value);
999 }
1000 return $arr;
1001 }
1002 }
Barry Mienydd671972010-10-04 16:33:58 +02001003
Andrey Andreevc8709832012-04-04 13:43:53 +03001004 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001005
Andrey Andreevc8709832012-04-04 13:43:53 +03001006 /**
1007 * ISO-8601 time to server or UTC time
1008 *
1009 * @param string
1010 * @param bool
1011 * @return int unix timestamp
1012 */
1013 public function iso8601_decode($time, $utc = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001014 {
vkeranovb497d2b2012-11-23 23:27:33 +02001015 // Return a time in the localtime, or UTC
Derek Allard2067d1a2008-11-13 22:59:24 +00001016 $t = 0;
1017 if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))
1018 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001019 $fnc = ($utc === TRUE) ? 'gmmktime' : 'mktime';
Pascal Kriete14287f32011-02-14 13:39:34 -05001020 $t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001021 }
1022 return $t;
1023 }
Barry Mienydd671972010-10-04 16:33:58 +02001024
Andrey Andreevc8709832012-04-04 13:43:53 +03001025} // END XML_RPC_Response Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001026
1027/**
1028 * XML-RPC Message class
1029 *
1030 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -05001031 * @author EllisLab Dev Team
Andrey Andreevbd202c92016-01-11 12:50:18 +02001032 * @link https://codeigniter.com/user_guide/libraries/xmlrpc.html
Derek Allard2067d1a2008-11-13 22:59:24 +00001033 */
1034class XML_RPC_Message extends CI_Xmlrpc
1035{
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001036
1037 /**
1038 * Payload
1039 *
1040 * @var string
1041 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001042 public $payload;
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001043
1044 /**
1045 * Method name
1046 *
1047 * @var string
1048 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001049 public $method_name;
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001050
1051 /**
1052 * Parameter list
1053 *
1054 * @var array
1055 */
Andrey Andreevc8709832012-04-04 13:43:53 +03001056 public $params = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001057
1058 /**
1059 * XH?
1060 *
1061 * @var array
1062 */
Andrey Andreevc8709832012-04-04 13:43:53 +03001063 public $xh = array();
Derek Allard2067d1a2008-11-13 22:59:24 +00001064
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001065 // --------------------------------------------------------------------
1066
Andrey Andreevc8709832012-04-04 13:43:53 +03001067 /**
1068 * Constructor
1069 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001070 * @param string $method
1071 * @param array $pars
Andrey Andreevc8709832012-04-04 13:43:53 +03001072 * @return void
1073 */
1074 public function __construct($method, $pars = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001075 {
Greg Akera9263282010-11-10 15:26:43 -06001076 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +02001077
Derek Allard2067d1a2008-11-13 22:59:24 +00001078 $this->method_name = $method;
Derek Jones33559102009-02-02 18:50:38 +00001079 if (is_array($pars) && count($pars) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001080 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001081 for ($i = 0, $c = count($pars); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001082 {
1083 // $pars[$i] = XML_RPC_Values
1084 $this->params[] = $pars[$i];
1085 }
1086 }
1087 }
Barry Mienydd671972010-10-04 16:33:58 +02001088
Andrey Andreevc8709832012-04-04 13:43:53 +03001089 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001090
Andrey Andreevc8709832012-04-04 13:43:53 +03001091 /**
1092 * Create Payload to Send
1093 *
1094 * @return void
1095 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001096 public function createPayload()
Derek Allard2067d1a2008-11-13 22:59:24 +00001097 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001098 $this->payload = '<?xml version="1.0"?'.">\r\n<methodCall>\r\n"
1099 .'<methodName>'.$this->method_name."</methodName>\r\n"
1100 ."<params>\r\n";
Barry Mienydd671972010-10-04 16:33:58 +02001101
Andrey Andreeva30faf92011-12-25 18:15:34 +02001102 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001103 {
1104 // $p = XML_RPC_Values
1105 $p = $this->params[$i];
1106 $this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n";
1107 }
Barry Mienydd671972010-10-04 16:33:58 +02001108
Derek Allard2067d1a2008-11-13 22:59:24 +00001109 $this->payload .= "</params>\r\n</methodCall>\r\n";
1110 }
Barry Mienydd671972010-10-04 16:33:58 +02001111
Andrey Andreevc8709832012-04-04 13:43:53 +03001112 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001113
Andrey Andreevc8709832012-04-04 13:43:53 +03001114 /**
1115 * Parse External XML-RPC Server's Response
1116 *
1117 * @param resource
1118 * @return object
1119 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001120 public function parseResponse($fp)
Derek Allard2067d1a2008-11-13 22:59:24 +00001121 {
1122 $data = '';
Barry Mienydd671972010-10-04 16:33:58 +02001123
Pascal Kriete14287f32011-02-14 13:39:34 -05001124 while ($datum = fread($fp, 4096))
Derek Allard2067d1a2008-11-13 22:59:24 +00001125 {
1126 $data .= $datum;
1127 }
Barry Mienydd671972010-10-04 16:33:58 +02001128
Andrey Andreevc8709832012-04-04 13:43:53 +03001129 // Display HTTP content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +00001130 if ($this->debug === TRUE)
1131 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001132 echo "<pre>---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n</pre>";
Derek Allard2067d1a2008-11-13 22:59:24 +00001133 }
Barry Mienydd671972010-10-04 16:33:58 +02001134
Andrey Andreevc8709832012-04-04 13:43:53 +03001135 // Check for data
Andrey Andreeva30faf92011-12-25 18:15:34 +02001136 if ($data === '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001137 {
1138 error_log($this->xmlrpcstr['no_data']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001139 return new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001140 }
Barry Mienydd671972010-10-04 16:33:58 +02001141
Andrey Andreevc8709832012-04-04 13:43:53 +03001142 // Check for HTTP 200 Response
Andrey Andreev3dad2e72012-06-14 15:10:56 +03001143 if (strpos($data, 'HTTP') === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
Derek Allard2067d1a2008-11-13 22:59:24 +00001144 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001145 $errstr = substr($data, 0, strpos($data, "\n")-1);
1146 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');
Derek Allard2067d1a2008-11-13 22:59:24 +00001147 }
Barry Mienydd671972010-10-04 16:33:58 +02001148
Derek Allard2067d1a2008-11-13 22:59:24 +00001149 //-------------------------------------
vkeranovb497d2b2012-11-23 23:27:33 +02001150 // Create and Set Up XML Parser
Derek Allard2067d1a2008-11-13 22:59:24 +00001151 //-------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001152
Derek Allard2067d1a2008-11-13 22:59:24 +00001153 $parser = xml_parser_create($this->xmlrpc_defencoding);
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001154 $pname = (string) $parser;
1155 $this->xh[$pname] = array(
1156 'isf' => 0,
1157 'ac' => '',
1158 'headers' => array(),
1159 'stack' => array(),
1160 'valuestack' => array(),
1161 'isf_reason' => 0
1162 );
Derek Allard2067d1a2008-11-13 22:59:24 +00001163
1164 xml_set_object($parser, $this);
Andrey Andreevc8709832012-04-04 13:43:53 +03001165 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +00001166 xml_set_element_handler($parser, 'open_tag', 'closing_tag');
1167 xml_set_character_data_handler($parser, 'character_data');
1168 //xml_set_default_handler($parser, 'default_handler');
1169
Andrey Andreevc8709832012-04-04 13:43:53 +03001170 // Get headers
Derek Allard2067d1a2008-11-13 22:59:24 +00001171 $lines = explode("\r\n", $data);
1172 while (($line = array_shift($lines)))
1173 {
1174 if (strlen($line) < 1)
1175 {
1176 break;
1177 }
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001178 $this->xh[$pname]['headers'][] = $line;
Derek Allard2067d1a2008-11-13 22:59:24 +00001179 }
1180 $data = implode("\r\n", $lines);
Barry Mienydd671972010-10-04 16:33:58 +02001181
Andrey Andreevc8709832012-04-04 13:43:53 +03001182 // Parse XML data
Derek Jones33559102009-02-02 18:50:38 +00001183 if ( ! xml_parse($parser, $data, count($data)))
Derek Allard2067d1a2008-11-13 22:59:24 +00001184 {
1185 $errstr = sprintf('XML error: %s at line %d',
Andrey Andreevc8709832012-04-04 13:43:53 +03001186 xml_error_string(xml_get_error_code($parser)),
1187 xml_get_current_line_number($parser));
vkeranovb497d2b2012-11-23 23:27:33 +02001188
Derek Allard2067d1a2008-11-13 22:59:24 +00001189 $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
1190 xml_parser_free($parser);
1191 return $r;
1192 }
1193 xml_parser_free($parser);
Barry Mienydd671972010-10-04 16:33:58 +02001194
Andrey Andreevc8709832012-04-04 13:43:53 +03001195 // Got ourselves some badness, it seems
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001196 if ($this->xh[$pname]['isf'] > 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001197 {
1198 if ($this->debug === TRUE)
1199 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001200 echo "---Invalid Return---\n".$this->xh[$pname]['isf_reason']."---Invalid Return---\n\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001201 }
Barry Mienydd671972010-10-04 16:33:58 +02001202
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001203 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 +00001204 }
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001205 elseif ( ! is_object($this->xh[$pname]['value']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001206 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001207 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 +00001208 }
Barry Mienydd671972010-10-04 16:33:58 +02001209
Andrey Andreevc8709832012-04-04 13:43:53 +03001210 // Display XML content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +00001211 if ($this->debug === TRUE)
1212 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001213 echo '<pre>';
Barry Mienydd671972010-10-04 16:33:58 +02001214
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001215 if (count($this->xh[$pname]['headers'] > 0))
Derek Allard2067d1a2008-11-13 22:59:24 +00001216 {
1217 echo "---HEADERS---\n";
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001218 foreach ($this->xh[$pname]['headers'] as $header)
Derek Allard2067d1a2008-11-13 22:59:24 +00001219 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001220 echo $header."\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001221 }
1222 echo "---END HEADERS---\n\n";
1223 }
Barry Mienydd671972010-10-04 16:33:58 +02001224
Andrey Andreeva30faf92011-12-25 18:15:34 +02001225 echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n---PARSED---\n";
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001226 var_dump($this->xh[$pname]['value']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001227 echo "\n---END PARSED---</pre>";
1228 }
Barry Mienydd671972010-10-04 16:33:58 +02001229
Andrey Andreevc8709832012-04-04 13:43:53 +03001230 // Send response
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001231 $v = $this->xh[$pname]['value'];
1232 if ($this->xh[$pname]['isf'])
Derek Allard2067d1a2008-11-13 22:59:24 +00001233 {
1234 $errno_v = $v->me['struct']['faultCode'];
1235 $errstr_v = $v->me['struct']['faultString'];
1236 $errno = $errno_v->scalarval();
1237
Alex Bilbied261b1e2012-06-02 11:12:16 +01001238 if ($errno === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001239 {
1240 // FAULT returned, errno needs to reflect that
1241 $errno = -1;
1242 }
1243
1244 $r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
1245 }
1246 else
1247 {
1248 $r = new XML_RPC_Response($v);
1249 }
1250
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001251 $r->headers = $this->xh[$pname]['headers'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001252 return $r;
1253 }
Barry Mienydd671972010-10-04 16:33:58 +02001254
Andrey Andreevc8709832012-04-04 13:43:53 +03001255 // --------------------------------------------------------------------
1256
Derek Allard2067d1a2008-11-13 22:59:24 +00001257 // ------------------------------------
Derek Jones37f4b9c2011-07-01 17:56:50 -05001258 // Begin Return Message Parsing section
Derek Allard2067d1a2008-11-13 22:59:24 +00001259 // ------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001260
Derek Allard2067d1a2008-11-13 22:59:24 +00001261 // quick explanation of components:
Derek Jones37f4b9c2011-07-01 17:56:50 -05001262 // ac - used to accumulate values
1263 // isf - used to indicate a fault
1264 // lv - used to indicate "looking for a value": implements
Derek Allard2067d1a2008-11-13 22:59:24 +00001265 // the logic to allow values with no types to be strings
Derek Jones37f4b9c2011-07-01 17:56:50 -05001266 // params - used to store parameters in method calls
1267 // method - used to store method name
Derek Allard2067d1a2008-11-13 22:59:24 +00001268 // stack - array with parent tree of the xml element,
1269 // used to validate the nesting of elements
1270
Andrey Andreevc8709832012-04-04 13:43:53 +03001271 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001272
Andrey Andreevc8709832012-04-04 13:43:53 +03001273 /**
1274 * Start Element Handler
1275 *
1276 * @param string
1277 * @param string
1278 * @return void
1279 */
1280 public function open_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001281 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001282 $the_parser = (string) $the_parser;
1283
Derek Allard2067d1a2008-11-13 22:59:24 +00001284 // If invalid nesting, then return
1285 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001286
Derek Allard2067d1a2008-11-13 22:59:24 +00001287 // Evaluate and check for correct nesting of XML elements
Alex Bilbied261b1e2012-06-02 11:12:16 +01001288 if (count($this->xh[$the_parser]['stack']) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001289 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001290 if ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')
Derek Allard2067d1a2008-11-13 22:59:24 +00001291 {
1292 $this->xh[$the_parser]['isf'] = 2;
1293 $this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
1294 return;
1295 }
1296 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001297 // not top level element: see if parent is OK
1298 elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +00001299 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001300 $this->xh[$the_parser]['isf'] = 2;
vkeranovb497d2b2012-11-23 23:27:33 +02001301 $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 +03001302 return;
Derek Allard2067d1a2008-11-13 22:59:24 +00001303 }
Barry Mienydd671972010-10-04 16:33:58 +02001304
Andrey Andreevc8709832012-04-04 13:43:53 +03001305 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001306 {
1307 case 'STRUCT':
1308 case 'ARRAY':
1309 // Creates array for child elements
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001310 $cur_val = array('value' => array(), 'type' => $name);
Derek Allard2067d1a2008-11-13 22:59:24 +00001311 array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
Andrey Andreevc8709832012-04-04 13:43:53 +03001312 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001313 case 'METHODNAME':
1314 case 'NAME':
1315 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +03001316 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001317 case 'FAULT':
1318 $this->xh[$the_parser]['isf'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +03001319 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001320 case 'PARAM':
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 'VALUE':
1324 $this->xh[$the_parser]['vt'] = 'value';
1325 $this->xh[$the_parser]['ac'] = '';
1326 $this->xh[$the_parser]['lv'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +03001327 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001328 case 'I4':
1329 case 'INT':
1330 case 'STRING':
1331 case 'BOOLEAN':
1332 case 'DOUBLE':
1333 case 'DATETIME.ISO8601':
1334 case 'BASE64':
Alex Bilbied261b1e2012-06-02 11:12:16 +01001335 if ($this->xh[$the_parser]['vt'] !== 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +00001336 {
1337 //two data elements inside a value: an error occurred!
1338 $this->xh[$the_parser]['isf'] = 2;
vkeranovb497d2b2012-11-23 23:27:33 +02001339 $this->xh[$the_parser]['isf_reason'] = 'There is a '.$name.' element following a '
Andrey Andreevc8709832012-04-04 13:43:53 +03001340 .$this->xh[$the_parser]['vt'].' element inside a single value';
Derek Allard2067d1a2008-11-13 22:59:24 +00001341 return;
1342 }
Barry Mienydd671972010-10-04 16:33:58 +02001343
Derek Allard2067d1a2008-11-13 22:59:24 +00001344 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +03001345 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001346 case 'MEMBER':
1347 // Set name of <member> to nothing to prevent errors later if no <name> is found
1348 $this->xh[$the_parser]['valuestack'][0]['name'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001349
Derek Allard2067d1a2008-11-13 22:59:24 +00001350 // Set NULL value to check to see if value passed for this param/member
Pascal Kriete8761ef52011-02-14 13:13:52 -05001351 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +03001352 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001353 case 'DATA':
1354 case 'METHODCALL':
1355 case 'METHODRESPONSE':
1356 case 'PARAMS':
1357 // valid elements that add little to processing
Andrey Andreevc8709832012-04-04 13:43:53 +03001358 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001359 default:
1360 /// An Invalid Element is Found, so we have trouble
1361 $this->xh[$the_parser]['isf'] = 2;
Andrey Andreevc8709832012-04-04 13:43:53 +03001362 $this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;
1363 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001364 }
Barry Mienydd671972010-10-04 16:33:58 +02001365
Derek Allard2067d1a2008-11-13 22:59:24 +00001366 // Add current element name to stack, to allow validation of nesting
1367 array_unshift($this->xh[$the_parser]['stack'], $name);
1368
Alex Bilbied261b1e2012-06-02 11:12:16 +01001369 $name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001370 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001371
Andrey Andreevc8709832012-04-04 13:43:53 +03001372 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001373
Andrey Andreevc8709832012-04-04 13:43:53 +03001374 /**
1375 * End Element Handler
1376 *
1377 * @param string
1378 * @param string
1379 * @return void
1380 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001381 public function closing_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001382 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001383 $the_parser = (string) $the_parser;
1384
Derek Allard2067d1a2008-11-13 22:59:24 +00001385 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001386
Derek Allard2067d1a2008-11-13 22:59:24 +00001387 // Remove current element from stack and set variable
1388 // NOTE: If the XML validates, then we do not have to worry about
Andrey Andreevc8709832012-04-04 13:43:53 +03001389 // the opening and closing of elements. Nesting is checked on the opening
Derek Allard2067d1a2008-11-13 22:59:24 +00001390 // tag so we be safe there as well.
Barry Mienydd671972010-10-04 16:33:58 +02001391
Derek Allard2067d1a2008-11-13 22:59:24 +00001392 $curr_elem = array_shift($this->xh[$the_parser]['stack']);
Barry Mienydd671972010-10-04 16:33:58 +02001393
Andrey Andreevc8709832012-04-04 13:43:53 +03001394 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001395 {
1396 case 'STRUCT':
1397 case 'ARRAY':
1398 $cur_val = array_shift($this->xh[$the_parser]['valuestack']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001399 $this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();
Derek Allard2067d1a2008-11-13 22:59:24 +00001400 $this->xh[$the_parser]['vt'] = strtolower($name);
Andrey Andreevc8709832012-04-04 13:43:53 +03001401 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001402 case 'NAME':
1403 $this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
Andrey Andreevc8709832012-04-04 13:43:53 +03001404 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001405 case 'BOOLEAN':
1406 case 'I4':
1407 case 'INT':
1408 case 'STRING':
1409 case 'DOUBLE':
1410 case 'DATETIME.ISO8601':
1411 case 'BASE64':
1412 $this->xh[$the_parser]['vt'] = strtolower($name);
Barry Mienydd671972010-10-04 16:33:58 +02001413
Alex Bilbied261b1e2012-06-02 11:12:16 +01001414 if ($name === 'STRING')
Derek Allard2067d1a2008-11-13 22:59:24 +00001415 {
1416 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1417 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001418 elseif ($name === 'DATETIME.ISO8601')
Derek Allard2067d1a2008-11-13 22:59:24 +00001419 {
1420 $this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime;
1421 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1422 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001423 elseif ($name === 'BASE64')
Derek Allard2067d1a2008-11-13 22:59:24 +00001424 {
1425 $this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
1426 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001427 elseif ($name === 'BOOLEAN')
Derek Allard2067d1a2008-11-13 22:59:24 +00001428 {
1429 // Translated BOOLEAN values to TRUE AND FALSE
Andrey Andreevc8709832012-04-04 13:43:53 +03001430 $this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001431 }
1432 elseif ($name=='DOUBLE')
1433 {
1434 // we have a DOUBLE
1435 // we must check that only 0123456789-.<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001436 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])
1437 ? (float) $this->xh[$the_parser]['ac']
1438 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001439 }
1440 else
1441 {
1442 // we have an I4/INT
1443 // we must check that only 0123456789-<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001444 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])
George Petsagourakis306b3782012-05-02 20:31:08 +03001445 ? (int) $this->xh[$the_parser]['ac']
Andrey Andreevc8709832012-04-04 13:43:53 +03001446 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001447 }
1448 $this->xh[$the_parser]['ac'] = '';
1449 $this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
Andrey Andreevc8709832012-04-04 13:43:53 +03001450 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001451 case 'VALUE':
1452 // This if() detects if no scalar was inside <VALUE></VALUE>
vkeranovb497d2b2012-11-23 23:27:33 +02001453 if ($this->xh[$the_parser]['vt'] == 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +00001454 {
1455 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1456 $this->xh[$the_parser]['vt'] = $this->xmlrpcString;
1457 }
Barry Mienydd671972010-10-04 16:33:58 +02001458
Derek Allard2067d1a2008-11-13 22:59:24 +00001459 // build the XML-RPC value out of the data received, and substitute it
1460 $temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
Barry Mienydd671972010-10-04 16:33:58 +02001461
Alex Bilbied261b1e2012-06-02 11:12:16 +01001462 if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')
Derek Allard2067d1a2008-11-13 22:59:24 +00001463 {
1464 // Array
1465 $this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
1466 }
1467 else
1468 {
1469 // Struct
1470 $this->xh[$the_parser]['value'] = $temp;
1471 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001472 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001473 case 'MEMBER':
Andrey Andreevc8709832012-04-04 13:43:53 +03001474 $this->xh[$the_parser]['ac'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001475
Derek Allard2067d1a2008-11-13 22:59:24 +00001476 // If value add to array in the stack for the last element built
1477 if ($this->xh[$the_parser]['value'])
1478 {
1479 $this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
1480 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001481 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001482 case 'DATA':
Andrey Andreevc8709832012-04-04 13:43:53 +03001483 $this->xh[$the_parser]['ac'] = '';
1484 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001485 case 'PARAM':
1486 if ($this->xh[$the_parser]['value'])
1487 {
1488 $this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
1489 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001490 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001491 case 'METHODNAME':
1492 $this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001493 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001494 case 'PARAMS':
1495 case 'FAULT':
1496 case 'METHODCALL':
1497 case 'METHORESPONSE':
1498 // We're all good kids with nuthin' to do
Andrey Andreevc8709832012-04-04 13:43:53 +03001499 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001500 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001501 // End of an Invalid Element. Taken care of during the opening tag though
1502 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001503 }
1504 }
1505
Andrey Andreevc8709832012-04-04 13:43:53 +03001506 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001507
Andrey Andreevc8709832012-04-04 13:43:53 +03001508 /**
1509 * Parse character data
1510 *
1511 * @param string
1512 * @param string
1513 * @return void
1514 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001515 public function character_data($the_parser, $data)
Derek Allard2067d1a2008-11-13 22:59:24 +00001516 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001517 $the_parser = (string) $the_parser;
1518
Derek Allard2067d1a2008-11-13 22:59:24 +00001519 if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
Barry Mienydd671972010-10-04 16:33:58 +02001520
Derek Allard2067d1a2008-11-13 22:59:24 +00001521 // If a value has not been found
Alex Bilbied261b1e2012-06-02 11:12:16 +01001522 if ($this->xh[$the_parser]['lv'] !== 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001523 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001524 if ($this->xh[$the_parser]['lv'] === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001525 {
1526 $this->xh[$the_parser]['lv'] = 2; // Found a value
1527 }
Barry Mienydd671972010-10-04 16:33:58 +02001528
Andrey Andreevc8709832012-04-04 13:43:53 +03001529 if ( ! isset($this->xh[$the_parser]['ac']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001530 {
1531 $this->xh[$the_parser]['ac'] = '';
1532 }
Barry Mienydd671972010-10-04 16:33:58 +02001533
Derek Allard2067d1a2008-11-13 22:59:24 +00001534 $this->xh[$the_parser]['ac'] .= $data;
1535 }
1536 }
Barry Mienydd671972010-10-04 16:33:58 +02001537
Andrey Andreevc8709832012-04-04 13:43:53 +03001538 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001539
Andrey Andreevc8709832012-04-04 13:43:53 +03001540 /**
1541 * Add parameter
1542 *
1543 * @param mixed
1544 * @return void
1545 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001546 public function addParam($par)
1547 {
1548 $this->params[] = $par;
1549 }
Barry Mienydd671972010-10-04 16:33:58 +02001550
Andrey Andreevc8709832012-04-04 13:43:53 +03001551 // --------------------------------------------------------------------
1552
1553 /**
1554 * Output parameters
1555 *
Andrey Andreeve417f042014-01-08 14:48:01 +02001556 * @param array $array
Andrey Andreevc8709832012-04-04 13:43:53 +03001557 * @return array
1558 */
Andrey Andreeve417f042014-01-08 14:48:01 +02001559 public function output_parameters(array $array = array())
Derek Allard2067d1a2008-11-13 22:59:24 +00001560 {
Barry Mienydd671972010-10-04 16:33:58 +02001561 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +02001562
Andrey Andreeve417f042014-01-08 14:48:01 +02001563 if ( ! empty($array))
Derek Allard2067d1a2008-11-13 22:59:24 +00001564 {
1565 while (list($key) = each($array))
1566 {
1567 if (is_array($array[$key]))
1568 {
1569 $array[$key] = $this->output_parameters($array[$key]);
1570 }
Andrey Andreeve417f042014-01-08 14:48:01 +02001571 elseif ($key !== 'bits' && $this->xss_clean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001572 {
Derek Jonesa9647e82010-03-02 22:59:07 -06001573 // 'bits' is for the MetaWeblog API image bits
1574 // @todo - this needs to be made more general purpose
Andrey Andreeve417f042014-01-08 14:48:01 +02001575 $array[$key] = $CI->security->xss_clean($array[$key]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001576 }
1577 }
Barry Mienydd671972010-10-04 16:33:58 +02001578
Andrey Andreevc8709832012-04-04 13:43:53 +03001579 return $array;
Derek Allard2067d1a2008-11-13 22:59:24 +00001580 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001581
1582 $parameters = array();
1583
1584 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001585 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001586 $a_param = $this->decode_message($this->params[$i]);
Barry Mienydd671972010-10-04 16:33:58 +02001587
Andrey Andreevc8709832012-04-04 13:43:53 +03001588 if (is_array($a_param))
Derek Allard2067d1a2008-11-13 22:59:24 +00001589 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001590 $parameters[] = $this->output_parameters($a_param);
1591 }
1592 else
1593 {
1594 $parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;
Barry Mienydd671972010-10-04 16:33:58 +02001595 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001596 }
Barry Mienydd671972010-10-04 16:33:58 +02001597
Derek Allard2067d1a2008-11-13 22:59:24 +00001598 return $parameters;
1599 }
Barry Mienydd671972010-10-04 16:33:58 +02001600
Andrey Andreevc8709832012-04-04 13:43:53 +03001601 // --------------------------------------------------------------------
1602
1603 /**
1604 * Decode message
1605 *
1606 * @param object
1607 * @return mixed
1608 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001609 public function decode_message($param)
Derek Allard2067d1a2008-11-13 22:59:24 +00001610 {
1611 $kind = $param->kindOf();
1612
Alex Bilbied261b1e2012-06-02 11:12:16 +01001613 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +00001614 {
1615 return $param->scalarval();
1616 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001617 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +00001618 {
1619 reset($param->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001620 $b = current($param->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001621 $arr = array();
1622
Andrey Andreevc8709832012-04-04 13:43:53 +03001623 for ($i = 0, $c = count($b); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001624 {
1625 $arr[] = $this->decode_message($param->me['array'][$i]);
1626 }
Barry Mienydd671972010-10-04 16:33:58 +02001627
Derek Allard2067d1a2008-11-13 22:59:24 +00001628 return $arr;
1629 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001630 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +00001631 {
1632 reset($param->me['struct']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001633 $arr = array();
1634
Pascal Kriete14287f32011-02-14 13:39:34 -05001635 while (list($key,$value) = each($param->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001636 {
1637 $arr[$key] = $this->decode_message($value);
1638 }
Barry Mienydd671972010-10-04 16:33:58 +02001639
Derek Allard2067d1a2008-11-13 22:59:24 +00001640 return $arr;
1641 }
1642 }
Barry Mienydd671972010-10-04 16:33:58 +02001643
Andrey Andreevc8709832012-04-04 13:43:53 +03001644} // END XML_RPC_Message Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001645
1646/**
1647 * XML-RPC Values class
1648 *
1649 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -05001650 * @author EllisLab Dev Team
Andrey Andreevbd202c92016-01-11 12:50:18 +02001651 * @link https://codeigniter.com/user_guide/libraries/xmlrpc.html
Derek Allard2067d1a2008-11-13 22:59:24 +00001652 */
1653class XML_RPC_Values extends CI_Xmlrpc
1654{
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001655 /**
1656 * Value data
1657 *
1658 * @var array
1659 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001660 public $me = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001661
1662 /**
1663 * Value type
1664 *
1665 * @var int
1666 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001667 public $mytype = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001668
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001669 // --------------------------------------------------------------------
1670
Andrey Andreevc8709832012-04-04 13:43:53 +03001671 /**
1672 * Constructor
1673 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001674 * @param mixed $val
1675 * @param string $type
Andrey Andreevc8709832012-04-04 13:43:53 +03001676 * @return void
1677 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001678 public function __construct($val = -1, $type = '')
Barry Mienydd671972010-10-04 16:33:58 +02001679 {
Greg Akera9263282010-11-10 15:26:43 -06001680 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +02001681
Alex Bilbied261b1e2012-06-02 11:12:16 +01001682 if ($val !== -1 OR $type !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001683 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001684 $type = $type === '' ? 'string' : $type;
Barry Mienydd671972010-10-04 16:33:58 +02001685
Dimitar740480a2012-10-05 13:24:59 +03001686 if ($this->xmlrpcTypes[$type] == 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001687 {
vkeranovb497d2b2012-11-23 23:27:33 +02001688 $this->addScalar($val, $type);
Derek Allard2067d1a2008-11-13 22:59:24 +00001689 }
Dimitar740480a2012-10-05 13:24:59 +03001690 elseif ($this->xmlrpcTypes[$type] == 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001691 {
1692 $this->addArray($val);
1693 }
Dimitar740480a2012-10-05 13:24:59 +03001694 elseif ($this->xmlrpcTypes[$type] == 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001695 {
1696 $this->addStruct($val);
1697 }
1698 }
1699 }
1700
Andrey Andreevc8709832012-04-04 13:43:53 +03001701 // --------------------------------------------------------------------
1702
1703 /**
1704 * Add scalar value
1705 *
1706 * @param scalar
1707 * @param string
1708 * @return int
1709 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001710 public function addScalar($val, $type = 'string')
Derek Allard2067d1a2008-11-13 22:59:24 +00001711 {
1712 $typeof = $this->xmlrpcTypes[$type];
Barry Mienydd671972010-10-04 16:33:58 +02001713
Alex Bilbied261b1e2012-06-02 11:12:16 +01001714 if ($this->mytype === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001715 {
1716 echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
1717 return 0;
1718 }
Barry Mienydd671972010-10-04 16:33:58 +02001719
Dimitar740480a2012-10-05 13:24:59 +03001720 if ($typeof != 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001721 {
1722 echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';
1723 return 0;
1724 }
1725
Alex Bilbied261b1e2012-06-02 11:12:16 +01001726 if ($type === $this->xmlrpcBoolean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001727 {
Andrey Andreev3f3f1352012-09-05 16:39:28 +03001728 $val = (int) (strcasecmp($val, 'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
Derek Allard2067d1a2008-11-13 22:59:24 +00001729 }
1730
Alex Bilbied261b1e2012-06-02 11:12:16 +01001731 if ($this->mytype === 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001732 {
1733 // adding to an array here
1734 $ar = $this->me['array'];
1735 $ar[] = new XML_RPC_Values($val, $type);
1736 $this->me['array'] = $ar;
1737 }
1738 else
1739 {
1740 // a scalar, so set the value and remember we're scalar
1741 $this->me[$type] = $val;
1742 $this->mytype = $typeof;
1743 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001744
Derek Allard2067d1a2008-11-13 22:59:24 +00001745 return 1;
1746 }
1747
Andrey Andreevc8709832012-04-04 13:43:53 +03001748 // --------------------------------------------------------------------
1749
1750 /**
1751 * Add array value
1752 *
1753 * @param array
1754 * @return int
1755 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001756 public function addArray($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001757 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001758 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001759 {
Andrey Andreev3ca060a2013-11-27 16:30:31 +02001760 echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
Derek Allard2067d1a2008-11-13 22:59:24 +00001761 return 0;
1762 }
1763
1764 $this->mytype = $this->xmlrpcTypes['array'];
1765 $this->me['array'] = $vals;
1766 return 1;
1767 }
1768
Andrey Andreevc8709832012-04-04 13:43:53 +03001769 // --------------------------------------------------------------------
1770
1771 /**
1772 * Add struct value
1773 *
1774 * @param object
1775 * @return int
1776 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001777 public function addStruct($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001778 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001779 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001780 {
Andrey Andreev3ca060a2013-11-27 16:30:31 +02001781 echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
Derek Allard2067d1a2008-11-13 22:59:24 +00001782 return 0;
1783 }
1784 $this->mytype = $this->xmlrpcTypes['struct'];
1785 $this->me['struct'] = $vals;
1786 return 1;
1787 }
1788
Andrey Andreevc8709832012-04-04 13:43:53 +03001789 // --------------------------------------------------------------------
1790
1791 /**
1792 * Get value type
1793 *
1794 * @return string
1795 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001796 public function kindOf()
Derek Allard2067d1a2008-11-13 22:59:24 +00001797 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001798 switch ($this->mytype)
Derek Allard2067d1a2008-11-13 22:59:24 +00001799 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001800 case 3: return 'struct';
1801 case 2: return 'array';
1802 case 1: return 'scalar';
1803 default: return 'undef';
Derek Allard2067d1a2008-11-13 22:59:24 +00001804 }
1805 }
1806
Andrey Andreevc8709832012-04-04 13:43:53 +03001807 // --------------------------------------------------------------------
1808
1809 /**
1810 * Serialize data
1811 *
1812 * @param string
1813 * @param mixed
Gabriel Potkánye8a27922015-02-04 09:52:50 +01001814 * @return string
Andrey Andreevc8709832012-04-04 13:43:53 +03001815 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001816 public function serializedata($typ, $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001817 {
1818 $rs = '';
Derek Jonesa9647e82010-03-02 22:59:07 -06001819
Andrey Andreevc8709832012-04-04 13:43:53 +03001820 switch ($this->xmlrpcTypes[$typ])
Derek Allard2067d1a2008-11-13 22:59:24 +00001821 {
1822 case 3:
1823 // struct
1824 $rs .= "<struct>\n";
1825 reset($val);
Pascal Kriete14287f32011-02-14 13:39:34 -05001826 while (list($key2, $val2) = each($val))
Derek Allard2067d1a2008-11-13 22:59:24 +00001827 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001828 $rs .= "<member>\n<name>{$key2}</name>\n".$this->serializeval($val2)."</member>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001829 }
1830 $rs .= '</struct>';
Andrey Andreevc8709832012-04-04 13:43:53 +03001831 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001832 case 2:
1833 // array
1834 $rs .= "<array>\n<data>\n";
Andrey Andreevc8709832012-04-04 13:43:53 +03001835 for ($i = 0, $c = count($val); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001836 {
1837 $rs .= $this->serializeval($val[$i]);
1838 }
Andrey Andreeva30faf92011-12-25 18:15:34 +02001839 $rs .= "</data>\n</array>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001840 break;
1841 case 1:
1842 // others
1843 switch ($typ)
1844 {
1845 case $this->xmlrpcBase64:
Andrey Andreevc8709832012-04-04 13:43:53 +03001846 $rs .= '<'.$typ.'>'.base64_encode( (string) $val).'</'.$typ.">\n";
1847 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001848 case $this->xmlrpcBoolean:
Andrey Andreevc8709832012-04-04 13:43:53 +03001849 $rs .= '<'.$typ.'>'.( (bool) $val ? '1' : '0').'</'.$typ.">\n";
1850 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001851 case $this->xmlrpcString:
Andrey Andreevc8709832012-04-04 13:43:53 +03001852 $rs .= '<'.$typ.'>'.htmlspecialchars( (string) $val).'</'.$typ.">\n";
1853 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001854 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001855 $rs .= '<'.$typ.'>'.$val.'</'.$typ.">\n";
1856 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001857 }
1858 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001859 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001860 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001861
Derek Allard2067d1a2008-11-13 22:59:24 +00001862 return $rs;
1863 }
1864
Andrey Andreevc8709832012-04-04 13:43:53 +03001865 // --------------------------------------------------------------------
1866
1867 /**
1868 * Serialize class
1869 *
1870 * @return string
1871 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001872 public function serialize_class()
Derek Allard2067d1a2008-11-13 22:59:24 +00001873 {
1874 return $this->serializeval($this);
1875 }
1876
Andrey Andreevc8709832012-04-04 13:43:53 +03001877 // --------------------------------------------------------------------
1878
1879 /**
1880 * Serialize value
1881 *
1882 * @param object
1883 * @return string
1884 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001885 public function serializeval($o)
Derek Allard2067d1a2008-11-13 22:59:24 +00001886 {
1887 $ar = $o->me;
1888 reset($ar);
Barry Mienydd671972010-10-04 16:33:58 +02001889
Derek Allard2067d1a2008-11-13 22:59:24 +00001890 list($typ, $val) = each($ar);
Andrey Andreeva30faf92011-12-25 18:15:34 +02001891 return "<value>\n".$this->serializedata($typ, $val)."</value>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001892 }
Barry Mienydd671972010-10-04 16:33:58 +02001893
Andrey Andreevc8709832012-04-04 13:43:53 +03001894 // --------------------------------------------------------------------
1895
1896 /**
1897 * Scalar value
1898 *
1899 * @return mixed
1900 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001901 public function scalarval()
Derek Allard2067d1a2008-11-13 22:59:24 +00001902 {
1903 reset($this->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001904 return current($this->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001905 }
1906
Andrey Andreevc8709832012-04-04 13:43:53 +03001907 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001908
Andrey Andreevc8709832012-04-04 13:43:53 +03001909 /**
1910 * Encode time in ISO-8601 form.
1911 * Useful for sending time in XML-RPC
1912 *
1913 * @param int unix timestamp
1914 * @param bool
1915 * @return string
1916 */
1917 public function iso8601_encode($time, $utc = FALSE)
Barry Mienydd671972010-10-04 16:33:58 +02001918 {
Andrey Andreev62090152011-12-30 12:49:27 +02001919 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 +00001920 }
Barry Mienydd671972010-10-04 16:33:58 +02001921
Andrey Andreevc8709832012-04-04 13:43:53 +03001922} // END XML_RPC_Values Class