blob: 79e6c613ff673a12fabba785189e7b467bb207eb [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Phil Sturgeon07c1ac82012-03-09 17:03:37 +00005 * An open source application development framework for PHP 5.2.4 or newer
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05007 * NOTICE OF LICENSE
Andrey Andreeva30faf92011-12-25 18:15:34 +02008 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05009 * Licensed under the Open Software License version 3.0
Andrey Andreeva30faf92011-12-25 18:15:34 +020010 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -050011 * This source file is subject to the Open Software License (OSL 3.0) that is
12 * bundled with this package in the files license.txt / license.rst. It is
13 * also available through the world wide web at this URL:
14 * http://opensource.org/licenses/OSL-3.0
15 * If you did not receive a copy of the license and are unable to obtain it
16 * through the world wide web, please send an email to
17 * licensing@ellislab.com so we can send you a copy immediately.
18 *
Derek Allard2067d1a2008-11-13 22:59:24 +000019 * @package CodeIgniter
Derek Jonesf4a4bd82011-10-20 12:18:42 -050020 * @author EllisLab Dev Team
Greg Aker0defe5d2012-01-01 18:46:41 -060021 * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
Derek Jonesf4a4bd82011-10-20 12:18:42 -050022 * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
Derek Allard2067d1a2008-11-13 22:59:24 +000023 * @link http://codeigniter.com
24 * @since Version 1.0
25 * @filesource
26 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020027defined('BASEPATH') OR exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +000028
Derek Allard2067d1a2008-11-13 22:59:24 +000029/**
30 * XML-RPC request handler class
31 *
32 * @package CodeIgniter
33 * @subpackage Libraries
34 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -050035 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000036 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
37 */
Andrey Andreevc8709832012-04-04 13:43:53 +030038
39if ( ! function_exists('xml_parser_create'))
40{
41 show_error('Your PHP installation does not support XML');
42}
43
44// ------------------------------------------------------------------------
45
Derek Allard2067d1a2008-11-13 22:59:24 +000046class CI_Xmlrpc {
47
Andrey Andreeva30faf92011-12-25 18:15:34 +020048 public $debug = FALSE; // Debugging on or off
49 public $xmlrpcI4 = 'i4';
50 public $xmlrpcInt = 'int';
51 public $xmlrpcBoolean = 'boolean';
52 public $xmlrpcDouble = 'double';
53 public $xmlrpcString = 'string';
54 public $xmlrpcDateTime = 'dateTime.iso8601';
55 public $xmlrpcBase64 = 'base64';
56 public $xmlrpcArray = 'array';
57 public $xmlrpcStruct = 'struct';
Barry Mienydd671972010-10-04 16:33:58 +020058
Andrey Andreeva30faf92011-12-25 18:15:34 +020059 public $xmlrpcTypes = array();
60 public $valid_parents = array();
61 public $xmlrpcerr = array(); // Response numbers
62 public $xmlrpcstr = array(); // Response strings
Barry Mienydd671972010-10-04 16:33:58 +020063
Andrey Andreeva30faf92011-12-25 18:15:34 +020064 public $xmlrpc_defencoding = 'UTF-8';
65 public $xmlrpcName = 'XML-RPC for CodeIgniter';
66 public $xmlrpcVersion = '1.1';
67 public $xmlrpcerruser = 800; // Start of user errors
68 public $xmlrpcerrxml = 100; // Start of XML Parse errors
69 public $xmlrpc_backslash = ''; // formulate backslashes for escaping regexp
Barry Mienydd671972010-10-04 16:33:58 +020070
Andrey Andreeva30faf92011-12-25 18:15:34 +020071 public $client;
72 public $method;
73 public $data;
74 public $message = '';
75 public $error = ''; // Error string for request
76 public $result;
77 public $response = array(); // Response from remote server
Derek Allard2067d1a2008-11-13 22:59:24 +000078
Andrey Andreeva30faf92011-12-25 18:15:34 +020079 public $xss_clean = TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +000080
Derek Allard2067d1a2008-11-13 22:59:24 +000081
Andrey Andreevc8709832012-04-04 13:43:53 +030082 /**
83 * Constructor
84 *
85 * Initializes property default values
86 *
87 * @param array
88 * @return void
89 */
Greg Akera9263282010-11-10 15:26:43 -060090 public function __construct($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +000091 {
Derek Allard2067d1a2008-11-13 22:59:24 +000092 $this->xmlrpc_backslash = chr(92).chr(92);
Barry Mienydd671972010-10-04 16:33:58 +020093
Derek Allard2067d1a2008-11-13 22:59:24 +000094 // Types for info sent back and forth
95 $this->xmlrpcTypes = array(
Barry Mienydd671972010-10-04 16:33:58 +020096 $this->xmlrpcI4 => '1',
97 $this->xmlrpcInt => '1',
98 $this->xmlrpcBoolean => '1',
99 $this->xmlrpcString => '1',
100 $this->xmlrpcDouble => '1',
101 $this->xmlrpcDateTime => '1',
102 $this->xmlrpcBase64 => '1',
103 $this->xmlrpcArray => '2',
104 $this->xmlrpcStruct => '3'
Derek Allard2067d1a2008-11-13 22:59:24 +0000105 );
Barry Mienydd671972010-10-04 16:33:58 +0200106
Derek Allard2067d1a2008-11-13 22:59:24 +0000107 // Array of Valid Parents for Various XML-RPC elements
Timothy Warren0688ac92012-04-20 10:25:04 -0400108 $this->valid_parents = array('BOOLEAN' => array('VALUE'),
109 'I4' => array('VALUE'),
110 'INT' => array('VALUE'),
111 'STRING' => array('VALUE'),
112 'DOUBLE' => array('VALUE'),
113 'DATETIME.ISO8601' => array('VALUE'),
114 'BASE64' => array('VALUE'),
115 'ARRAY' => array('VALUE'),
116 'STRUCT' => array('VALUE'),
117 'PARAM' => array('PARAMS'),
118 'METHODNAME' => array('METHODCALL'),
119 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'),
120 'MEMBER' => array('STRUCT'),
121 'NAME' => array('MEMBER'),
122 'DATA' => array('ARRAY'),
123 'FAULT' => array('METHODRESPONSE'),
124 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT')
125 );
Barry Mienydd671972010-10-04 16:33:58 +0200126
127
Derek Allard2067d1a2008-11-13 22:59:24 +0000128 // XML-RPC Responses
129 $this->xmlrpcerr['unknown_method'] = '1';
130 $this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server';
131 $this->xmlrpcerr['invalid_return'] = '2';
Derek Jones37f4b9c2011-07-01 17:56:50 -0500132 $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 +0000133 $this->xmlrpcerr['incorrect_params'] = '3';
134 $this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method';
135 $this->xmlrpcerr['introspect_unknown'] = '4';
Andrey Andreeva30faf92011-12-25 18:15:34 +0200136 $this->xmlrpcstr['introspect_unknown'] = 'Cannot inspect signature for request: method unknown';
Derek Allard2067d1a2008-11-13 22:59:24 +0000137 $this->xmlrpcerr['http_error'] = '5';
138 $this->xmlrpcstr['http_error'] = "Did not receive a '200 OK' response from remote server.";
139 $this->xmlrpcerr['no_data'] = '6';
140 $this->xmlrpcstr['no_data'] ='No data received from server.';
Barry Mienydd671972010-10-04 16:33:58 +0200141
Derek Allard2067d1a2008-11-13 22:59:24 +0000142 $this->initialize($config);
Barry Mienydd671972010-10-04 16:33:58 +0200143
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300144 log_message('debug', 'XML-RPC Class Initialized');
Derek Allard2067d1a2008-11-13 22:59:24 +0000145 }
Barry Mienydd671972010-10-04 16:33:58 +0200146
Andrey Andreevc8709832012-04-04 13:43:53 +0300147 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000148
Andrey Andreevc8709832012-04-04 13:43:53 +0300149 /**
150 * Initialize
151 *
152 * @param array
153 * @return void
154 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200155 public function initialize($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000156 {
Derek Jones33559102009-02-02 18:50:38 +0000157 if (count($config) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000158 {
159 foreach ($config as $key => $val)
160 {
161 if (isset($this->$key))
162 {
Barry Mienydd671972010-10-04 16:33:58 +0200163 $this->$key = $val;
Derek Allard2067d1a2008-11-13 22:59:24 +0000164 }
165 }
166 }
167 }
Barry Mienydd671972010-10-04 16:33:58 +0200168
Andrey Andreevc8709832012-04-04 13:43:53 +0300169 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000170
Andrey Andreevc8709832012-04-04 13:43:53 +0300171 /**
172 * Parse server URL
173 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300174 * @param string $url
175 * @param int $port = 80
176 * @param string $proxy = FALSE
177 * @param int $proxy_port = 8080
Andrey Andreevc8709832012-04-04 13:43:53 +0300178 * @return void
179 */
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300180 public function server($url, $port = 80, $proxy = FALSE, $proxy_port = 8080)
Derek Allard2067d1a2008-11-13 22:59:24 +0000181 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200182 if (strpos($url, 'http') !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000183 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300184 $url = 'http://'.$url;
Derek Allard2067d1a2008-11-13 22:59:24 +0000185 }
Barry Mienydd671972010-10-04 16:33:58 +0200186
Derek Allard2067d1a2008-11-13 22:59:24 +0000187 $parts = parse_url($url);
Barry Mienydd671972010-10-04 16:33:58 +0200188
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300189 $path = isset($parts['path']) ? $parts['path'] : '/';
Barry Mienydd671972010-10-04 16:33:58 +0200190
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300191 if ( ! empty($parts['query']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000192 {
193 $path .= '?'.$parts['query'];
Barry Mienydd671972010-10-04 16:33:58 +0200194 }
195
Valio9dee5352012-07-02 10:42:28 +0300196 $this->client = new XML_RPC_Client($path, $parts['host'], $port, $proxy, $proxy_port);
Derek Allard2067d1a2008-11-13 22:59:24 +0000197 }
Barry Mienydd671972010-10-04 16:33:58 +0200198
Andrey Andreevc8709832012-04-04 13:43:53 +0300199 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000200
Andrey Andreevc8709832012-04-04 13:43:53 +0300201 /**
202 * Set Timeout
203 *
204 * @param int seconds
205 * @return void
206 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200207 public function timeout($seconds = 5)
Derek Allard2067d1a2008-11-13 22:59:24 +0000208 {
209 if ( ! is_null($this->client) && is_int($seconds))
210 {
211 $this->client->timeout = $seconds;
212 }
213 }
Barry Mienydd671972010-10-04 16:33:58 +0200214
Andrey Andreevc8709832012-04-04 13:43:53 +0300215 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000216
Andrey Andreevc8709832012-04-04 13:43:53 +0300217 /**
218 * Set Methods
219 *
220 * @param string method name
221 * @return void
222 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200223 public function method($function)
Derek Allard2067d1a2008-11-13 22:59:24 +0000224 {
225 $this->method = $function;
226 }
Barry Mienydd671972010-10-04 16:33:58 +0200227
Andrey Andreevc8709832012-04-04 13:43:53 +0300228 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000229
Andrey Andreevc8709832012-04-04 13:43:53 +0300230 /**
231 * Take Array of Data and Create Objects
232 *
233 * @param array
234 * @return void
235 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200236 public function request($incoming)
Derek Allard2067d1a2008-11-13 22:59:24 +0000237 {
238 if ( ! is_array($incoming))
239 {
240 // Send Error
Andrey Andreevc8709832012-04-04 13:43:53 +0300241 return;
Derek Allard2067d1a2008-11-13 22:59:24 +0000242 }
Barry Mienydd671972010-10-04 16:33:58 +0200243
Derek Allard2067d1a2008-11-13 22:59:24 +0000244 $this->data = array();
Barry Mienydd671972010-10-04 16:33:58 +0200245
Pascal Kriete14287f32011-02-14 13:39:34 -0500246 foreach ($incoming as $key => $value)
Derek Allard2067d1a2008-11-13 22:59:24 +0000247 {
248 $this->data[$key] = $this->values_parsing($value);
249 }
250 }
Barry Mienydd671972010-10-04 16:33:58 +0200251
Andrey Andreevc8709832012-04-04 13:43:53 +0300252 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200253
Andrey Andreevc8709832012-04-04 13:43:53 +0300254 /**
255 * Set Debug
256 *
257 * @param bool
258 * @return void
259 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200260 public function set_debug($flag = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000261 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100262 $this->debug = ($flag === TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000263 }
Barry Mienydd671972010-10-04 16:33:58 +0200264
Andrey Andreevc8709832012-04-04 13:43:53 +0300265 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000266
Andrey Andreevc8709832012-04-04 13:43:53 +0300267 /**
268 * Values Parsing
269 *
270 * @param mixed
271 * @return object
272 */
273 public function values_parsing($value)
Derek Allard2067d1a2008-11-13 22:59:24 +0000274 {
Derek Jones8c4b5e72010-01-06 22:21:41 +0000275 if (is_array($value) && array_key_exists(0, $value))
Derek Allard2067d1a2008-11-13 22:59:24 +0000276 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300277 if ( ! isset($value[1], $this->xmlrpcTypes[$value[1]]))
Derek Allard2067d1a2008-11-13 22:59:24 +0000278 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200279 $temp = new XML_RPC_Values($value[0], (is_array($value[0]) ? 'array' : 'string'));
Derek Allard2067d1a2008-11-13 22:59:24 +0000280 }
281 else
282 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100283 if (is_array($value[0]) && ($value[1] === 'struct' OR $value[1] === 'array'))
Andrey Andreeva30faf92011-12-25 18:15:34 +0200284 {
285 while (list($k) = each($value[0]))
286 {
287 $value[0][$k] = $this->values_parsing($value[0][$k], TRUE);
288 }
289 }
290
291 $temp = new XML_RPC_Values($value[0], $value[1]);
Derek Allard2067d1a2008-11-13 22:59:24 +0000292 }
293 }
294 else
295 {
296 $temp = new XML_RPC_Values($value, 'string');
297 }
298
299 return $temp;
300 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000301
Andrey Andreevc8709832012-04-04 13:43:53 +0300302 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000303
Andrey Andreevc8709832012-04-04 13:43:53 +0300304 /**
305 * Sends XML-RPC Request
306 *
307 * @return bool
308 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200309 public function send_request()
Derek Allard2067d1a2008-11-13 22:59:24 +0000310 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300311 $this->message = new XML_RPC_Message($this->method, $this->data);
Derek Allard2067d1a2008-11-13 22:59:24 +0000312 $this->message->debug = $this->debug;
Barry Mienydd671972010-10-04 16:33:58 +0200313
Andrey Andreeva30faf92011-12-25 18:15:34 +0200314 if ( ! $this->result = $this->client->send($this->message) OR ! is_object($this->result->val))
Derek Allard2067d1a2008-11-13 22:59:24 +0000315 {
316 $this->error = $this->result->errstr;
317 return FALSE;
318 }
Barry Mienydd671972010-10-04 16:33:58 +0200319
Derek Allard2067d1a2008-11-13 22:59:24 +0000320 $this->response = $this->result->decode();
Derek Allard2067d1a2008-11-13 22:59:24 +0000321 return TRUE;
322 }
Barry Mienydd671972010-10-04 16:33:58 +0200323
Andrey Andreevc8709832012-04-04 13:43:53 +0300324 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000325
Andrey Andreevc8709832012-04-04 13:43:53 +0300326 /**
327 * Returns Error
328 *
329 * @return string
330 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200331 public function display_error()
Derek Allard2067d1a2008-11-13 22:59:24 +0000332 {
333 return $this->error;
334 }
Barry Mienydd671972010-10-04 16:33:58 +0200335
Andrey Andreevc8709832012-04-04 13:43:53 +0300336 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000337
Andrey Andreevc8709832012-04-04 13:43:53 +0300338 /**
339 * Returns Remote Server Response
340 *
341 * @return string
342 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200343 public function display_response()
Derek Allard2067d1a2008-11-13 22:59:24 +0000344 {
345 return $this->response;
346 }
Barry Mienydd671972010-10-04 16:33:58 +0200347
Andrey Andreevc8709832012-04-04 13:43:53 +0300348 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200349
Andrey Andreevc8709832012-04-04 13:43:53 +0300350 /**
351 * Sends an Error Message for Server Request
352 *
353 * @param int
354 * @param string
355 * @return object
356 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200357 public function send_error_message($number, $message)
Derek Allard2067d1a2008-11-13 22:59:24 +0000358 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200359 return new XML_RPC_Response(0, $number, $message);
Derek Allard2067d1a2008-11-13 22:59:24 +0000360 }
Barry Mienydd671972010-10-04 16:33:58 +0200361
Andrey Andreevc8709832012-04-04 13:43:53 +0300362 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200363
Andrey Andreevc8709832012-04-04 13:43:53 +0300364 /**
365 * Send Response for Server Request
366 *
367 * @param array
368 * @return object
369 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200370 public function send_response($response)
Derek Allard2067d1a2008-11-13 22:59:24 +0000371 {
372 // $response should be array of values, which will be parsed
373 // based on their data and type into a valid group of XML-RPC values
Andrey Andreeva30faf92011-12-25 18:15:34 +0200374 return new XML_RPC_Response($this->values_parsing($response));
Derek Allard2067d1a2008-11-13 22:59:24 +0000375 }
Barry Mienydd671972010-10-04 16:33:58 +0200376
Derek Allard2067d1a2008-11-13 22:59:24 +0000377} // END XML_RPC Class
378
Derek Allard2067d1a2008-11-13 22:59:24 +0000379/**
380 * XML-RPC Client class
381 *
382 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500383 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000384 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
385 */
386class XML_RPC_Client extends CI_Xmlrpc
387{
Andrey Andreeva30faf92011-12-25 18:15:34 +0200388 public $path = '';
389 public $server = '';
390 public $port = 80;
Valio9dee5352012-07-02 10:42:28 +0300391 public $proxy = FALSE;
392 public $proxy_port = 8080;
Andrey Andreeva30faf92011-12-25 18:15:34 +0200393 public $errno = '';
394 public $errstring = '';
395 public $timeout = 5;
396 public $no_multicall = FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000397
Andrey Andreevc8709832012-04-04 13:43:53 +0300398 /**
399 * Constructor
400 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300401 * @param string $path
402 * @param object $server
403 * @param int $port = 80
404 * @param string $proxy = FALSE
405 * @param int $proxy_port = 8080
Andrey Andreevc8709832012-04-04 13:43:53 +0300406 * @return void
407 */
Valio9dee5352012-07-02 10:42:28 +0300408 public function __construct($path, $server, $port = 80, $proxy = FALSE, $proxy_port = 8080)
Derek Allard2067d1a2008-11-13 22:59:24 +0000409 {
Greg Akera9263282010-11-10 15:26:43 -0600410 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +0200411
Derek Allard2067d1a2008-11-13 22:59:24 +0000412 $this->port = $port;
413 $this->server = $server;
414 $this->path = $path;
Valio9dee5352012-07-02 10:42:28 +0300415 $this->proxy = $proxy;
416 $this->proxy_port = $proxy_port;
Derek Allard2067d1a2008-11-13 22:59:24 +0000417 }
Barry Mienydd671972010-10-04 16:33:58 +0200418
Andrey Andreevc8709832012-04-04 13:43:53 +0300419 // --------------------------------------------------------------------
420
421 /**
422 * Send message
423 *
424 * @param mixed
425 * @return object
426 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200427 public function send($msg)
Derek Allard2067d1a2008-11-13 22:59:24 +0000428 {
429 if (is_array($msg))
430 {
431 // Multi-call disabled
Andrey Andreevc8709832012-04-04 13:43:53 +0300432 return new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'], $this->xmlrpcstr['multicall_recursion']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000433 }
434
435 return $this->sendPayload($msg);
436 }
437
Andrey Andreevc8709832012-04-04 13:43:53 +0300438 // --------------------------------------------------------------------
439
440 /**
441 * Send payload
442 *
443 * @param object
444 * @return object
445 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200446 public function sendPayload($msg)
Barry Mienydd671972010-10-04 16:33:58 +0200447 {
Andrey Andreevc02e7c52012-07-02 16:43:43 +0300448 if ($this->proxy === FALSE)
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300449 {
450 $server = $this->server;
451 $port = $this->port;
Valentin Sheyretski09217ce2012-07-02 16:27:01 +0300452 }
453 else
454 {
Valio9dee5352012-07-02 10:42:28 +0300455 $server = $this->proxy;
456 $port = $this->proxy_port;
457 }
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300458
Valio9dee5352012-07-02 10:42:28 +0300459 $fp = @fsockopen($server, $port, $this->errno, $this->errstring, $this->timeout);
Barry Mienydd671972010-10-04 16:33:58 +0200460
Derek Allard2067d1a2008-11-13 22:59:24 +0000461 if ( ! is_resource($fp))
462 {
463 error_log($this->xmlrpcstr['http_error']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300464 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000465 }
Barry Mienydd671972010-10-04 16:33:58 +0200466
Pascal Kriete14287f32011-02-14 13:39:34 -0500467 if (empty($msg->payload))
Derek Allard2067d1a2008-11-13 22:59:24 +0000468 {
469 // $msg = XML_RPC_Messages
470 $msg->createPayload();
471 }
Barry Mienydd671972010-10-04 16:33:58 +0200472
Derek Allard2067d1a2008-11-13 22:59:24 +0000473 $r = "\r\n";
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300474 $op = 'POST '.$this->path.' HTTP/1.0'.$r
475 .'Host: '.$this->server.$r
476 .'Content-Type: text/xml'.$r
477 .'User-Agent: '.$this->xmlrpcName.$r
478 .'Content-Length: '.strlen($msg->payload).$r.$r
479 .$msg->payload;
Barry Mienydd671972010-10-04 16:33:58 +0200480
George Petsagourakis306b3782012-05-02 20:31:08 +0300481 if ( ! fwrite($fp, $op, strlen($op)))
Derek Allard2067d1a2008-11-13 22:59:24 +0000482 {
483 error_log($this->xmlrpcstr['http_error']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300484 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000485 }
Andrey Andreevc8709832012-04-04 13:43:53 +0300486
Derek Allard2067d1a2008-11-13 22:59:24 +0000487 $resp = $msg->parseResponse($fp);
488 fclose($fp);
489 return $resp;
490 }
491
Andrey Andreevc8709832012-04-04 13:43:53 +0300492} // END XML_RPC_Client Class
Derek Allard2067d1a2008-11-13 22:59:24 +0000493
494/**
495 * XML-RPC Response class
496 *
497 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500498 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000499 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
500 */
501class XML_RPC_Response
502{
Andrey Andreevc8709832012-04-04 13:43:53 +0300503 public $val = 0;
504 public $errno = 0;
505 public $errstr = '';
506 public $headers = array();
507 public $xss_clean = TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000508
Andrey Andreevc8709832012-04-04 13:43:53 +0300509 /**
510 * Constructor
511 *
512 * @param mixed
513 * @param int
514 * @param string
515 * @return void
516 */
Greg Akera9263282010-11-10 15:26:43 -0600517 public function __construct($val, $code = 0, $fstr = '')
Barry Mienydd671972010-10-04 16:33:58 +0200518 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100519 if ($code !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000520 {
521 // error
522 $this->errno = $code;
Andrey Andreevc8709832012-04-04 13:43:53 +0300523 $this->errstr = htmlspecialchars($fstr,
524 (is_php('5.4') ? ENT_XML1 | ENT_NOQUOTES : ENT_NOQUOTES),
525 'UTF-8');
Derek Allard2067d1a2008-11-13 22:59:24 +0000526 }
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300527 elseif ( ! is_object($val))
Derek Allard2067d1a2008-11-13 22:59:24 +0000528 {
529 // programmer error, not an object
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300530 error_log("Invalid type '".gettype($val)."' (value: ".$val.') passed to XML_RPC_Response. Defaulting to empty value.');
Derek Allard2067d1a2008-11-13 22:59:24 +0000531 $this->val = new XML_RPC_Values();
532 }
533 else
534 {
535 $this->val = $val;
536 }
537 }
538
Andrey Andreevc8709832012-04-04 13:43:53 +0300539 // --------------------------------------------------------------------
540
541 /**
542 * Fault code
543 *
544 * @return int
545 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200546 public function faultCode()
Derek Allard2067d1a2008-11-13 22:59:24 +0000547 {
548 return $this->errno;
549 }
550
Andrey Andreevc8709832012-04-04 13:43:53 +0300551 // --------------------------------------------------------------------
552
553 /**
554 * Fault string
555 *
556 * @return string
557 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200558 public function faultString()
Derek Allard2067d1a2008-11-13 22:59:24 +0000559 {
560 return $this->errstr;
561 }
562
Andrey Andreevc8709832012-04-04 13:43:53 +0300563 // --------------------------------------------------------------------
564
565 /**
566 * Value
567 *
568 * @return mixed
569 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200570 public function value()
Derek Allard2067d1a2008-11-13 22:59:24 +0000571 {
572 return $this->val;
573 }
Barry Mienydd671972010-10-04 16:33:58 +0200574
Andrey Andreevc8709832012-04-04 13:43:53 +0300575 // --------------------------------------------------------------------
576
577 /**
578 * Prepare response
579 *
580 * @return string xml
581 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200582 public function prepare_response()
Derek Allard2067d1a2008-11-13 22:59:24 +0000583 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200584 return "<methodResponse>\n"
Andrey Andreevc8709832012-04-04 13:43:53 +0300585 .($this->errno
586 ? '<fault>
Derek Allard2067d1a2008-11-13 22:59:24 +0000587 <value>
588 <struct>
589 <member>
590 <name>faultCode</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300591 <value><int>'.$this->errno.'</int></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000592 </member>
593 <member>
594 <name>faultString</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300595 <value><string>'.$this->errstr.'</string></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000596 </member>
597 </struct>
598 </value>
Andrey Andreeva30faf92011-12-25 18:15:34 +0200599</fault>'
Andrey Andreevc8709832012-04-04 13:43:53 +0300600 : "<params>\n<param>\n".$this->val->serialize_class()."</param>\n</params>")
601 ."\n</methodResponse>";
Derek Allard2067d1a2008-11-13 22:59:24 +0000602 }
Barry Mienydd671972010-10-04 16:33:58 +0200603
Andrey Andreevc8709832012-04-04 13:43:53 +0300604 // --------------------------------------------------------------------
605
606 /**
607 * Decode
608 *
609 * @param mixed
610 * @return array
611 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200612 public function decode($array = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000613 {
614 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +0200615
616 if (is_array($array))
Derek Allard2067d1a2008-11-13 22:59:24 +0000617 {
618 while (list($key) = each($array))
619 {
620 if (is_array($array[$key]))
621 {
622 $array[$key] = $this->decode($array[$key]);
623 }
624 else
625 {
Robin Sowell66a3fc02010-03-18 09:44:55 -0400626 $array[$key] = ($this->xss_clean) ? $CI->security->xss_clean($array[$key]) : $array[$key];
Derek Allard2067d1a2008-11-13 22:59:24 +0000627 }
628 }
Barry Mienydd671972010-10-04 16:33:58 +0200629
Andrey Andreevc8709832012-04-04 13:43:53 +0300630 return $array;
631 }
632
633 $result = $this->xmlrpc_decoder($this->val);
634
635 if (is_array($result))
636 {
637 $result = $this->decode($result);
Derek Allard2067d1a2008-11-13 22:59:24 +0000638 }
639 else
640 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300641 $result = ($this->xss_clean) ? $CI->security->xss_clean($result) : $result;
Derek Allard2067d1a2008-11-13 22:59:24 +0000642 }
Barry Mienydd671972010-10-04 16:33:58 +0200643
Derek Allard2067d1a2008-11-13 22:59:24 +0000644 return $result;
645 }
646
Andrey Andreevc8709832012-04-04 13:43:53 +0300647 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000648
Andrey Andreevc8709832012-04-04 13:43:53 +0300649 /**
650 * XML-RPC Object to PHP Types
651 *
652 * @param object
653 * @return array
654 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200655 public function xmlrpc_decoder($xmlrpc_val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000656 {
657 $kind = $xmlrpc_val->kindOf();
658
Alex Bilbied261b1e2012-06-02 11:12:16 +0100659 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +0000660 {
661 return $xmlrpc_val->scalarval();
662 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100663 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +0000664 {
665 reset($xmlrpc_val->me);
Andrey Andreevadc11752011-12-30 14:46:08 +0200666 $b = current($xmlrpc_val->me);
Derek Allard2067d1a2008-11-13 22:59:24 +0000667 $arr = array();
668
Andrey Andreeva30faf92011-12-25 18:15:34 +0200669 for ($i = 0, $size = count($b); $i < $size; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000670 {
671 $arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);
672 }
673 return $arr;
674 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100675 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +0000676 {
677 reset($xmlrpc_val->me['struct']);
678 $arr = array();
679
Pascal Kriete14287f32011-02-14 13:39:34 -0500680 while (list($key,$value) = each($xmlrpc_val->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000681 {
682 $arr[$key] = $this->xmlrpc_decoder($value);
683 }
684 return $arr;
685 }
686 }
Barry Mienydd671972010-10-04 16:33:58 +0200687
Andrey Andreevc8709832012-04-04 13:43:53 +0300688 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000689
Andrey Andreevc8709832012-04-04 13:43:53 +0300690 /**
691 * ISO-8601 time to server or UTC time
692 *
693 * @param string
694 * @param bool
695 * @return int unix timestamp
696 */
697 public function iso8601_decode($time, $utc = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000698 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300699 // return a time in the localtime, or UTC
Derek Allard2067d1a2008-11-13 22:59:24 +0000700 $t = 0;
701 if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))
702 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100703 $fnc = ($utc === TRUE) ? 'gmmktime' : 'mktime';
Pascal Kriete14287f32011-02-14 13:39:34 -0500704 $t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
Derek Allard2067d1a2008-11-13 22:59:24 +0000705 }
706 return $t;
707 }
Barry Mienydd671972010-10-04 16:33:58 +0200708
Andrey Andreevc8709832012-04-04 13:43:53 +0300709} // END XML_RPC_Response Class
Derek Allard2067d1a2008-11-13 22:59:24 +0000710
711/**
712 * XML-RPC Message class
713 *
714 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500715 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000716 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
717 */
718class XML_RPC_Message extends CI_Xmlrpc
719{
Andrey Andreeva30faf92011-12-25 18:15:34 +0200720 public $payload;
721 public $method_name;
Andrey Andreevc8709832012-04-04 13:43:53 +0300722 public $params = array();
723 public $xh = array();
Derek Allard2067d1a2008-11-13 22:59:24 +0000724
Andrey Andreevc8709832012-04-04 13:43:53 +0300725 /**
726 * Constructor
727 *
728 * @param string method name
729 * @param array
730 * @return void
731 */
732 public function __construct($method, $pars = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000733 {
Greg Akera9263282010-11-10 15:26:43 -0600734 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +0200735
Derek Allard2067d1a2008-11-13 22:59:24 +0000736 $this->method_name = $method;
Derek Jones33559102009-02-02 18:50:38 +0000737 if (is_array($pars) && count($pars) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000738 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200739 for ($i = 0, $c = count($pars); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000740 {
741 // $pars[$i] = XML_RPC_Values
742 $this->params[] = $pars[$i];
743 }
744 }
745 }
Barry Mienydd671972010-10-04 16:33:58 +0200746
Andrey Andreevc8709832012-04-04 13:43:53 +0300747 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200748
Andrey Andreevc8709832012-04-04 13:43:53 +0300749 /**
750 * Create Payload to Send
751 *
752 * @return void
753 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200754 public function createPayload()
Derek Allard2067d1a2008-11-13 22:59:24 +0000755 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300756 $this->payload = '<?xml version="1.0"?'.">\r\n<methodCall>\r\n"
757 .'<methodName>'.$this->method_name."</methodName>\r\n"
758 ."<params>\r\n";
Barry Mienydd671972010-10-04 16:33:58 +0200759
Andrey Andreeva30faf92011-12-25 18:15:34 +0200760 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000761 {
762 // $p = XML_RPC_Values
763 $p = $this->params[$i];
764 $this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n";
765 }
Barry Mienydd671972010-10-04 16:33:58 +0200766
Derek Allard2067d1a2008-11-13 22:59:24 +0000767 $this->payload .= "</params>\r\n</methodCall>\r\n";
768 }
Barry Mienydd671972010-10-04 16:33:58 +0200769
Andrey Andreevc8709832012-04-04 13:43:53 +0300770 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200771
Andrey Andreevc8709832012-04-04 13:43:53 +0300772 /**
773 * Parse External XML-RPC Server's Response
774 *
775 * @param resource
776 * @return object
777 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200778 public function parseResponse($fp)
Derek Allard2067d1a2008-11-13 22:59:24 +0000779 {
780 $data = '';
Barry Mienydd671972010-10-04 16:33:58 +0200781
Pascal Kriete14287f32011-02-14 13:39:34 -0500782 while ($datum = fread($fp, 4096))
Derek Allard2067d1a2008-11-13 22:59:24 +0000783 {
784 $data .= $datum;
785 }
Barry Mienydd671972010-10-04 16:33:58 +0200786
Andrey Andreevc8709832012-04-04 13:43:53 +0300787 // Display HTTP content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +0000788 if ($this->debug === TRUE)
789 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200790 echo "<pre>---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n</pre>";
Derek Allard2067d1a2008-11-13 22:59:24 +0000791 }
Barry Mienydd671972010-10-04 16:33:58 +0200792
Andrey Andreevc8709832012-04-04 13:43:53 +0300793 // Check for data
Andrey Andreeva30faf92011-12-25 18:15:34 +0200794 if ($data === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000795 {
796 error_log($this->xmlrpcstr['no_data']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300797 return new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000798 }
Barry Mienydd671972010-10-04 16:33:58 +0200799
Andrey Andreevc8709832012-04-04 13:43:53 +0300800 // Check for HTTP 200 Response
Andrey Andreev3dad2e72012-06-14 15:10:56 +0300801 if (strpos($data, 'HTTP') === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
Derek Allard2067d1a2008-11-13 22:59:24 +0000802 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300803 $errstr = substr($data, 0, strpos($data, "\n")-1);
804 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');
Derek Allard2067d1a2008-11-13 22:59:24 +0000805 }
Barry Mienydd671972010-10-04 16:33:58 +0200806
Derek Allard2067d1a2008-11-13 22:59:24 +0000807 //-------------------------------------
Derek Jones37f4b9c2011-07-01 17:56:50 -0500808 // Create and Set Up XML Parser
Derek Allard2067d1a2008-11-13 22:59:24 +0000809 //-------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200810
Derek Allard2067d1a2008-11-13 22:59:24 +0000811 $parser = xml_parser_create($this->xmlrpc_defencoding);
812
Andrey Andreeva30faf92011-12-25 18:15:34 +0200813 $this->xh[$parser] = array(
Andrey Andreevc8709832012-04-04 13:43:53 +0300814 'isf' => 0,
815 'ac' => '',
816 'headers' => array(),
817 'stack' => array(),
818 'valuestack' => array(),
819 'isf_reason' => 0
Andrey Andreeva30faf92011-12-25 18:15:34 +0200820 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000821
822 xml_set_object($parser, $this);
Andrey Andreevc8709832012-04-04 13:43:53 +0300823 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000824 xml_set_element_handler($parser, 'open_tag', 'closing_tag');
825 xml_set_character_data_handler($parser, 'character_data');
826 //xml_set_default_handler($parser, 'default_handler');
827
Andrey Andreevc8709832012-04-04 13:43:53 +0300828 // Get headers
Derek Allard2067d1a2008-11-13 22:59:24 +0000829 $lines = explode("\r\n", $data);
830 while (($line = array_shift($lines)))
831 {
832 if (strlen($line) < 1)
833 {
834 break;
835 }
836 $this->xh[$parser]['headers'][] = $line;
837 }
838 $data = implode("\r\n", $lines);
Barry Mienydd671972010-10-04 16:33:58 +0200839
Andrey Andreevc8709832012-04-04 13:43:53 +0300840 // Parse XML data
Derek Jones33559102009-02-02 18:50:38 +0000841 if ( ! xml_parse($parser, $data, count($data)))
Derek Allard2067d1a2008-11-13 22:59:24 +0000842 {
843 $errstr = sprintf('XML error: %s at line %d',
Andrey Andreevc8709832012-04-04 13:43:53 +0300844 xml_error_string(xml_get_error_code($parser)),
845 xml_get_current_line_number($parser));
Derek Allard2067d1a2008-11-13 22:59:24 +0000846 //error_log($errstr);
847 $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
848 xml_parser_free($parser);
849 return $r;
850 }
851 xml_parser_free($parser);
Barry Mienydd671972010-10-04 16:33:58 +0200852
Andrey Andreevc8709832012-04-04 13:43:53 +0300853 // Got ourselves some badness, it seems
Derek Allard2067d1a2008-11-13 22:59:24 +0000854 if ($this->xh[$parser]['isf'] > 1)
855 {
856 if ($this->debug === TRUE)
857 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200858 echo "---Invalid Return---\n".$this->xh[$parser]['isf_reason']."---Invalid Return---\n\n";
Derek Allard2067d1a2008-11-13 22:59:24 +0000859 }
Barry Mienydd671972010-10-04 16:33:58 +0200860
Andrey Andreevc8709832012-04-04 13:43:53 +0300861 return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000862 }
863 elseif ( ! is_object($this->xh[$parser]['value']))
864 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300865 return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000866 }
Barry Mienydd671972010-10-04 16:33:58 +0200867
Andrey Andreevc8709832012-04-04 13:43:53 +0300868 // Display XML content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +0000869 if ($this->debug === TRUE)
870 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300871 echo '<pre>';
Barry Mienydd671972010-10-04 16:33:58 +0200872
Derek Allard2067d1a2008-11-13 22:59:24 +0000873 if (count($this->xh[$parser]['headers'] > 0))
874 {
875 echo "---HEADERS---\n";
876 foreach ($this->xh[$parser]['headers'] as $header)
877 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300878 echo $header."\n";
Derek Allard2067d1a2008-11-13 22:59:24 +0000879 }
880 echo "---END HEADERS---\n\n";
881 }
Barry Mienydd671972010-10-04 16:33:58 +0200882
Andrey Andreeva30faf92011-12-25 18:15:34 +0200883 echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n---PARSED---\n";
Derek Allard2067d1a2008-11-13 22:59:24 +0000884 var_dump($this->xh[$parser]['value']);
885 echo "\n---END PARSED---</pre>";
886 }
Barry Mienydd671972010-10-04 16:33:58 +0200887
Andrey Andreevc8709832012-04-04 13:43:53 +0300888 // Send response
Derek Allard2067d1a2008-11-13 22:59:24 +0000889 $v = $this->xh[$parser]['value'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000890 if ($this->xh[$parser]['isf'])
891 {
892 $errno_v = $v->me['struct']['faultCode'];
893 $errstr_v = $v->me['struct']['faultString'];
894 $errno = $errno_v->scalarval();
895
Alex Bilbied261b1e2012-06-02 11:12:16 +0100896 if ($errno === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000897 {
898 // FAULT returned, errno needs to reflect that
899 $errno = -1;
900 }
901
902 $r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
903 }
904 else
905 {
906 $r = new XML_RPC_Response($v);
907 }
908
909 $r->headers = $this->xh[$parser]['headers'];
910 return $r;
911 }
Barry Mienydd671972010-10-04 16:33:58 +0200912
Andrey Andreevc8709832012-04-04 13:43:53 +0300913 // --------------------------------------------------------------------
914
Derek Allard2067d1a2008-11-13 22:59:24 +0000915 // ------------------------------------
Derek Jones37f4b9c2011-07-01 17:56:50 -0500916 // Begin Return Message Parsing section
Derek Allard2067d1a2008-11-13 22:59:24 +0000917 // ------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200918
Derek Allard2067d1a2008-11-13 22:59:24 +0000919 // quick explanation of components:
Derek Jones37f4b9c2011-07-01 17:56:50 -0500920 // ac - used to accumulate values
921 // isf - used to indicate a fault
922 // lv - used to indicate "looking for a value": implements
Derek Allard2067d1a2008-11-13 22:59:24 +0000923 // the logic to allow values with no types to be strings
Derek Jones37f4b9c2011-07-01 17:56:50 -0500924 // params - used to store parameters in method calls
925 // method - used to store method name
Derek Allard2067d1a2008-11-13 22:59:24 +0000926 // stack - array with parent tree of the xml element,
927 // used to validate the nesting of elements
928
Andrey Andreevc8709832012-04-04 13:43:53 +0300929 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000930
Andrey Andreevc8709832012-04-04 13:43:53 +0300931 /**
932 * Start Element Handler
933 *
934 * @param string
935 * @param string
936 * @return void
937 */
938 public function open_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +0000939 {
940 // If invalid nesting, then return
941 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +0200942
Derek Allard2067d1a2008-11-13 22:59:24 +0000943 // Evaluate and check for correct nesting of XML elements
Alex Bilbied261b1e2012-06-02 11:12:16 +0100944 if (count($this->xh[$the_parser]['stack']) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000945 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100946 if ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')
Derek Allard2067d1a2008-11-13 22:59:24 +0000947 {
948 $this->xh[$the_parser]['isf'] = 2;
949 $this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
950 return;
951 }
952 }
Andrey Andreevc8709832012-04-04 13:43:53 +0300953 // not top level element: see if parent is OK
954 elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +0000955 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300956 $this->xh[$the_parser]['isf'] = 2;
957 $this->xh[$the_parser]['isf_reason'] = 'XML-RPC element $name cannot be child of '.$this->xh[$the_parser]['stack'][0];
958 return;
Derek Allard2067d1a2008-11-13 22:59:24 +0000959 }
Barry Mienydd671972010-10-04 16:33:58 +0200960
Andrey Andreevc8709832012-04-04 13:43:53 +0300961 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +0000962 {
963 case 'STRUCT':
964 case 'ARRAY':
965 // Creates array for child elements
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300966 $cur_val = array('value' => array(), 'type' => $name);
Derek Allard2067d1a2008-11-13 22:59:24 +0000967 array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
Andrey Andreevc8709832012-04-04 13:43:53 +0300968 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000969 case 'METHODNAME':
970 case 'NAME':
971 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +0300972 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000973 case 'FAULT':
974 $this->xh[$the_parser]['isf'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +0300975 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000976 case 'PARAM':
Pascal Kriete8761ef52011-02-14 13:13:52 -0500977 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +0300978 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000979 case 'VALUE':
980 $this->xh[$the_parser]['vt'] = 'value';
981 $this->xh[$the_parser]['ac'] = '';
982 $this->xh[$the_parser]['lv'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +0300983 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000984 case 'I4':
985 case 'INT':
986 case 'STRING':
987 case 'BOOLEAN':
988 case 'DOUBLE':
989 case 'DATETIME.ISO8601':
990 case 'BASE64':
Alex Bilbied261b1e2012-06-02 11:12:16 +0100991 if ($this->xh[$the_parser]['vt'] !== 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +0000992 {
993 //two data elements inside a value: an error occurred!
994 $this->xh[$the_parser]['isf'] = 2;
Andrey Andreevc8709832012-04-04 13:43:53 +0300995 $this->xh[$the_parser]['isf_reason'] = "'Twas a ".$name.' element following a '
996 .$this->xh[$the_parser]['vt'].' element inside a single value';
Derek Allard2067d1a2008-11-13 22:59:24 +0000997 return;
998 }
Barry Mienydd671972010-10-04 16:33:58 +0200999
Derek Allard2067d1a2008-11-13 22:59:24 +00001000 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +03001001 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001002 case 'MEMBER':
1003 // Set name of <member> to nothing to prevent errors later if no <name> is found
1004 $this->xh[$the_parser]['valuestack'][0]['name'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001005
Derek Allard2067d1a2008-11-13 22:59:24 +00001006 // Set NULL value to check to see if value passed for this param/member
Pascal Kriete8761ef52011-02-14 13:13:52 -05001007 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +03001008 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001009 case 'DATA':
1010 case 'METHODCALL':
1011 case 'METHODRESPONSE':
1012 case 'PARAMS':
1013 // valid elements that add little to processing
Andrey Andreevc8709832012-04-04 13:43:53 +03001014 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001015 default:
1016 /// An Invalid Element is Found, so we have trouble
1017 $this->xh[$the_parser]['isf'] = 2;
Andrey Andreevc8709832012-04-04 13:43:53 +03001018 $this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;
1019 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001020 }
Barry Mienydd671972010-10-04 16:33:58 +02001021
Derek Allard2067d1a2008-11-13 22:59:24 +00001022 // Add current element name to stack, to allow validation of nesting
1023 array_unshift($this->xh[$the_parser]['stack'], $name);
1024
Alex Bilbied261b1e2012-06-02 11:12:16 +01001025 $name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001026 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001027
Andrey Andreevc8709832012-04-04 13:43:53 +03001028 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001029
Andrey Andreevc8709832012-04-04 13:43:53 +03001030 /**
1031 * End Element Handler
1032 *
1033 * @param string
1034 * @param string
1035 * @return void
1036 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001037 public function closing_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001038 {
1039 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001040
Derek Allard2067d1a2008-11-13 22:59:24 +00001041 // Remove current element from stack and set variable
1042 // NOTE: If the XML validates, then we do not have to worry about
Andrey Andreevc8709832012-04-04 13:43:53 +03001043 // the opening and closing of elements. Nesting is checked on the opening
Derek Allard2067d1a2008-11-13 22:59:24 +00001044 // tag so we be safe there as well.
Barry Mienydd671972010-10-04 16:33:58 +02001045
Derek Allard2067d1a2008-11-13 22:59:24 +00001046 $curr_elem = array_shift($this->xh[$the_parser]['stack']);
Barry Mienydd671972010-10-04 16:33:58 +02001047
Andrey Andreevc8709832012-04-04 13:43:53 +03001048 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001049 {
1050 case 'STRUCT':
1051 case 'ARRAY':
1052 $cur_val = array_shift($this->xh[$the_parser]['valuestack']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001053 $this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();
Derek Allard2067d1a2008-11-13 22:59:24 +00001054 $this->xh[$the_parser]['vt'] = strtolower($name);
Andrey Andreevc8709832012-04-04 13:43:53 +03001055 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001056 case 'NAME':
1057 $this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
Andrey Andreevc8709832012-04-04 13:43:53 +03001058 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001059 case 'BOOLEAN':
1060 case 'I4':
1061 case 'INT':
1062 case 'STRING':
1063 case 'DOUBLE':
1064 case 'DATETIME.ISO8601':
1065 case 'BASE64':
1066 $this->xh[$the_parser]['vt'] = strtolower($name);
Barry Mienydd671972010-10-04 16:33:58 +02001067
Alex Bilbied261b1e2012-06-02 11:12:16 +01001068 if ($name === 'STRING')
Derek Allard2067d1a2008-11-13 22:59:24 +00001069 {
1070 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1071 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001072 elseif ($name === 'DATETIME.ISO8601')
Derek Allard2067d1a2008-11-13 22:59:24 +00001073 {
1074 $this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime;
1075 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1076 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001077 elseif ($name === 'BASE64')
Derek Allard2067d1a2008-11-13 22:59:24 +00001078 {
1079 $this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
1080 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001081 elseif ($name === 'BOOLEAN')
Derek Allard2067d1a2008-11-13 22:59:24 +00001082 {
1083 // Translated BOOLEAN values to TRUE AND FALSE
Andrey Andreevc8709832012-04-04 13:43:53 +03001084 $this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001085 }
1086 elseif ($name=='DOUBLE')
1087 {
1088 // we have a DOUBLE
1089 // we must check that only 0123456789-.<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001090 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])
1091 ? (float) $this->xh[$the_parser]['ac']
1092 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001093 }
1094 else
1095 {
1096 // we have an I4/INT
1097 // we must check that only 0123456789-<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001098 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])
George Petsagourakis306b3782012-05-02 20:31:08 +03001099 ? (int) $this->xh[$the_parser]['ac']
Andrey Andreevc8709832012-04-04 13:43:53 +03001100 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001101 }
1102 $this->xh[$the_parser]['ac'] = '';
1103 $this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
Andrey Andreevc8709832012-04-04 13:43:53 +03001104 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001105 case 'VALUE':
1106 // This if() detects if no scalar was inside <VALUE></VALUE>
1107 if ($this->xh[$the_parser]['vt']=='value')
1108 {
1109 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1110 $this->xh[$the_parser]['vt'] = $this->xmlrpcString;
1111 }
Barry Mienydd671972010-10-04 16:33:58 +02001112
Derek Allard2067d1a2008-11-13 22:59:24 +00001113 // build the XML-RPC value out of the data received, and substitute it
1114 $temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
Barry Mienydd671972010-10-04 16:33:58 +02001115
Alex Bilbied261b1e2012-06-02 11:12:16 +01001116 if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')
Derek Allard2067d1a2008-11-13 22:59:24 +00001117 {
1118 // Array
1119 $this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
1120 }
1121 else
1122 {
1123 // Struct
1124 $this->xh[$the_parser]['value'] = $temp;
1125 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001126 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001127 case 'MEMBER':
Andrey Andreevc8709832012-04-04 13:43:53 +03001128 $this->xh[$the_parser]['ac'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001129
Derek Allard2067d1a2008-11-13 22:59:24 +00001130 // If value add to array in the stack for the last element built
1131 if ($this->xh[$the_parser]['value'])
1132 {
1133 $this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
1134 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001135 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001136 case 'DATA':
Andrey Andreevc8709832012-04-04 13:43:53 +03001137 $this->xh[$the_parser]['ac'] = '';
1138 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001139 case 'PARAM':
1140 if ($this->xh[$the_parser]['value'])
1141 {
1142 $this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
1143 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001144 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001145 case 'METHODNAME':
1146 $this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001147 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001148 case 'PARAMS':
1149 case 'FAULT':
1150 case 'METHODCALL':
1151 case 'METHORESPONSE':
1152 // We're all good kids with nuthin' to do
Andrey Andreevc8709832012-04-04 13:43:53 +03001153 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001154 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001155 // End of an Invalid Element. Taken care of during the opening tag though
1156 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001157 }
1158 }
1159
Andrey Andreevc8709832012-04-04 13:43:53 +03001160 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001161
Andrey Andreevc8709832012-04-04 13:43:53 +03001162 /**
1163 * Parse character data
1164 *
1165 * @param string
1166 * @param string
1167 * @return void
1168 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001169 public function character_data($the_parser, $data)
Derek Allard2067d1a2008-11-13 22:59:24 +00001170 {
1171 if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
Barry Mienydd671972010-10-04 16:33:58 +02001172
Derek Allard2067d1a2008-11-13 22:59:24 +00001173 // If a value has not been found
Alex Bilbied261b1e2012-06-02 11:12:16 +01001174 if ($this->xh[$the_parser]['lv'] !== 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001175 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001176 if ($this->xh[$the_parser]['lv'] === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001177 {
1178 $this->xh[$the_parser]['lv'] = 2; // Found a value
1179 }
Barry Mienydd671972010-10-04 16:33:58 +02001180
Andrey Andreevc8709832012-04-04 13:43:53 +03001181 if ( ! isset($this->xh[$the_parser]['ac']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001182 {
1183 $this->xh[$the_parser]['ac'] = '';
1184 }
Barry Mienydd671972010-10-04 16:33:58 +02001185
Derek Allard2067d1a2008-11-13 22:59:24 +00001186 $this->xh[$the_parser]['ac'] .= $data;
1187 }
1188 }
Barry Mienydd671972010-10-04 16:33:58 +02001189
Andrey Andreevc8709832012-04-04 13:43:53 +03001190 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001191
Andrey Andreevc8709832012-04-04 13:43:53 +03001192 /**
1193 * Add parameter
1194 *
1195 * @param mixed
1196 * @return void
1197 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001198 public function addParam($par)
1199 {
1200 $this->params[] = $par;
1201 }
Barry Mienydd671972010-10-04 16:33:58 +02001202
Andrey Andreevc8709832012-04-04 13:43:53 +03001203 // --------------------------------------------------------------------
1204
1205 /**
1206 * Output parameters
1207 *
1208 * @param array
1209 * @return array
1210 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001211 public function output_parameters($array = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001212 {
Barry Mienydd671972010-10-04 16:33:58 +02001213 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +02001214
1215 if (is_array($array))
Derek Allard2067d1a2008-11-13 22:59:24 +00001216 {
1217 while (list($key) = each($array))
1218 {
1219 if (is_array($array[$key]))
1220 {
1221 $array[$key] = $this->output_parameters($array[$key]);
1222 }
1223 else
1224 {
Derek Jonesa9647e82010-03-02 22:59:07 -06001225 // 'bits' is for the MetaWeblog API image bits
1226 // @todo - this needs to be made more general purpose
Alex Bilbied261b1e2012-06-02 11:12:16 +01001227 $array[$key] = ($key === 'bits' OR $this->xss_clean === FALSE) ? $array[$key] : $CI->security->xss_clean($array[$key]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001228 }
1229 }
Barry Mienydd671972010-10-04 16:33:58 +02001230
Andrey Andreevc8709832012-04-04 13:43:53 +03001231 return $array;
Derek Allard2067d1a2008-11-13 22:59:24 +00001232 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001233
1234 $parameters = array();
1235
1236 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001237 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001238 $a_param = $this->decode_message($this->params[$i]);
Barry Mienydd671972010-10-04 16:33:58 +02001239
Andrey Andreevc8709832012-04-04 13:43:53 +03001240 if (is_array($a_param))
Derek Allard2067d1a2008-11-13 22:59:24 +00001241 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001242 $parameters[] = $this->output_parameters($a_param);
1243 }
1244 else
1245 {
1246 $parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;
Barry Mienydd671972010-10-04 16:33:58 +02001247 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001248 }
Barry Mienydd671972010-10-04 16:33:58 +02001249
Derek Allard2067d1a2008-11-13 22:59:24 +00001250 return $parameters;
1251 }
Barry Mienydd671972010-10-04 16:33:58 +02001252
Andrey Andreevc8709832012-04-04 13:43:53 +03001253 // --------------------------------------------------------------------
1254
1255 /**
1256 * Decode message
1257 *
1258 * @param object
1259 * @return mixed
1260 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001261 public function decode_message($param)
Derek Allard2067d1a2008-11-13 22:59:24 +00001262 {
1263 $kind = $param->kindOf();
1264
Alex Bilbied261b1e2012-06-02 11:12:16 +01001265 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +00001266 {
1267 return $param->scalarval();
1268 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001269 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +00001270 {
1271 reset($param->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001272 $b = current($param->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001273 $arr = array();
1274
Andrey Andreevc8709832012-04-04 13:43:53 +03001275 for ($i = 0, $c = count($b); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001276 {
1277 $arr[] = $this->decode_message($param->me['array'][$i]);
1278 }
Barry Mienydd671972010-10-04 16:33:58 +02001279
Derek Allard2067d1a2008-11-13 22:59:24 +00001280 return $arr;
1281 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001282 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +00001283 {
1284 reset($param->me['struct']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001285 $arr = array();
1286
Pascal Kriete14287f32011-02-14 13:39:34 -05001287 while (list($key,$value) = each($param->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001288 {
1289 $arr[$key] = $this->decode_message($value);
1290 }
Barry Mienydd671972010-10-04 16:33:58 +02001291
Derek Allard2067d1a2008-11-13 22:59:24 +00001292 return $arr;
1293 }
1294 }
Barry Mienydd671972010-10-04 16:33:58 +02001295
Andrey Andreevc8709832012-04-04 13:43:53 +03001296} // END XML_RPC_Message Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001297
1298/**
1299 * XML-RPC Values class
1300 *
1301 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -05001302 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +00001303 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
1304 */
1305class XML_RPC_Values extends CI_Xmlrpc
1306{
Andrey Andreeva30faf92011-12-25 18:15:34 +02001307 public $me = array();
1308 public $mytype = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001309
Andrey Andreevc8709832012-04-04 13:43:53 +03001310 /**
1311 * Constructor
1312 *
1313 * @param mixed
1314 * @param string
1315 * @return void
1316 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001317 public function __construct($val = -1, $type = '')
Barry Mienydd671972010-10-04 16:33:58 +02001318 {
Greg Akera9263282010-11-10 15:26:43 -06001319 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +02001320
Alex Bilbied261b1e2012-06-02 11:12:16 +01001321 if ($val !== -1 OR $type !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001322 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001323 $type = $type === '' ? 'string' : $type;
Barry Mienydd671972010-10-04 16:33:58 +02001324
Dimitar740480a2012-10-05 13:24:59 +03001325 if ($this->xmlrpcTypes[$type] == 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001326 {
1327 $this->addScalar($val,$type);
1328 }
Dimitar740480a2012-10-05 13:24:59 +03001329 elseif ($this->xmlrpcTypes[$type] == 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001330 {
1331 $this->addArray($val);
1332 }
Dimitar740480a2012-10-05 13:24:59 +03001333 elseif ($this->xmlrpcTypes[$type] == 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001334 {
1335 $this->addStruct($val);
1336 }
1337 }
1338 }
1339
Andrey Andreevc8709832012-04-04 13:43:53 +03001340 // --------------------------------------------------------------------
1341
1342 /**
1343 * Add scalar value
1344 *
1345 * @param scalar
1346 * @param string
1347 * @return int
1348 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001349 public function addScalar($val, $type = 'string')
Derek Allard2067d1a2008-11-13 22:59:24 +00001350 {
1351 $typeof = $this->xmlrpcTypes[$type];
Barry Mienydd671972010-10-04 16:33:58 +02001352
Alex Bilbied261b1e2012-06-02 11:12:16 +01001353 if ($this->mytype === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001354 {
1355 echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
1356 return 0;
1357 }
Barry Mienydd671972010-10-04 16:33:58 +02001358
Dimitar740480a2012-10-05 13:24:59 +03001359 if ($typeof != 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001360 {
1361 echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';
1362 return 0;
1363 }
1364
Alex Bilbied261b1e2012-06-02 11:12:16 +01001365 if ($type === $this->xmlrpcBoolean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001366 {
Andrey Andreev3f3f1352012-09-05 16:39:28 +03001367 $val = (int) (strcasecmp($val, 'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
Derek Allard2067d1a2008-11-13 22:59:24 +00001368 }
1369
Alex Bilbied261b1e2012-06-02 11:12:16 +01001370 if ($this->mytype === 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001371 {
1372 // adding to an array here
1373 $ar = $this->me['array'];
1374 $ar[] = new XML_RPC_Values($val, $type);
1375 $this->me['array'] = $ar;
1376 }
1377 else
1378 {
1379 // a scalar, so set the value and remember we're scalar
1380 $this->me[$type] = $val;
1381 $this->mytype = $typeof;
1382 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001383
Derek Allard2067d1a2008-11-13 22:59:24 +00001384 return 1;
1385 }
1386
Andrey Andreevc8709832012-04-04 13:43:53 +03001387 // --------------------------------------------------------------------
1388
1389 /**
1390 * Add array value
1391 *
1392 * @param array
1393 * @return int
1394 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001395 public function addArray($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001396 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001397 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001398 {
1399 echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
1400 return 0;
1401 }
1402
1403 $this->mytype = $this->xmlrpcTypes['array'];
1404 $this->me['array'] = $vals;
1405 return 1;
1406 }
1407
Andrey Andreevc8709832012-04-04 13:43:53 +03001408 // --------------------------------------------------------------------
1409
1410 /**
1411 * Add struct value
1412 *
1413 * @param object
1414 * @return int
1415 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001416 public function addStruct($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001417 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001418 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001419 {
1420 echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
1421 return 0;
1422 }
1423 $this->mytype = $this->xmlrpcTypes['struct'];
1424 $this->me['struct'] = $vals;
1425 return 1;
1426 }
1427
Andrey Andreevc8709832012-04-04 13:43:53 +03001428 // --------------------------------------------------------------------
1429
1430 /**
1431 * Get value type
1432 *
1433 * @return string
1434 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001435 public function kindOf()
Derek Allard2067d1a2008-11-13 22:59:24 +00001436 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001437 switch ($this->mytype)
Derek Allard2067d1a2008-11-13 22:59:24 +00001438 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001439 case 3: return 'struct';
1440 case 2: return 'array';
1441 case 1: return 'scalar';
1442 default: return 'undef';
Derek Allard2067d1a2008-11-13 22:59:24 +00001443 }
1444 }
1445
Andrey Andreevc8709832012-04-04 13:43:53 +03001446 // --------------------------------------------------------------------
1447
1448 /**
1449 * Serialize data
1450 *
1451 * @param string
1452 * @param mixed
1453 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001454 public function serializedata($typ, $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001455 {
1456 $rs = '';
Derek Jonesa9647e82010-03-02 22:59:07 -06001457
Andrey Andreevc8709832012-04-04 13:43:53 +03001458 switch ($this->xmlrpcTypes[$typ])
Derek Allard2067d1a2008-11-13 22:59:24 +00001459 {
1460 case 3:
1461 // struct
1462 $rs .= "<struct>\n";
1463 reset($val);
Pascal Kriete14287f32011-02-14 13:39:34 -05001464 while (list($key2, $val2) = each($val))
Derek Allard2067d1a2008-11-13 22:59:24 +00001465 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001466 $rs .= "<member>\n<name>{$key2}</name>\n".$this->serializeval($val2)."</member>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001467 }
1468 $rs .= '</struct>';
Andrey Andreevc8709832012-04-04 13:43:53 +03001469 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001470 case 2:
1471 // array
1472 $rs .= "<array>\n<data>\n";
Andrey Andreevc8709832012-04-04 13:43:53 +03001473 for ($i = 0, $c = count($val); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001474 {
1475 $rs .= $this->serializeval($val[$i]);
1476 }
Andrey Andreeva30faf92011-12-25 18:15:34 +02001477 $rs .= "</data>\n</array>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001478 break;
1479 case 1:
1480 // others
1481 switch ($typ)
1482 {
1483 case $this->xmlrpcBase64:
Andrey Andreevc8709832012-04-04 13:43:53 +03001484 $rs .= '<'.$typ.'>'.base64_encode( (string) $val).'</'.$typ.">\n";
1485 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001486 case $this->xmlrpcBoolean:
Andrey Andreevc8709832012-04-04 13:43:53 +03001487 $rs .= '<'.$typ.'>'.( (bool) $val ? '1' : '0').'</'.$typ.">\n";
1488 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001489 case $this->xmlrpcString:
Andrey Andreevc8709832012-04-04 13:43:53 +03001490 $rs .= '<'.$typ.'>'.htmlspecialchars( (string) $val).'</'.$typ.">\n";
1491 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001492 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001493 $rs .= '<'.$typ.'>'.$val.'</'.$typ.">\n";
1494 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001495 }
1496 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001497 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001498 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001499
Derek Allard2067d1a2008-11-13 22:59:24 +00001500 return $rs;
1501 }
1502
Andrey Andreevc8709832012-04-04 13:43:53 +03001503 // --------------------------------------------------------------------
1504
1505 /**
1506 * Serialize class
1507 *
1508 * @return string
1509 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001510 public function serialize_class()
Derek Allard2067d1a2008-11-13 22:59:24 +00001511 {
1512 return $this->serializeval($this);
1513 }
1514
Andrey Andreevc8709832012-04-04 13:43:53 +03001515 // --------------------------------------------------------------------
1516
1517 /**
1518 * Serialize value
1519 *
1520 * @param object
1521 * @return string
1522 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001523 public function serializeval($o)
Derek Allard2067d1a2008-11-13 22:59:24 +00001524 {
1525 $ar = $o->me;
1526 reset($ar);
Barry Mienydd671972010-10-04 16:33:58 +02001527
Derek Allard2067d1a2008-11-13 22:59:24 +00001528 list($typ, $val) = each($ar);
Andrey Andreeva30faf92011-12-25 18:15:34 +02001529 return "<value>\n".$this->serializedata($typ, $val)."</value>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001530 }
Barry Mienydd671972010-10-04 16:33:58 +02001531
Andrey Andreevc8709832012-04-04 13:43:53 +03001532 // --------------------------------------------------------------------
1533
1534 /**
1535 * Scalar value
1536 *
1537 * @return mixed
1538 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001539 public function scalarval()
Derek Allard2067d1a2008-11-13 22:59:24 +00001540 {
1541 reset($this->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001542 return current($this->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001543 }
1544
Andrey Andreevc8709832012-04-04 13:43:53 +03001545 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001546
Andrey Andreevc8709832012-04-04 13:43:53 +03001547 /**
1548 * Encode time in ISO-8601 form.
1549 * Useful for sending time in XML-RPC
1550 *
1551 * @param int unix timestamp
1552 * @param bool
1553 * @return string
1554 */
1555 public function iso8601_encode($time, $utc = FALSE)
Barry Mienydd671972010-10-04 16:33:58 +02001556 {
Andrey Andreev62090152011-12-30 12:49:27 +02001557 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 +00001558 }
Barry Mienydd671972010-10-04 16:33:58 +02001559
Andrey Andreevc8709832012-04-04 13:43:53 +03001560} // END XML_RPC_Values Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001561
1562/* End of file Xmlrpc.php */
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001563/* Location: ./system/libraries/Xmlrpc.php */