blob: 8fbc18f0415d23bbe9f9dc02076f8d58809324f4 [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 Andreevfe9309d2015-01-09 17:48:58 +02009 * Copyright (c) 2014 - 2015, 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
darwinel871754a2014-02-11 17:34:57 +010031 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
Andrey Andreevfe9309d2015-01-09 17:48:58 +020032 * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020033 * @license http://opensource.org/licenses/MIT MIT License
34 * @link http://codeigniter.com
35 * @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
Derek Allard2067d1a2008-11-13 22:59:24 +000054 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
55 */
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 Andreeva30faf92011-12-25 18:15:34 +0200355 if (strpos($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
Derek Allard2067d1a2008-11-13 22:59:24 +0000562 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
563 */
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;
Barry Mienydd671972010-10-04 16:33:58 +0200737
Andrey Andreevd8b1ad32014-01-15 17:42:52 +0200738 for ($written = 0, $length = strlen($op); $written < $length; $written += $result)
739 {
740 if (($result = fwrite($fp, substr($op, $written))) === FALSE)
741 {
742 break;
743 }
744 }
745
746 if ($result === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000747 {
748 error_log($this->xmlrpcstr['http_error']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300749 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000750 }
Andrey Andreevc8709832012-04-04 13:43:53 +0300751
Derek Allard2067d1a2008-11-13 22:59:24 +0000752 $resp = $msg->parseResponse($fp);
753 fclose($fp);
754 return $resp;
755 }
756
Andrey Andreevc8709832012-04-04 13:43:53 +0300757} // END XML_RPC_Client Class
Derek Allard2067d1a2008-11-13 22:59:24 +0000758
759/**
760 * XML-RPC Response class
761 *
762 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500763 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000764 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
765 */
766class XML_RPC_Response
767{
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200768
769 /**
770 * Value
771 *
772 * @var mixed
773 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300774 public $val = 0;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200775
776 /**
777 * Error number
778 *
779 * @var int
780 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300781 public $errno = 0;
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200782
783 /**
784 * Error message
785 *
786 * @var string
787 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300788 public $errstr = '';
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200789
790 /**
791 * Headers list
792 *
793 * @var array
794 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300795 public $headers = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200796
797 /**
798 * XSS Filter flag
799 *
800 * @var bool
801 */
Andrey Andreevc8709832012-04-04 13:43:53 +0300802 public $xss_clean = TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000803
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200804 // --------------------------------------------------------------------
805
Andrey Andreevc8709832012-04-04 13:43:53 +0300806 /**
807 * Constructor
808 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +0200809 * @param mixed $val
810 * @param int $code
811 * @param string $fstr
Andrey Andreevc8709832012-04-04 13:43:53 +0300812 * @return void
813 */
Greg Akera9263282010-11-10 15:26:43 -0600814 public function __construct($val, $code = 0, $fstr = '')
Barry Mienydd671972010-10-04 16:33:58 +0200815 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100816 if ($code !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000817 {
818 // error
819 $this->errno = $code;
Andrey Andreevc8709832012-04-04 13:43:53 +0300820 $this->errstr = htmlspecialchars($fstr,
821 (is_php('5.4') ? ENT_XML1 | ENT_NOQUOTES : ENT_NOQUOTES),
822 'UTF-8');
Derek Allard2067d1a2008-11-13 22:59:24 +0000823 }
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300824 elseif ( ! is_object($val))
Derek Allard2067d1a2008-11-13 22:59:24 +0000825 {
826 // programmer error, not an object
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300827 error_log("Invalid type '".gettype($val)."' (value: ".$val.') passed to XML_RPC_Response. Defaulting to empty value.');
Derek Allard2067d1a2008-11-13 22:59:24 +0000828 $this->val = new XML_RPC_Values();
829 }
830 else
831 {
832 $this->val = $val;
833 }
834 }
835
Andrey Andreevc8709832012-04-04 13:43:53 +0300836 // --------------------------------------------------------------------
837
838 /**
839 * Fault code
840 *
841 * @return int
842 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200843 public function faultCode()
Derek Allard2067d1a2008-11-13 22:59:24 +0000844 {
845 return $this->errno;
846 }
847
Andrey Andreevc8709832012-04-04 13:43:53 +0300848 // --------------------------------------------------------------------
849
850 /**
851 * Fault string
852 *
853 * @return string
854 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200855 public function faultString()
Derek Allard2067d1a2008-11-13 22:59:24 +0000856 {
857 return $this->errstr;
858 }
859
Andrey Andreevc8709832012-04-04 13:43:53 +0300860 // --------------------------------------------------------------------
861
862 /**
863 * Value
864 *
865 * @return mixed
866 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200867 public function value()
Derek Allard2067d1a2008-11-13 22:59:24 +0000868 {
869 return $this->val;
870 }
Barry Mienydd671972010-10-04 16:33:58 +0200871
Andrey Andreevc8709832012-04-04 13:43:53 +0300872 // --------------------------------------------------------------------
873
874 /**
875 * Prepare response
876 *
877 * @return string xml
878 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200879 public function prepare_response()
Derek Allard2067d1a2008-11-13 22:59:24 +0000880 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200881 return "<methodResponse>\n"
Andrey Andreevc8709832012-04-04 13:43:53 +0300882 .($this->errno
883 ? '<fault>
Derek Allard2067d1a2008-11-13 22:59:24 +0000884 <value>
885 <struct>
886 <member>
887 <name>faultCode</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300888 <value><int>'.$this->errno.'</int></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000889 </member>
890 <member>
891 <name>faultString</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300892 <value><string>'.$this->errstr.'</string></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000893 </member>
894 </struct>
895 </value>
Andrey Andreeva30faf92011-12-25 18:15:34 +0200896</fault>'
Andrey Andreevc8709832012-04-04 13:43:53 +0300897 : "<params>\n<param>\n".$this->val->serialize_class()."</param>\n</params>")
898 ."\n</methodResponse>";
Derek Allard2067d1a2008-11-13 22:59:24 +0000899 }
Barry Mienydd671972010-10-04 16:33:58 +0200900
Andrey Andreevc8709832012-04-04 13:43:53 +0300901 // --------------------------------------------------------------------
902
903 /**
904 * Decode
905 *
Andrey Andreeve417f042014-01-08 14:48:01 +0200906 * @param mixed $array
Andrey Andreevc8709832012-04-04 13:43:53 +0300907 * @return array
908 */
Andrey Andreeve417f042014-01-08 14:48:01 +0200909 public function decode($array = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000910 {
911 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +0200912
913 if (is_array($array))
Derek Allard2067d1a2008-11-13 22:59:24 +0000914 {
915 while (list($key) = each($array))
916 {
917 if (is_array($array[$key]))
918 {
919 $array[$key] = $this->decode($array[$key]);
920 }
Andrey Andreeve417f042014-01-08 14:48:01 +0200921 elseif ($this->xss_clean)
Derek Allard2067d1a2008-11-13 22:59:24 +0000922 {
Andrey Andreeve417f042014-01-08 14:48:01 +0200923 $array[$key] = $CI->security->xss_clean($array[$key]);
Derek Allard2067d1a2008-11-13 22:59:24 +0000924 }
925 }
Barry Mienydd671972010-10-04 16:33:58 +0200926
Andrey Andreevc8709832012-04-04 13:43:53 +0300927 return $array;
928 }
929
930 $result = $this->xmlrpc_decoder($this->val);
931
932 if (is_array($result))
933 {
934 $result = $this->decode($result);
Derek Allard2067d1a2008-11-13 22:59:24 +0000935 }
Andrey Andreeve417f042014-01-08 14:48:01 +0200936 elseif ($this->xss_clean)
Derek Allard2067d1a2008-11-13 22:59:24 +0000937 {
Andrey Andreeve417f042014-01-08 14:48:01 +0200938 $result = $CI->security->xss_clean($result);
Derek Allard2067d1a2008-11-13 22:59:24 +0000939 }
Barry Mienydd671972010-10-04 16:33:58 +0200940
Derek Allard2067d1a2008-11-13 22:59:24 +0000941 return $result;
942 }
943
Andrey Andreevc8709832012-04-04 13:43:53 +0300944 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000945
Andrey Andreevc8709832012-04-04 13:43:53 +0300946 /**
947 * XML-RPC Object to PHP Types
948 *
949 * @param object
950 * @return array
951 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200952 public function xmlrpc_decoder($xmlrpc_val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000953 {
954 $kind = $xmlrpc_val->kindOf();
955
Alex Bilbied261b1e2012-06-02 11:12:16 +0100956 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +0000957 {
958 return $xmlrpc_val->scalarval();
959 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100960 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +0000961 {
962 reset($xmlrpc_val->me);
Andrey Andreevadc11752011-12-30 14:46:08 +0200963 $b = current($xmlrpc_val->me);
Derek Allard2067d1a2008-11-13 22:59:24 +0000964 $arr = array();
965
Andrey Andreeva30faf92011-12-25 18:15:34 +0200966 for ($i = 0, $size = count($b); $i < $size; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000967 {
968 $arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);
969 }
970 return $arr;
971 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100972 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +0000973 {
974 reset($xmlrpc_val->me['struct']);
975 $arr = array();
976
Pascal Kriete14287f32011-02-14 13:39:34 -0500977 while (list($key,$value) = each($xmlrpc_val->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000978 {
979 $arr[$key] = $this->xmlrpc_decoder($value);
980 }
981 return $arr;
982 }
983 }
Barry Mienydd671972010-10-04 16:33:58 +0200984
Andrey Andreevc8709832012-04-04 13:43:53 +0300985 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000986
Andrey Andreevc8709832012-04-04 13:43:53 +0300987 /**
988 * ISO-8601 time to server or UTC time
989 *
990 * @param string
991 * @param bool
992 * @return int unix timestamp
993 */
994 public function iso8601_decode($time, $utc = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000995 {
vkeranovb497d2b2012-11-23 23:27:33 +0200996 // Return a time in the localtime, or UTC
Derek Allard2067d1a2008-11-13 22:59:24 +0000997 $t = 0;
998 if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))
999 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001000 $fnc = ($utc === TRUE) ? 'gmmktime' : 'mktime';
Pascal Kriete14287f32011-02-14 13:39:34 -05001001 $t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001002 }
1003 return $t;
1004 }
Barry Mienydd671972010-10-04 16:33:58 +02001005
Andrey Andreevc8709832012-04-04 13:43:53 +03001006} // END XML_RPC_Response Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001007
1008/**
1009 * XML-RPC Message class
1010 *
1011 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -05001012 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +00001013 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
1014 */
1015class XML_RPC_Message extends CI_Xmlrpc
1016{
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001017
1018 /**
1019 * Payload
1020 *
1021 * @var string
1022 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001023 public $payload;
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001024
1025 /**
1026 * Method name
1027 *
1028 * @var string
1029 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001030 public $method_name;
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001031
1032 /**
1033 * Parameter list
1034 *
1035 * @var array
1036 */
Andrey Andreevc8709832012-04-04 13:43:53 +03001037 public $params = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001038
1039 /**
1040 * XH?
1041 *
1042 * @var array
1043 */
Andrey Andreevc8709832012-04-04 13:43:53 +03001044 public $xh = array();
Derek Allard2067d1a2008-11-13 22:59:24 +00001045
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001046 // --------------------------------------------------------------------
1047
Andrey Andreevc8709832012-04-04 13:43:53 +03001048 /**
1049 * Constructor
1050 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001051 * @param string $method
1052 * @param array $pars
Andrey Andreevc8709832012-04-04 13:43:53 +03001053 * @return void
1054 */
1055 public function __construct($method, $pars = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001056 {
Greg Akera9263282010-11-10 15:26:43 -06001057 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +02001058
Derek Allard2067d1a2008-11-13 22:59:24 +00001059 $this->method_name = $method;
Derek Jones33559102009-02-02 18:50:38 +00001060 if (is_array($pars) && count($pars) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001061 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001062 for ($i = 0, $c = count($pars); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001063 {
1064 // $pars[$i] = XML_RPC_Values
1065 $this->params[] = $pars[$i];
1066 }
1067 }
1068 }
Barry Mienydd671972010-10-04 16:33:58 +02001069
Andrey Andreevc8709832012-04-04 13:43:53 +03001070 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001071
Andrey Andreevc8709832012-04-04 13:43:53 +03001072 /**
1073 * Create Payload to Send
1074 *
1075 * @return void
1076 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001077 public function createPayload()
Derek Allard2067d1a2008-11-13 22:59:24 +00001078 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001079 $this->payload = '<?xml version="1.0"?'.">\r\n<methodCall>\r\n"
1080 .'<methodName>'.$this->method_name."</methodName>\r\n"
1081 ."<params>\r\n";
Barry Mienydd671972010-10-04 16:33:58 +02001082
Andrey Andreeva30faf92011-12-25 18:15:34 +02001083 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001084 {
1085 // $p = XML_RPC_Values
1086 $p = $this->params[$i];
1087 $this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n";
1088 }
Barry Mienydd671972010-10-04 16:33:58 +02001089
Derek Allard2067d1a2008-11-13 22:59:24 +00001090 $this->payload .= "</params>\r\n</methodCall>\r\n";
1091 }
Barry Mienydd671972010-10-04 16:33:58 +02001092
Andrey Andreevc8709832012-04-04 13:43:53 +03001093 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001094
Andrey Andreevc8709832012-04-04 13:43:53 +03001095 /**
1096 * Parse External XML-RPC Server's Response
1097 *
1098 * @param resource
1099 * @return object
1100 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001101 public function parseResponse($fp)
Derek Allard2067d1a2008-11-13 22:59:24 +00001102 {
1103 $data = '';
Barry Mienydd671972010-10-04 16:33:58 +02001104
Pascal Kriete14287f32011-02-14 13:39:34 -05001105 while ($datum = fread($fp, 4096))
Derek Allard2067d1a2008-11-13 22:59:24 +00001106 {
1107 $data .= $datum;
1108 }
Barry Mienydd671972010-10-04 16:33:58 +02001109
Andrey Andreevc8709832012-04-04 13:43:53 +03001110 // Display HTTP content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +00001111 if ($this->debug === TRUE)
1112 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001113 echo "<pre>---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n</pre>";
Derek Allard2067d1a2008-11-13 22:59:24 +00001114 }
Barry Mienydd671972010-10-04 16:33:58 +02001115
Andrey Andreevc8709832012-04-04 13:43:53 +03001116 // Check for data
Andrey Andreeva30faf92011-12-25 18:15:34 +02001117 if ($data === '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001118 {
1119 error_log($this->xmlrpcstr['no_data']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001120 return new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001121 }
Barry Mienydd671972010-10-04 16:33:58 +02001122
Andrey Andreevc8709832012-04-04 13:43:53 +03001123 // Check for HTTP 200 Response
Andrey Andreev3dad2e72012-06-14 15:10:56 +03001124 if (strpos($data, 'HTTP') === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
Derek Allard2067d1a2008-11-13 22:59:24 +00001125 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001126 $errstr = substr($data, 0, strpos($data, "\n")-1);
1127 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');
Derek Allard2067d1a2008-11-13 22:59:24 +00001128 }
Barry Mienydd671972010-10-04 16:33:58 +02001129
Derek Allard2067d1a2008-11-13 22:59:24 +00001130 //-------------------------------------
vkeranovb497d2b2012-11-23 23:27:33 +02001131 // Create and Set Up XML Parser
Derek Allard2067d1a2008-11-13 22:59:24 +00001132 //-------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001133
Derek Allard2067d1a2008-11-13 22:59:24 +00001134 $parser = xml_parser_create($this->xmlrpc_defencoding);
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001135 $pname = (string) $parser;
1136 $this->xh[$pname] = array(
1137 'isf' => 0,
1138 'ac' => '',
1139 'headers' => array(),
1140 'stack' => array(),
1141 'valuestack' => array(),
1142 'isf_reason' => 0
1143 );
Derek Allard2067d1a2008-11-13 22:59:24 +00001144
1145 xml_set_object($parser, $this);
Andrey Andreevc8709832012-04-04 13:43:53 +03001146 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +00001147 xml_set_element_handler($parser, 'open_tag', 'closing_tag');
1148 xml_set_character_data_handler($parser, 'character_data');
1149 //xml_set_default_handler($parser, 'default_handler');
1150
Andrey Andreevc8709832012-04-04 13:43:53 +03001151 // Get headers
Derek Allard2067d1a2008-11-13 22:59:24 +00001152 $lines = explode("\r\n", $data);
1153 while (($line = array_shift($lines)))
1154 {
1155 if (strlen($line) < 1)
1156 {
1157 break;
1158 }
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001159 $this->xh[$pname]['headers'][] = $line;
Derek Allard2067d1a2008-11-13 22:59:24 +00001160 }
1161 $data = implode("\r\n", $lines);
Barry Mienydd671972010-10-04 16:33:58 +02001162
Andrey Andreevc8709832012-04-04 13:43:53 +03001163 // Parse XML data
Derek Jones33559102009-02-02 18:50:38 +00001164 if ( ! xml_parse($parser, $data, count($data)))
Derek Allard2067d1a2008-11-13 22:59:24 +00001165 {
1166 $errstr = sprintf('XML error: %s at line %d',
Andrey Andreevc8709832012-04-04 13:43:53 +03001167 xml_error_string(xml_get_error_code($parser)),
1168 xml_get_current_line_number($parser));
vkeranovb497d2b2012-11-23 23:27:33 +02001169
Derek Allard2067d1a2008-11-13 22:59:24 +00001170 $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
1171 xml_parser_free($parser);
1172 return $r;
1173 }
1174 xml_parser_free($parser);
Barry Mienydd671972010-10-04 16:33:58 +02001175
Andrey Andreevc8709832012-04-04 13:43:53 +03001176 // Got ourselves some badness, it seems
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001177 if ($this->xh[$pname]['isf'] > 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001178 {
1179 if ($this->debug === TRUE)
1180 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001181 echo "---Invalid Return---\n".$this->xh[$pname]['isf_reason']."---Invalid Return---\n\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001182 }
Barry Mienydd671972010-10-04 16:33:58 +02001183
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001184 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 +00001185 }
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001186 elseif ( ! is_object($this->xh[$pname]['value']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001187 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001188 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 +00001189 }
Barry Mienydd671972010-10-04 16:33:58 +02001190
Andrey Andreevc8709832012-04-04 13:43:53 +03001191 // Display XML content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +00001192 if ($this->debug === TRUE)
1193 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001194 echo '<pre>';
Barry Mienydd671972010-10-04 16:33:58 +02001195
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001196 if (count($this->xh[$pname]['headers'] > 0))
Derek Allard2067d1a2008-11-13 22:59:24 +00001197 {
1198 echo "---HEADERS---\n";
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001199 foreach ($this->xh[$pname]['headers'] as $header)
Derek Allard2067d1a2008-11-13 22:59:24 +00001200 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001201 echo $header."\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001202 }
1203 echo "---END HEADERS---\n\n";
1204 }
Barry Mienydd671972010-10-04 16:33:58 +02001205
Andrey Andreeva30faf92011-12-25 18:15:34 +02001206 echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n---PARSED---\n";
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001207 var_dump($this->xh[$pname]['value']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001208 echo "\n---END PARSED---</pre>";
1209 }
Barry Mienydd671972010-10-04 16:33:58 +02001210
Andrey Andreevc8709832012-04-04 13:43:53 +03001211 // Send response
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001212 $v = $this->xh[$pname]['value'];
1213 if ($this->xh[$pname]['isf'])
Derek Allard2067d1a2008-11-13 22:59:24 +00001214 {
1215 $errno_v = $v->me['struct']['faultCode'];
1216 $errstr_v = $v->me['struct']['faultString'];
1217 $errno = $errno_v->scalarval();
1218
Alex Bilbied261b1e2012-06-02 11:12:16 +01001219 if ($errno === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001220 {
1221 // FAULT returned, errno needs to reflect that
1222 $errno = -1;
1223 }
1224
1225 $r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
1226 }
1227 else
1228 {
1229 $r = new XML_RPC_Response($v);
1230 }
1231
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001232 $r->headers = $this->xh[$pname]['headers'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001233 return $r;
1234 }
Barry Mienydd671972010-10-04 16:33:58 +02001235
Andrey Andreevc8709832012-04-04 13:43:53 +03001236 // --------------------------------------------------------------------
1237
Derek Allard2067d1a2008-11-13 22:59:24 +00001238 // ------------------------------------
Derek Jones37f4b9c2011-07-01 17:56:50 -05001239 // Begin Return Message Parsing section
Derek Allard2067d1a2008-11-13 22:59:24 +00001240 // ------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001241
Derek Allard2067d1a2008-11-13 22:59:24 +00001242 // quick explanation of components:
Derek Jones37f4b9c2011-07-01 17:56:50 -05001243 // ac - used to accumulate values
1244 // isf - used to indicate a fault
1245 // lv - used to indicate "looking for a value": implements
Derek Allard2067d1a2008-11-13 22:59:24 +00001246 // the logic to allow values with no types to be strings
Derek Jones37f4b9c2011-07-01 17:56:50 -05001247 // params - used to store parameters in method calls
1248 // method - used to store method name
Derek Allard2067d1a2008-11-13 22:59:24 +00001249 // stack - array with parent tree of the xml element,
1250 // used to validate the nesting of elements
1251
Andrey Andreevc8709832012-04-04 13:43:53 +03001252 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001253
Andrey Andreevc8709832012-04-04 13:43:53 +03001254 /**
1255 * Start Element Handler
1256 *
1257 * @param string
1258 * @param string
1259 * @return void
1260 */
1261 public function open_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001262 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001263 $the_parser = (string) $the_parser;
1264
Derek Allard2067d1a2008-11-13 22:59:24 +00001265 // If invalid nesting, then return
1266 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001267
Derek Allard2067d1a2008-11-13 22:59:24 +00001268 // Evaluate and check for correct nesting of XML elements
Alex Bilbied261b1e2012-06-02 11:12:16 +01001269 if (count($this->xh[$the_parser]['stack']) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001270 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001271 if ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')
Derek Allard2067d1a2008-11-13 22:59:24 +00001272 {
1273 $this->xh[$the_parser]['isf'] = 2;
1274 $this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
1275 return;
1276 }
1277 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001278 // not top level element: see if parent is OK
1279 elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +00001280 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001281 $this->xh[$the_parser]['isf'] = 2;
vkeranovb497d2b2012-11-23 23:27:33 +02001282 $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 +03001283 return;
Derek Allard2067d1a2008-11-13 22:59:24 +00001284 }
Barry Mienydd671972010-10-04 16:33:58 +02001285
Andrey Andreevc8709832012-04-04 13:43:53 +03001286 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001287 {
1288 case 'STRUCT':
1289 case 'ARRAY':
1290 // Creates array for child elements
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001291 $cur_val = array('value' => array(), 'type' => $name);
Derek Allard2067d1a2008-11-13 22:59:24 +00001292 array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
Andrey Andreevc8709832012-04-04 13:43:53 +03001293 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001294 case 'METHODNAME':
1295 case 'NAME':
1296 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +03001297 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001298 case 'FAULT':
1299 $this->xh[$the_parser]['isf'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +03001300 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001301 case 'PARAM':
Pascal Kriete8761ef52011-02-14 13:13:52 -05001302 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +03001303 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001304 case 'VALUE':
1305 $this->xh[$the_parser]['vt'] = 'value';
1306 $this->xh[$the_parser]['ac'] = '';
1307 $this->xh[$the_parser]['lv'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +03001308 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001309 case 'I4':
1310 case 'INT':
1311 case 'STRING':
1312 case 'BOOLEAN':
1313 case 'DOUBLE':
1314 case 'DATETIME.ISO8601':
1315 case 'BASE64':
Alex Bilbied261b1e2012-06-02 11:12:16 +01001316 if ($this->xh[$the_parser]['vt'] !== 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +00001317 {
1318 //two data elements inside a value: an error occurred!
1319 $this->xh[$the_parser]['isf'] = 2;
vkeranovb497d2b2012-11-23 23:27:33 +02001320 $this->xh[$the_parser]['isf_reason'] = 'There is a '.$name.' element following a '
Andrey Andreevc8709832012-04-04 13:43:53 +03001321 .$this->xh[$the_parser]['vt'].' element inside a single value';
Derek Allard2067d1a2008-11-13 22:59:24 +00001322 return;
1323 }
Barry Mienydd671972010-10-04 16:33:58 +02001324
Derek Allard2067d1a2008-11-13 22:59:24 +00001325 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +03001326 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001327 case 'MEMBER':
1328 // Set name of <member> to nothing to prevent errors later if no <name> is found
1329 $this->xh[$the_parser]['valuestack'][0]['name'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001330
Derek Allard2067d1a2008-11-13 22:59:24 +00001331 // Set NULL value to check to see if value passed for this param/member
Pascal Kriete8761ef52011-02-14 13:13:52 -05001332 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +03001333 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001334 case 'DATA':
1335 case 'METHODCALL':
1336 case 'METHODRESPONSE':
1337 case 'PARAMS':
1338 // valid elements that add little to processing
Andrey Andreevc8709832012-04-04 13:43:53 +03001339 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001340 default:
1341 /// An Invalid Element is Found, so we have trouble
1342 $this->xh[$the_parser]['isf'] = 2;
Andrey Andreevc8709832012-04-04 13:43:53 +03001343 $this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;
1344 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001345 }
Barry Mienydd671972010-10-04 16:33:58 +02001346
Derek Allard2067d1a2008-11-13 22:59:24 +00001347 // Add current element name to stack, to allow validation of nesting
1348 array_unshift($this->xh[$the_parser]['stack'], $name);
1349
Alex Bilbied261b1e2012-06-02 11:12:16 +01001350 $name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001351 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001352
Andrey Andreevc8709832012-04-04 13:43:53 +03001353 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001354
Andrey Andreevc8709832012-04-04 13:43:53 +03001355 /**
1356 * End Element Handler
1357 *
1358 * @param string
1359 * @param string
1360 * @return void
1361 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001362 public function closing_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001363 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001364 $the_parser = (string) $the_parser;
1365
Derek Allard2067d1a2008-11-13 22:59:24 +00001366 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001367
Derek Allard2067d1a2008-11-13 22:59:24 +00001368 // Remove current element from stack and set variable
1369 // NOTE: If the XML validates, then we do not have to worry about
Andrey Andreevc8709832012-04-04 13:43:53 +03001370 // the opening and closing of elements. Nesting is checked on the opening
Derek Allard2067d1a2008-11-13 22:59:24 +00001371 // tag so we be safe there as well.
Barry Mienydd671972010-10-04 16:33:58 +02001372
Derek Allard2067d1a2008-11-13 22:59:24 +00001373 $curr_elem = array_shift($this->xh[$the_parser]['stack']);
Barry Mienydd671972010-10-04 16:33:58 +02001374
Andrey Andreevc8709832012-04-04 13:43:53 +03001375 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001376 {
1377 case 'STRUCT':
1378 case 'ARRAY':
1379 $cur_val = array_shift($this->xh[$the_parser]['valuestack']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001380 $this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();
Derek Allard2067d1a2008-11-13 22:59:24 +00001381 $this->xh[$the_parser]['vt'] = strtolower($name);
Andrey Andreevc8709832012-04-04 13:43:53 +03001382 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001383 case 'NAME':
1384 $this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
Andrey Andreevc8709832012-04-04 13:43:53 +03001385 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001386 case 'BOOLEAN':
1387 case 'I4':
1388 case 'INT':
1389 case 'STRING':
1390 case 'DOUBLE':
1391 case 'DATETIME.ISO8601':
1392 case 'BASE64':
1393 $this->xh[$the_parser]['vt'] = strtolower($name);
Barry Mienydd671972010-10-04 16:33:58 +02001394
Alex Bilbied261b1e2012-06-02 11:12:16 +01001395 if ($name === 'STRING')
Derek Allard2067d1a2008-11-13 22:59:24 +00001396 {
1397 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1398 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001399 elseif ($name === 'DATETIME.ISO8601')
Derek Allard2067d1a2008-11-13 22:59:24 +00001400 {
1401 $this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime;
1402 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1403 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001404 elseif ($name === 'BASE64')
Derek Allard2067d1a2008-11-13 22:59:24 +00001405 {
1406 $this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
1407 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001408 elseif ($name === 'BOOLEAN')
Derek Allard2067d1a2008-11-13 22:59:24 +00001409 {
1410 // Translated BOOLEAN values to TRUE AND FALSE
Andrey Andreevc8709832012-04-04 13:43:53 +03001411 $this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001412 }
1413 elseif ($name=='DOUBLE')
1414 {
1415 // we have a DOUBLE
1416 // we must check that only 0123456789-.<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001417 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])
1418 ? (float) $this->xh[$the_parser]['ac']
1419 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001420 }
1421 else
1422 {
1423 // we have an I4/INT
1424 // we must check that only 0123456789-<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001425 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])
George Petsagourakis306b3782012-05-02 20:31:08 +03001426 ? (int) $this->xh[$the_parser]['ac']
Andrey Andreevc8709832012-04-04 13:43:53 +03001427 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001428 }
1429 $this->xh[$the_parser]['ac'] = '';
1430 $this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
Andrey Andreevc8709832012-04-04 13:43:53 +03001431 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001432 case 'VALUE':
1433 // This if() detects if no scalar was inside <VALUE></VALUE>
vkeranovb497d2b2012-11-23 23:27:33 +02001434 if ($this->xh[$the_parser]['vt'] == 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +00001435 {
1436 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1437 $this->xh[$the_parser]['vt'] = $this->xmlrpcString;
1438 }
Barry Mienydd671972010-10-04 16:33:58 +02001439
Derek Allard2067d1a2008-11-13 22:59:24 +00001440 // build the XML-RPC value out of the data received, and substitute it
1441 $temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
Barry Mienydd671972010-10-04 16:33:58 +02001442
Alex Bilbied261b1e2012-06-02 11:12:16 +01001443 if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')
Derek Allard2067d1a2008-11-13 22:59:24 +00001444 {
1445 // Array
1446 $this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
1447 }
1448 else
1449 {
1450 // Struct
1451 $this->xh[$the_parser]['value'] = $temp;
1452 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001453 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001454 case 'MEMBER':
Andrey Andreevc8709832012-04-04 13:43:53 +03001455 $this->xh[$the_parser]['ac'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001456
Derek Allard2067d1a2008-11-13 22:59:24 +00001457 // If value add to array in the stack for the last element built
1458 if ($this->xh[$the_parser]['value'])
1459 {
1460 $this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
1461 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001462 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001463 case 'DATA':
Andrey Andreevc8709832012-04-04 13:43:53 +03001464 $this->xh[$the_parser]['ac'] = '';
1465 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001466 case 'PARAM':
1467 if ($this->xh[$the_parser]['value'])
1468 {
1469 $this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
1470 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001471 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001472 case 'METHODNAME':
1473 $this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001474 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001475 case 'PARAMS':
1476 case 'FAULT':
1477 case 'METHODCALL':
1478 case 'METHORESPONSE':
1479 // We're all good kids with nuthin' to do
Andrey Andreevc8709832012-04-04 13:43:53 +03001480 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001481 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001482 // End of an Invalid Element. Taken care of during the opening tag though
1483 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001484 }
1485 }
1486
Andrey Andreevc8709832012-04-04 13:43:53 +03001487 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001488
Andrey Andreevc8709832012-04-04 13:43:53 +03001489 /**
1490 * Parse character data
1491 *
1492 * @param string
1493 * @param string
1494 * @return void
1495 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001496 public function character_data($the_parser, $data)
Derek Allard2067d1a2008-11-13 22:59:24 +00001497 {
Andrey Andreev3aecedb2014-01-20 10:39:08 +02001498 $the_parser = (string) $the_parser;
1499
Derek Allard2067d1a2008-11-13 22:59:24 +00001500 if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
Barry Mienydd671972010-10-04 16:33:58 +02001501
Derek Allard2067d1a2008-11-13 22:59:24 +00001502 // If a value has not been found
Alex Bilbied261b1e2012-06-02 11:12:16 +01001503 if ($this->xh[$the_parser]['lv'] !== 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001504 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001505 if ($this->xh[$the_parser]['lv'] === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001506 {
1507 $this->xh[$the_parser]['lv'] = 2; // Found a value
1508 }
Barry Mienydd671972010-10-04 16:33:58 +02001509
Andrey Andreevc8709832012-04-04 13:43:53 +03001510 if ( ! isset($this->xh[$the_parser]['ac']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001511 {
1512 $this->xh[$the_parser]['ac'] = '';
1513 }
Barry Mienydd671972010-10-04 16:33:58 +02001514
Derek Allard2067d1a2008-11-13 22:59:24 +00001515 $this->xh[$the_parser]['ac'] .= $data;
1516 }
1517 }
Barry Mienydd671972010-10-04 16:33:58 +02001518
Andrey Andreevc8709832012-04-04 13:43:53 +03001519 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001520
Andrey Andreevc8709832012-04-04 13:43:53 +03001521 /**
1522 * Add parameter
1523 *
1524 * @param mixed
1525 * @return void
1526 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001527 public function addParam($par)
1528 {
1529 $this->params[] = $par;
1530 }
Barry Mienydd671972010-10-04 16:33:58 +02001531
Andrey Andreevc8709832012-04-04 13:43:53 +03001532 // --------------------------------------------------------------------
1533
1534 /**
1535 * Output parameters
1536 *
Andrey Andreeve417f042014-01-08 14:48:01 +02001537 * @param array $array
Andrey Andreevc8709832012-04-04 13:43:53 +03001538 * @return array
1539 */
Andrey Andreeve417f042014-01-08 14:48:01 +02001540 public function output_parameters(array $array = array())
Derek Allard2067d1a2008-11-13 22:59:24 +00001541 {
Barry Mienydd671972010-10-04 16:33:58 +02001542 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +02001543
Andrey Andreeve417f042014-01-08 14:48:01 +02001544 if ( ! empty($array))
Derek Allard2067d1a2008-11-13 22:59:24 +00001545 {
1546 while (list($key) = each($array))
1547 {
1548 if (is_array($array[$key]))
1549 {
1550 $array[$key] = $this->output_parameters($array[$key]);
1551 }
Andrey Andreeve417f042014-01-08 14:48:01 +02001552 elseif ($key !== 'bits' && $this->xss_clean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001553 {
Derek Jonesa9647e82010-03-02 22:59:07 -06001554 // 'bits' is for the MetaWeblog API image bits
1555 // @todo - this needs to be made more general purpose
Andrey Andreeve417f042014-01-08 14:48:01 +02001556 $array[$key] = $CI->security->xss_clean($array[$key]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001557 }
1558 }
Barry Mienydd671972010-10-04 16:33:58 +02001559
Andrey Andreevc8709832012-04-04 13:43:53 +03001560 return $array;
Derek Allard2067d1a2008-11-13 22:59:24 +00001561 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001562
1563 $parameters = array();
1564
1565 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001566 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001567 $a_param = $this->decode_message($this->params[$i]);
Barry Mienydd671972010-10-04 16:33:58 +02001568
Andrey Andreevc8709832012-04-04 13:43:53 +03001569 if (is_array($a_param))
Derek Allard2067d1a2008-11-13 22:59:24 +00001570 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001571 $parameters[] = $this->output_parameters($a_param);
1572 }
1573 else
1574 {
1575 $parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;
Barry Mienydd671972010-10-04 16:33:58 +02001576 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001577 }
Barry Mienydd671972010-10-04 16:33:58 +02001578
Derek Allard2067d1a2008-11-13 22:59:24 +00001579 return $parameters;
1580 }
Barry Mienydd671972010-10-04 16:33:58 +02001581
Andrey Andreevc8709832012-04-04 13:43:53 +03001582 // --------------------------------------------------------------------
1583
1584 /**
1585 * Decode message
1586 *
1587 * @param object
1588 * @return mixed
1589 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001590 public function decode_message($param)
Derek Allard2067d1a2008-11-13 22:59:24 +00001591 {
1592 $kind = $param->kindOf();
1593
Alex Bilbied261b1e2012-06-02 11:12:16 +01001594 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +00001595 {
1596 return $param->scalarval();
1597 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001598 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +00001599 {
1600 reset($param->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001601 $b = current($param->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001602 $arr = array();
1603
Andrey Andreevc8709832012-04-04 13:43:53 +03001604 for ($i = 0, $c = count($b); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001605 {
1606 $arr[] = $this->decode_message($param->me['array'][$i]);
1607 }
Barry Mienydd671972010-10-04 16:33:58 +02001608
Derek Allard2067d1a2008-11-13 22:59:24 +00001609 return $arr;
1610 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001611 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +00001612 {
1613 reset($param->me['struct']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001614 $arr = array();
1615
Pascal Kriete14287f32011-02-14 13:39:34 -05001616 while (list($key,$value) = each($param->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001617 {
1618 $arr[$key] = $this->decode_message($value);
1619 }
Barry Mienydd671972010-10-04 16:33:58 +02001620
Derek Allard2067d1a2008-11-13 22:59:24 +00001621 return $arr;
1622 }
1623 }
Barry Mienydd671972010-10-04 16:33:58 +02001624
Andrey Andreevc8709832012-04-04 13:43:53 +03001625} // END XML_RPC_Message Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001626
1627/**
1628 * XML-RPC Values class
1629 *
1630 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -05001631 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +00001632 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
1633 */
1634class XML_RPC_Values extends CI_Xmlrpc
1635{
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001636 /**
1637 * Value data
1638 *
1639 * @var array
1640 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001641 public $me = array();
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001642
1643 /**
1644 * Value type
1645 *
1646 * @var int
1647 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001648 public $mytype = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001649
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001650 // --------------------------------------------------------------------
1651
Andrey Andreevc8709832012-04-04 13:43:53 +03001652 /**
1653 * Constructor
1654 *
Andrey Andreevf5ccd122012-11-02 00:17:39 +02001655 * @param mixed $val
1656 * @param string $type
Andrey Andreevc8709832012-04-04 13:43:53 +03001657 * @return void
1658 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001659 public function __construct($val = -1, $type = '')
Barry Mienydd671972010-10-04 16:33:58 +02001660 {
Greg Akera9263282010-11-10 15:26:43 -06001661 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +02001662
Alex Bilbied261b1e2012-06-02 11:12:16 +01001663 if ($val !== -1 OR $type !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001664 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001665 $type = $type === '' ? 'string' : $type;
Barry Mienydd671972010-10-04 16:33:58 +02001666
Dimitar740480a2012-10-05 13:24:59 +03001667 if ($this->xmlrpcTypes[$type] == 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001668 {
vkeranovb497d2b2012-11-23 23:27:33 +02001669 $this->addScalar($val, $type);
Derek Allard2067d1a2008-11-13 22:59:24 +00001670 }
Dimitar740480a2012-10-05 13:24:59 +03001671 elseif ($this->xmlrpcTypes[$type] == 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001672 {
1673 $this->addArray($val);
1674 }
Dimitar740480a2012-10-05 13:24:59 +03001675 elseif ($this->xmlrpcTypes[$type] == 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001676 {
1677 $this->addStruct($val);
1678 }
1679 }
1680 }
1681
Andrey Andreevc8709832012-04-04 13:43:53 +03001682 // --------------------------------------------------------------------
1683
1684 /**
1685 * Add scalar value
1686 *
1687 * @param scalar
1688 * @param string
1689 * @return int
1690 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001691 public function addScalar($val, $type = 'string')
Derek Allard2067d1a2008-11-13 22:59:24 +00001692 {
1693 $typeof = $this->xmlrpcTypes[$type];
Barry Mienydd671972010-10-04 16:33:58 +02001694
Alex Bilbied261b1e2012-06-02 11:12:16 +01001695 if ($this->mytype === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001696 {
1697 echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
1698 return 0;
1699 }
Barry Mienydd671972010-10-04 16:33:58 +02001700
Dimitar740480a2012-10-05 13:24:59 +03001701 if ($typeof != 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001702 {
1703 echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';
1704 return 0;
1705 }
1706
Alex Bilbied261b1e2012-06-02 11:12:16 +01001707 if ($type === $this->xmlrpcBoolean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001708 {
Andrey Andreev3f3f1352012-09-05 16:39:28 +03001709 $val = (int) (strcasecmp($val, 'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
Derek Allard2067d1a2008-11-13 22:59:24 +00001710 }
1711
Alex Bilbied261b1e2012-06-02 11:12:16 +01001712 if ($this->mytype === 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001713 {
1714 // adding to an array here
1715 $ar = $this->me['array'];
1716 $ar[] = new XML_RPC_Values($val, $type);
1717 $this->me['array'] = $ar;
1718 }
1719 else
1720 {
1721 // a scalar, so set the value and remember we're scalar
1722 $this->me[$type] = $val;
1723 $this->mytype = $typeof;
1724 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001725
Derek Allard2067d1a2008-11-13 22:59:24 +00001726 return 1;
1727 }
1728
Andrey Andreevc8709832012-04-04 13:43:53 +03001729 // --------------------------------------------------------------------
1730
1731 /**
1732 * Add array value
1733 *
1734 * @param array
1735 * @return int
1736 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001737 public function addArray($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001738 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001739 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001740 {
Andrey Andreev3ca060a2013-11-27 16:30:31 +02001741 echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
Derek Allard2067d1a2008-11-13 22:59:24 +00001742 return 0;
1743 }
1744
1745 $this->mytype = $this->xmlrpcTypes['array'];
1746 $this->me['array'] = $vals;
1747 return 1;
1748 }
1749
Andrey Andreevc8709832012-04-04 13:43:53 +03001750 // --------------------------------------------------------------------
1751
1752 /**
1753 * Add struct value
1754 *
1755 * @param object
1756 * @return int
1757 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001758 public function addStruct($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001759 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001760 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001761 {
Andrey Andreev3ca060a2013-11-27 16:30:31 +02001762 echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
Derek Allard2067d1a2008-11-13 22:59:24 +00001763 return 0;
1764 }
1765 $this->mytype = $this->xmlrpcTypes['struct'];
1766 $this->me['struct'] = $vals;
1767 return 1;
1768 }
1769
Andrey Andreevc8709832012-04-04 13:43:53 +03001770 // --------------------------------------------------------------------
1771
1772 /**
1773 * Get value type
1774 *
1775 * @return string
1776 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001777 public function kindOf()
Derek Allard2067d1a2008-11-13 22:59:24 +00001778 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001779 switch ($this->mytype)
Derek Allard2067d1a2008-11-13 22:59:24 +00001780 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001781 case 3: return 'struct';
1782 case 2: return 'array';
1783 case 1: return 'scalar';
1784 default: return 'undef';
Derek Allard2067d1a2008-11-13 22:59:24 +00001785 }
1786 }
1787
Andrey Andreevc8709832012-04-04 13:43:53 +03001788 // --------------------------------------------------------------------
1789
1790 /**
1791 * Serialize data
1792 *
1793 * @param string
1794 * @param mixed
Gabriel Potkánye8a27922015-02-04 09:52:50 +01001795 * @return string
Andrey Andreevc8709832012-04-04 13:43:53 +03001796 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001797 public function serializedata($typ, $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001798 {
1799 $rs = '';
Derek Jonesa9647e82010-03-02 22:59:07 -06001800
Andrey Andreevc8709832012-04-04 13:43:53 +03001801 switch ($this->xmlrpcTypes[$typ])
Derek Allard2067d1a2008-11-13 22:59:24 +00001802 {
1803 case 3:
1804 // struct
1805 $rs .= "<struct>\n";
1806 reset($val);
Pascal Kriete14287f32011-02-14 13:39:34 -05001807 while (list($key2, $val2) = each($val))
Derek Allard2067d1a2008-11-13 22:59:24 +00001808 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001809 $rs .= "<member>\n<name>{$key2}</name>\n".$this->serializeval($val2)."</member>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001810 }
1811 $rs .= '</struct>';
Andrey Andreevc8709832012-04-04 13:43:53 +03001812 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001813 case 2:
1814 // array
1815 $rs .= "<array>\n<data>\n";
Andrey Andreevc8709832012-04-04 13:43:53 +03001816 for ($i = 0, $c = count($val); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001817 {
1818 $rs .= $this->serializeval($val[$i]);
1819 }
Andrey Andreeva30faf92011-12-25 18:15:34 +02001820 $rs .= "</data>\n</array>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001821 break;
1822 case 1:
1823 // others
1824 switch ($typ)
1825 {
1826 case $this->xmlrpcBase64:
Andrey Andreevc8709832012-04-04 13:43:53 +03001827 $rs .= '<'.$typ.'>'.base64_encode( (string) $val).'</'.$typ.">\n";
1828 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001829 case $this->xmlrpcBoolean:
Andrey Andreevc8709832012-04-04 13:43:53 +03001830 $rs .= '<'.$typ.'>'.( (bool) $val ? '1' : '0').'</'.$typ.">\n";
1831 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001832 case $this->xmlrpcString:
Andrey Andreevc8709832012-04-04 13:43:53 +03001833 $rs .= '<'.$typ.'>'.htmlspecialchars( (string) $val).'</'.$typ.">\n";
1834 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001835 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001836 $rs .= '<'.$typ.'>'.$val.'</'.$typ.">\n";
1837 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001838 }
1839 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001840 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001841 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001842
Derek Allard2067d1a2008-11-13 22:59:24 +00001843 return $rs;
1844 }
1845
Andrey Andreevc8709832012-04-04 13:43:53 +03001846 // --------------------------------------------------------------------
1847
1848 /**
1849 * Serialize class
1850 *
1851 * @return string
1852 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001853 public function serialize_class()
Derek Allard2067d1a2008-11-13 22:59:24 +00001854 {
1855 return $this->serializeval($this);
1856 }
1857
Andrey Andreevc8709832012-04-04 13:43:53 +03001858 // --------------------------------------------------------------------
1859
1860 /**
1861 * Serialize value
1862 *
1863 * @param object
1864 * @return string
1865 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001866 public function serializeval($o)
Derek Allard2067d1a2008-11-13 22:59:24 +00001867 {
1868 $ar = $o->me;
1869 reset($ar);
Barry Mienydd671972010-10-04 16:33:58 +02001870
Derek Allard2067d1a2008-11-13 22:59:24 +00001871 list($typ, $val) = each($ar);
Andrey Andreeva30faf92011-12-25 18:15:34 +02001872 return "<value>\n".$this->serializedata($typ, $val)."</value>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001873 }
Barry Mienydd671972010-10-04 16:33:58 +02001874
Andrey Andreevc8709832012-04-04 13:43:53 +03001875 // --------------------------------------------------------------------
1876
1877 /**
1878 * Scalar value
1879 *
1880 * @return mixed
1881 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001882 public function scalarval()
Derek Allard2067d1a2008-11-13 22:59:24 +00001883 {
1884 reset($this->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001885 return current($this->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001886 }
1887
Andrey Andreevc8709832012-04-04 13:43:53 +03001888 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001889
Andrey Andreevc8709832012-04-04 13:43:53 +03001890 /**
1891 * Encode time in ISO-8601 form.
1892 * Useful for sending time in XML-RPC
1893 *
1894 * @param int unix timestamp
1895 * @param bool
1896 * @return string
1897 */
1898 public function iso8601_encode($time, $utc = FALSE)
Barry Mienydd671972010-10-04 16:33:58 +02001899 {
Andrey Andreev62090152011-12-30 12:49:27 +02001900 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 +00001901 }
Barry Mienydd671972010-10-04 16:33:58 +02001902
Andrey Andreevc8709832012-04-04 13:43:53 +03001903} // END XML_RPC_Values Class