blob: cbb91c40ae3417cb595df68f11d91c0078af327e [file] [log] [blame]
Andrey Andreeva30faf92011-12-25 18:15:34 +02001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
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 */
27
Derek Allard2067d1a2008-11-13 22:59:24 +000028/**
29 * XML-RPC request handler class
30 *
31 * @package CodeIgniter
32 * @subpackage Libraries
33 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -050034 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000035 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
36 */
Andrey Andreevc8709832012-04-04 13:43:53 +030037
38if ( ! function_exists('xml_parser_create'))
39{
40 show_error('Your PHP installation does not support XML');
41}
42
43// ------------------------------------------------------------------------
44
Derek Allard2067d1a2008-11-13 22:59:24 +000045class CI_Xmlrpc {
46
Andrey Andreeva30faf92011-12-25 18:15:34 +020047 public $debug = FALSE; // Debugging on or off
48 public $xmlrpcI4 = 'i4';
49 public $xmlrpcInt = 'int';
50 public $xmlrpcBoolean = 'boolean';
51 public $xmlrpcDouble = 'double';
52 public $xmlrpcString = 'string';
53 public $xmlrpcDateTime = 'dateTime.iso8601';
54 public $xmlrpcBase64 = 'base64';
55 public $xmlrpcArray = 'array';
56 public $xmlrpcStruct = 'struct';
Barry Mienydd671972010-10-04 16:33:58 +020057
Andrey Andreeva30faf92011-12-25 18:15:34 +020058 public $xmlrpcTypes = array();
59 public $valid_parents = array();
60 public $xmlrpcerr = array(); // Response numbers
61 public $xmlrpcstr = array(); // Response strings
Barry Mienydd671972010-10-04 16:33:58 +020062
Andrey Andreeva30faf92011-12-25 18:15:34 +020063 public $xmlrpc_defencoding = 'UTF-8';
64 public $xmlrpcName = 'XML-RPC for CodeIgniter';
65 public $xmlrpcVersion = '1.1';
66 public $xmlrpcerruser = 800; // Start of user errors
67 public $xmlrpcerrxml = 100; // Start of XML Parse errors
68 public $xmlrpc_backslash = ''; // formulate backslashes for escaping regexp
Barry Mienydd671972010-10-04 16:33:58 +020069
Andrey Andreeva30faf92011-12-25 18:15:34 +020070 public $client;
71 public $method;
72 public $data;
73 public $message = '';
74 public $error = ''; // Error string for request
75 public $result;
76 public $response = array(); // Response from remote server
Derek Allard2067d1a2008-11-13 22:59:24 +000077
Andrey Andreeva30faf92011-12-25 18:15:34 +020078 public $xss_clean = TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +000079
Derek Allard2067d1a2008-11-13 22:59:24 +000080
Andrey Andreevc8709832012-04-04 13:43:53 +030081 /**
82 * Constructor
83 *
84 * Initializes property default values
85 *
86 * @param array
87 * @return void
88 */
Greg Akera9263282010-11-10 15:26:43 -060089 public function __construct($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +000090 {
Derek Allard2067d1a2008-11-13 22:59:24 +000091 $this->xmlrpc_backslash = chr(92).chr(92);
Barry Mienydd671972010-10-04 16:33:58 +020092
Derek Allard2067d1a2008-11-13 22:59:24 +000093 // Types for info sent back and forth
94 $this->xmlrpcTypes = array(
Barry Mienydd671972010-10-04 16:33:58 +020095 $this->xmlrpcI4 => '1',
96 $this->xmlrpcInt => '1',
97 $this->xmlrpcBoolean => '1',
98 $this->xmlrpcString => '1',
99 $this->xmlrpcDouble => '1',
100 $this->xmlrpcDateTime => '1',
101 $this->xmlrpcBase64 => '1',
102 $this->xmlrpcArray => '2',
103 $this->xmlrpcStruct => '3'
Derek Allard2067d1a2008-11-13 22:59:24 +0000104 );
Barry Mienydd671972010-10-04 16:33:58 +0200105
Derek Allard2067d1a2008-11-13 22:59:24 +0000106 // Array of Valid Parents for Various XML-RPC elements
Timothy Warren0688ac92012-04-20 10:25:04 -0400107 $this->valid_parents = array('BOOLEAN' => array('VALUE'),
108 'I4' => array('VALUE'),
109 'INT' => array('VALUE'),
110 'STRING' => array('VALUE'),
111 'DOUBLE' => array('VALUE'),
112 'DATETIME.ISO8601' => array('VALUE'),
113 'BASE64' => array('VALUE'),
114 'ARRAY' => array('VALUE'),
115 'STRUCT' => array('VALUE'),
116 'PARAM' => array('PARAMS'),
117 'METHODNAME' => array('METHODCALL'),
118 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'),
119 'MEMBER' => array('STRUCT'),
120 'NAME' => array('MEMBER'),
121 'DATA' => array('ARRAY'),
122 'FAULT' => array('METHODRESPONSE'),
123 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT')
124 );
Barry Mienydd671972010-10-04 16:33:58 +0200125
126
Derek Allard2067d1a2008-11-13 22:59:24 +0000127 // XML-RPC Responses
128 $this->xmlrpcerr['unknown_method'] = '1';
129 $this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server';
130 $this->xmlrpcerr['invalid_return'] = '2';
Derek Jones37f4b9c2011-07-01 17:56:50 -0500131 $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 +0000132 $this->xmlrpcerr['incorrect_params'] = '3';
133 $this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method';
134 $this->xmlrpcerr['introspect_unknown'] = '4';
Andrey Andreeva30faf92011-12-25 18:15:34 +0200135 $this->xmlrpcstr['introspect_unknown'] = 'Cannot inspect signature for request: method unknown';
Derek Allard2067d1a2008-11-13 22:59:24 +0000136 $this->xmlrpcerr['http_error'] = '5';
137 $this->xmlrpcstr['http_error'] = "Did not receive a '200 OK' response from remote server.";
138 $this->xmlrpcerr['no_data'] = '6';
139 $this->xmlrpcstr['no_data'] ='No data received from server.';
Barry Mienydd671972010-10-04 16:33:58 +0200140
Derek Allard2067d1a2008-11-13 22:59:24 +0000141 $this->initialize($config);
Barry Mienydd671972010-10-04 16:33:58 +0200142
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300143 log_message('debug', 'XML-RPC Class Initialized');
Derek Allard2067d1a2008-11-13 22:59:24 +0000144 }
Barry Mienydd671972010-10-04 16:33:58 +0200145
Andrey Andreevc8709832012-04-04 13:43:53 +0300146 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000147
Andrey Andreevc8709832012-04-04 13:43:53 +0300148 /**
149 * Initialize
150 *
151 * @param array
152 * @return void
153 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200154 public function initialize($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000155 {
Derek Jones33559102009-02-02 18:50:38 +0000156 if (count($config) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000157 {
158 foreach ($config as $key => $val)
159 {
160 if (isset($this->$key))
161 {
Barry Mienydd671972010-10-04 16:33:58 +0200162 $this->$key = $val;
Derek Allard2067d1a2008-11-13 22:59:24 +0000163 }
164 }
165 }
166 }
Barry Mienydd671972010-10-04 16:33:58 +0200167
Andrey Andreevc8709832012-04-04 13:43:53 +0300168 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000169
Andrey Andreevc8709832012-04-04 13:43:53 +0300170 /**
171 * Parse server URL
172 *
173 * @param string url
174 * @param int port
175 * @return void
176 */
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300177 public function server($url, $port = 80, $proxy = FALSE, $proxy_port = 8080)
Derek Allard2067d1a2008-11-13 22:59:24 +0000178 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200179 if (strpos($url, 'http') !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000180 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300181 $url = 'http://'.$url;
Derek Allard2067d1a2008-11-13 22:59:24 +0000182 }
Barry Mienydd671972010-10-04 16:33:58 +0200183
Derek Allard2067d1a2008-11-13 22:59:24 +0000184 $parts = parse_url($url);
Barry Mienydd671972010-10-04 16:33:58 +0200185
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300186 $path = isset($parts['path']) ? $parts['path'] : '/';
Barry Mienydd671972010-10-04 16:33:58 +0200187
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300188 if ( ! empty($parts['query']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000189 {
190 $path .= '?'.$parts['query'];
Barry Mienydd671972010-10-04 16:33:58 +0200191 }
192
Valio9dee5352012-07-02 10:42:28 +0300193 $this->client = new XML_RPC_Client($path, $parts['host'], $port, $proxy, $proxy_port);
Derek Allard2067d1a2008-11-13 22:59:24 +0000194 }
Barry Mienydd671972010-10-04 16:33:58 +0200195
Andrey Andreevc8709832012-04-04 13:43:53 +0300196 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000197
Andrey Andreevc8709832012-04-04 13:43:53 +0300198 /**
199 * Set Timeout
200 *
201 * @param int seconds
202 * @return void
203 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200204 public function timeout($seconds = 5)
Derek Allard2067d1a2008-11-13 22:59:24 +0000205 {
206 if ( ! is_null($this->client) && is_int($seconds))
207 {
208 $this->client->timeout = $seconds;
209 }
210 }
Barry Mienydd671972010-10-04 16:33:58 +0200211
Andrey Andreevc8709832012-04-04 13:43:53 +0300212 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000213
Andrey Andreevc8709832012-04-04 13:43:53 +0300214 /**
215 * Set Methods
216 *
217 * @param string method name
218 * @return void
219 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200220 public function method($function)
Derek Allard2067d1a2008-11-13 22:59:24 +0000221 {
222 $this->method = $function;
223 }
Barry Mienydd671972010-10-04 16:33:58 +0200224
Andrey Andreevc8709832012-04-04 13:43:53 +0300225 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000226
Andrey Andreevc8709832012-04-04 13:43:53 +0300227 /**
228 * Take Array of Data and Create Objects
229 *
230 * @param array
231 * @return void
232 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200233 public function request($incoming)
Derek Allard2067d1a2008-11-13 22:59:24 +0000234 {
235 if ( ! is_array($incoming))
236 {
237 // Send Error
Andrey Andreevc8709832012-04-04 13:43:53 +0300238 return;
Derek Allard2067d1a2008-11-13 22:59:24 +0000239 }
Barry Mienydd671972010-10-04 16:33:58 +0200240
Derek Allard2067d1a2008-11-13 22:59:24 +0000241 $this->data = array();
Barry Mienydd671972010-10-04 16:33:58 +0200242
Pascal Kriete14287f32011-02-14 13:39:34 -0500243 foreach ($incoming as $key => $value)
Derek Allard2067d1a2008-11-13 22:59:24 +0000244 {
245 $this->data[$key] = $this->values_parsing($value);
246 }
247 }
Barry Mienydd671972010-10-04 16:33:58 +0200248
Andrey Andreevc8709832012-04-04 13:43:53 +0300249 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200250
Andrey Andreevc8709832012-04-04 13:43:53 +0300251 /**
252 * Set Debug
253 *
254 * @param bool
255 * @return void
256 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200257 public function set_debug($flag = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000258 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100259 $this->debug = ($flag === TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000260 }
Barry Mienydd671972010-10-04 16:33:58 +0200261
Andrey Andreevc8709832012-04-04 13:43:53 +0300262 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000263
Andrey Andreevc8709832012-04-04 13:43:53 +0300264 /**
265 * Values Parsing
266 *
267 * @param mixed
268 * @return object
269 */
270 public function values_parsing($value)
Derek Allard2067d1a2008-11-13 22:59:24 +0000271 {
Derek Jones8c4b5e72010-01-06 22:21:41 +0000272 if (is_array($value) && array_key_exists(0, $value))
Derek Allard2067d1a2008-11-13 22:59:24 +0000273 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300274 if ( ! isset($value[1], $this->xmlrpcTypes[$value[1]]))
Derek Allard2067d1a2008-11-13 22:59:24 +0000275 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200276 $temp = new XML_RPC_Values($value[0], (is_array($value[0]) ? 'array' : 'string'));
Derek Allard2067d1a2008-11-13 22:59:24 +0000277 }
278 else
279 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100280 if (is_array($value[0]) && ($value[1] === 'struct' OR $value[1] === 'array'))
Andrey Andreeva30faf92011-12-25 18:15:34 +0200281 {
282 while (list($k) = each($value[0]))
283 {
284 $value[0][$k] = $this->values_parsing($value[0][$k], TRUE);
285 }
286 }
287
288 $temp = new XML_RPC_Values($value[0], $value[1]);
Derek Allard2067d1a2008-11-13 22:59:24 +0000289 }
290 }
291 else
292 {
293 $temp = new XML_RPC_Values($value, 'string');
294 }
295
296 return $temp;
297 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000298
Andrey Andreevc8709832012-04-04 13:43:53 +0300299 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000300
Andrey Andreevc8709832012-04-04 13:43:53 +0300301 /**
302 * Sends XML-RPC Request
303 *
304 * @return bool
305 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200306 public function send_request()
Derek Allard2067d1a2008-11-13 22:59:24 +0000307 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300308 $this->message = new XML_RPC_Message($this->method, $this->data);
Derek Allard2067d1a2008-11-13 22:59:24 +0000309 $this->message->debug = $this->debug;
Barry Mienydd671972010-10-04 16:33:58 +0200310
Andrey Andreeva30faf92011-12-25 18:15:34 +0200311 if ( ! $this->result = $this->client->send($this->message) OR ! is_object($this->result->val))
Derek Allard2067d1a2008-11-13 22:59:24 +0000312 {
313 $this->error = $this->result->errstr;
314 return FALSE;
315 }
Barry Mienydd671972010-10-04 16:33:58 +0200316
Derek Allard2067d1a2008-11-13 22:59:24 +0000317 $this->response = $this->result->decode();
Derek Allard2067d1a2008-11-13 22:59:24 +0000318 return TRUE;
319 }
Barry Mienydd671972010-10-04 16:33:58 +0200320
Andrey Andreevc8709832012-04-04 13:43:53 +0300321 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000322
Andrey Andreevc8709832012-04-04 13:43:53 +0300323 /**
324 * Returns Error
325 *
326 * @return string
327 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200328 public function display_error()
Derek Allard2067d1a2008-11-13 22:59:24 +0000329 {
330 return $this->error;
331 }
Barry Mienydd671972010-10-04 16:33:58 +0200332
Andrey Andreevc8709832012-04-04 13:43:53 +0300333 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000334
Andrey Andreevc8709832012-04-04 13:43:53 +0300335 /**
336 * Returns Remote Server Response
337 *
338 * @return string
339 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200340 public function display_response()
Derek Allard2067d1a2008-11-13 22:59:24 +0000341 {
342 return $this->response;
343 }
Barry Mienydd671972010-10-04 16:33:58 +0200344
Andrey Andreevc8709832012-04-04 13:43:53 +0300345 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200346
Andrey Andreevc8709832012-04-04 13:43:53 +0300347 /**
348 * Sends an Error Message for Server Request
349 *
350 * @param int
351 * @param string
352 * @return object
353 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200354 public function send_error_message($number, $message)
Derek Allard2067d1a2008-11-13 22:59:24 +0000355 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200356 return new XML_RPC_Response(0, $number, $message);
Derek Allard2067d1a2008-11-13 22:59:24 +0000357 }
Barry Mienydd671972010-10-04 16:33:58 +0200358
Andrey Andreevc8709832012-04-04 13:43:53 +0300359 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200360
Andrey Andreevc8709832012-04-04 13:43:53 +0300361 /**
362 * Send Response for Server Request
363 *
364 * @param array
365 * @return object
366 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200367 public function send_response($response)
Derek Allard2067d1a2008-11-13 22:59:24 +0000368 {
369 // $response should be array of values, which will be parsed
370 // based on their data and type into a valid group of XML-RPC values
Andrey Andreeva30faf92011-12-25 18:15:34 +0200371 return new XML_RPC_Response($this->values_parsing($response));
Derek Allard2067d1a2008-11-13 22:59:24 +0000372 }
Barry Mienydd671972010-10-04 16:33:58 +0200373
Derek Allard2067d1a2008-11-13 22:59:24 +0000374} // END XML_RPC Class
375
Derek Allard2067d1a2008-11-13 22:59:24 +0000376/**
377 * XML-RPC Client class
378 *
379 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500380 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000381 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
382 */
383class XML_RPC_Client extends CI_Xmlrpc
384{
Andrey Andreeva30faf92011-12-25 18:15:34 +0200385 public $path = '';
386 public $server = '';
387 public $port = 80;
Valio9dee5352012-07-02 10:42:28 +0300388 public $proxy = FALSE;
389 public $proxy_port = 8080;
Andrey Andreeva30faf92011-12-25 18:15:34 +0200390 public $errno = '';
391 public $errstring = '';
392 public $timeout = 5;
393 public $no_multicall = FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000394
Andrey Andreevc8709832012-04-04 13:43:53 +0300395 /**
396 * Constructor
397 *
398 * @param string
399 * @param object
400 * @param int
401 * @return void
402 */
Valio9dee5352012-07-02 10:42:28 +0300403 public function __construct($path, $server, $port = 80, $proxy = FALSE, $proxy_port = 8080)
Derek Allard2067d1a2008-11-13 22:59:24 +0000404 {
Greg Akera9263282010-11-10 15:26:43 -0600405 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +0200406
Derek Allard2067d1a2008-11-13 22:59:24 +0000407 $this->port = $port;
408 $this->server = $server;
409 $this->path = $path;
Valio9dee5352012-07-02 10:42:28 +0300410 $this->proxy = $proxy;
411 $this->proxy_port = $proxy_port;
Derek Allard2067d1a2008-11-13 22:59:24 +0000412 }
Barry Mienydd671972010-10-04 16:33:58 +0200413
Andrey Andreevc8709832012-04-04 13:43:53 +0300414 // --------------------------------------------------------------------
415
416 /**
417 * Send message
418 *
419 * @param mixed
420 * @return object
421 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200422 public function send($msg)
Derek Allard2067d1a2008-11-13 22:59:24 +0000423 {
424 if (is_array($msg))
425 {
426 // Multi-call disabled
Andrey Andreevc8709832012-04-04 13:43:53 +0300427 return new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'], $this->xmlrpcstr['multicall_recursion']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000428 }
429
430 return $this->sendPayload($msg);
431 }
432
Andrey Andreevc8709832012-04-04 13:43:53 +0300433 // --------------------------------------------------------------------
434
435 /**
436 * Send payload
437 *
438 * @param object
439 * @return object
440 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200441 public function sendPayload($msg)
Barry Mienydd671972010-10-04 16:33:58 +0200442 {
Andrey Andreevc02e7c52012-07-02 16:43:43 +0300443 if ($this->proxy === FALSE)
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300444 {
445 $server = $this->server;
446 $port = $this->port;
Valentin Sheyretski09217ce2012-07-02 16:27:01 +0300447 }
448 else
449 {
Valio9dee5352012-07-02 10:42:28 +0300450 $server = $this->proxy;
451 $port = $this->proxy_port;
452 }
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300453
Valio9dee5352012-07-02 10:42:28 +0300454 $fp = @fsockopen($server, $port, $this->errno, $this->errstring, $this->timeout);
Barry Mienydd671972010-10-04 16:33:58 +0200455
Derek Allard2067d1a2008-11-13 22:59:24 +0000456 if ( ! is_resource($fp))
457 {
458 error_log($this->xmlrpcstr['http_error']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300459 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000460 }
Barry Mienydd671972010-10-04 16:33:58 +0200461
Pascal Kriete14287f32011-02-14 13:39:34 -0500462 if (empty($msg->payload))
Derek Allard2067d1a2008-11-13 22:59:24 +0000463 {
464 // $msg = XML_RPC_Messages
465 $msg->createPayload();
466 }
Barry Mienydd671972010-10-04 16:33:58 +0200467
Derek Allard2067d1a2008-11-13 22:59:24 +0000468 $r = "\r\n";
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300469 $op = 'POST '.$this->path.' HTTP/1.0'.$r
470 .'Host: '.$this->server.$r
471 .'Content-Type: text/xml'.$r
472 .'User-Agent: '.$this->xmlrpcName.$r
473 .'Content-Length: '.strlen($msg->payload).$r.$r
474 .$msg->payload;
Barry Mienydd671972010-10-04 16:33:58 +0200475
George Petsagourakis306b3782012-05-02 20:31:08 +0300476 if ( ! fwrite($fp, $op, strlen($op)))
Derek Allard2067d1a2008-11-13 22:59:24 +0000477 {
478 error_log($this->xmlrpcstr['http_error']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300479 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000480 }
Andrey Andreevc8709832012-04-04 13:43:53 +0300481
Derek Allard2067d1a2008-11-13 22:59:24 +0000482 $resp = $msg->parseResponse($fp);
483 fclose($fp);
484 return $resp;
485 }
486
Andrey Andreevc8709832012-04-04 13:43:53 +0300487} // END XML_RPC_Client Class
Derek Allard2067d1a2008-11-13 22:59:24 +0000488
489/**
490 * XML-RPC Response class
491 *
492 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500493 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000494 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
495 */
496class XML_RPC_Response
497{
Andrey Andreevc8709832012-04-04 13:43:53 +0300498 public $val = 0;
499 public $errno = 0;
500 public $errstr = '';
501 public $headers = array();
502 public $xss_clean = TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000503
Andrey Andreevc8709832012-04-04 13:43:53 +0300504 /**
505 * Constructor
506 *
507 * @param mixed
508 * @param int
509 * @param string
510 * @return void
511 */
Greg Akera9263282010-11-10 15:26:43 -0600512 public function __construct($val, $code = 0, $fstr = '')
Barry Mienydd671972010-10-04 16:33:58 +0200513 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100514 if ($code !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000515 {
516 // error
517 $this->errno = $code;
Andrey Andreevc8709832012-04-04 13:43:53 +0300518 $this->errstr = htmlspecialchars($fstr,
519 (is_php('5.4') ? ENT_XML1 | ENT_NOQUOTES : ENT_NOQUOTES),
520 'UTF-8');
Derek Allard2067d1a2008-11-13 22:59:24 +0000521 }
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300522 elseif ( ! is_object($val))
Derek Allard2067d1a2008-11-13 22:59:24 +0000523 {
524 // programmer error, not an object
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300525 error_log("Invalid type '".gettype($val)."' (value: ".$val.') passed to XML_RPC_Response. Defaulting to empty value.');
Derek Allard2067d1a2008-11-13 22:59:24 +0000526 $this->val = new XML_RPC_Values();
527 }
528 else
529 {
530 $this->val = $val;
531 }
532 }
533
Andrey Andreevc8709832012-04-04 13:43:53 +0300534 // --------------------------------------------------------------------
535
536 /**
537 * Fault code
538 *
539 * @return int
540 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200541 public function faultCode()
Derek Allard2067d1a2008-11-13 22:59:24 +0000542 {
543 return $this->errno;
544 }
545
Andrey Andreevc8709832012-04-04 13:43:53 +0300546 // --------------------------------------------------------------------
547
548 /**
549 * Fault string
550 *
551 * @return string
552 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200553 public function faultString()
Derek Allard2067d1a2008-11-13 22:59:24 +0000554 {
555 return $this->errstr;
556 }
557
Andrey Andreevc8709832012-04-04 13:43:53 +0300558 // --------------------------------------------------------------------
559
560 /**
561 * Value
562 *
563 * @return mixed
564 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200565 public function value()
Derek Allard2067d1a2008-11-13 22:59:24 +0000566 {
567 return $this->val;
568 }
Barry Mienydd671972010-10-04 16:33:58 +0200569
Andrey Andreevc8709832012-04-04 13:43:53 +0300570 // --------------------------------------------------------------------
571
572 /**
573 * Prepare response
574 *
575 * @return string xml
576 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200577 public function prepare_response()
Derek Allard2067d1a2008-11-13 22:59:24 +0000578 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200579 return "<methodResponse>\n"
Andrey Andreevc8709832012-04-04 13:43:53 +0300580 .($this->errno
581 ? '<fault>
Derek Allard2067d1a2008-11-13 22:59:24 +0000582 <value>
583 <struct>
584 <member>
585 <name>faultCode</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300586 <value><int>'.$this->errno.'</int></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000587 </member>
588 <member>
589 <name>faultString</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300590 <value><string>'.$this->errstr.'</string></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000591 </member>
592 </struct>
593 </value>
Andrey Andreeva30faf92011-12-25 18:15:34 +0200594</fault>'
Andrey Andreevc8709832012-04-04 13:43:53 +0300595 : "<params>\n<param>\n".$this->val->serialize_class()."</param>\n</params>")
596 ."\n</methodResponse>";
Derek Allard2067d1a2008-11-13 22:59:24 +0000597 }
Barry Mienydd671972010-10-04 16:33:58 +0200598
Andrey Andreevc8709832012-04-04 13:43:53 +0300599 // --------------------------------------------------------------------
600
601 /**
602 * Decode
603 *
604 * @param mixed
605 * @return array
606 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200607 public function decode($array = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000608 {
609 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +0200610
611 if (is_array($array))
Derek Allard2067d1a2008-11-13 22:59:24 +0000612 {
613 while (list($key) = each($array))
614 {
615 if (is_array($array[$key]))
616 {
617 $array[$key] = $this->decode($array[$key]);
618 }
619 else
620 {
Robin Sowell66a3fc02010-03-18 09:44:55 -0400621 $array[$key] = ($this->xss_clean) ? $CI->security->xss_clean($array[$key]) : $array[$key];
Derek Allard2067d1a2008-11-13 22:59:24 +0000622 }
623 }
Barry Mienydd671972010-10-04 16:33:58 +0200624
Andrey Andreevc8709832012-04-04 13:43:53 +0300625 return $array;
626 }
627
628 $result = $this->xmlrpc_decoder($this->val);
629
630 if (is_array($result))
631 {
632 $result = $this->decode($result);
Derek Allard2067d1a2008-11-13 22:59:24 +0000633 }
634 else
635 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300636 $result = ($this->xss_clean) ? $CI->security->xss_clean($result) : $result;
Derek Allard2067d1a2008-11-13 22:59:24 +0000637 }
Barry Mienydd671972010-10-04 16:33:58 +0200638
Derek Allard2067d1a2008-11-13 22:59:24 +0000639 return $result;
640 }
641
Andrey Andreevc8709832012-04-04 13:43:53 +0300642 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000643
Andrey Andreevc8709832012-04-04 13:43:53 +0300644 /**
645 * XML-RPC Object to PHP Types
646 *
647 * @param object
648 * @return array
649 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200650 public function xmlrpc_decoder($xmlrpc_val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000651 {
652 $kind = $xmlrpc_val->kindOf();
653
Alex Bilbied261b1e2012-06-02 11:12:16 +0100654 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +0000655 {
656 return $xmlrpc_val->scalarval();
657 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100658 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +0000659 {
660 reset($xmlrpc_val->me);
Andrey Andreevadc11752011-12-30 14:46:08 +0200661 $b = current($xmlrpc_val->me);
Derek Allard2067d1a2008-11-13 22:59:24 +0000662 $arr = array();
663
Andrey Andreeva30faf92011-12-25 18:15:34 +0200664 for ($i = 0, $size = count($b); $i < $size; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000665 {
666 $arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);
667 }
668 return $arr;
669 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100670 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +0000671 {
672 reset($xmlrpc_val->me['struct']);
673 $arr = array();
674
Pascal Kriete14287f32011-02-14 13:39:34 -0500675 while (list($key,$value) = each($xmlrpc_val->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000676 {
677 $arr[$key] = $this->xmlrpc_decoder($value);
678 }
679 return $arr;
680 }
681 }
Barry Mienydd671972010-10-04 16:33:58 +0200682
Andrey Andreevc8709832012-04-04 13:43:53 +0300683 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000684
Andrey Andreevc8709832012-04-04 13:43:53 +0300685 /**
686 * ISO-8601 time to server or UTC time
687 *
688 * @param string
689 * @param bool
690 * @return int unix timestamp
691 */
692 public function iso8601_decode($time, $utc = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000693 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300694 // return a time in the localtime, or UTC
Derek Allard2067d1a2008-11-13 22:59:24 +0000695 $t = 0;
696 if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))
697 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100698 $fnc = ($utc === TRUE) ? 'gmmktime' : 'mktime';
Pascal Kriete14287f32011-02-14 13:39:34 -0500699 $t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
Derek Allard2067d1a2008-11-13 22:59:24 +0000700 }
701 return $t;
702 }
Barry Mienydd671972010-10-04 16:33:58 +0200703
Andrey Andreevc8709832012-04-04 13:43:53 +0300704} // END XML_RPC_Response Class
Derek Allard2067d1a2008-11-13 22:59:24 +0000705
706/**
707 * XML-RPC Message class
708 *
709 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500710 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000711 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
712 */
713class XML_RPC_Message extends CI_Xmlrpc
714{
Andrey Andreeva30faf92011-12-25 18:15:34 +0200715 public $payload;
716 public $method_name;
Andrey Andreevc8709832012-04-04 13:43:53 +0300717 public $params = array();
718 public $xh = array();
Derek Allard2067d1a2008-11-13 22:59:24 +0000719
Andrey Andreevc8709832012-04-04 13:43:53 +0300720 /**
721 * Constructor
722 *
723 * @param string method name
724 * @param array
725 * @return void
726 */
727 public function __construct($method, $pars = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000728 {
Greg Akera9263282010-11-10 15:26:43 -0600729 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +0200730
Derek Allard2067d1a2008-11-13 22:59:24 +0000731 $this->method_name = $method;
Derek Jones33559102009-02-02 18:50:38 +0000732 if (is_array($pars) && count($pars) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000733 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200734 for ($i = 0, $c = count($pars); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000735 {
736 // $pars[$i] = XML_RPC_Values
737 $this->params[] = $pars[$i];
738 }
739 }
740 }
Barry Mienydd671972010-10-04 16:33:58 +0200741
Andrey Andreevc8709832012-04-04 13:43:53 +0300742 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200743
Andrey Andreevc8709832012-04-04 13:43:53 +0300744 /**
745 * Create Payload to Send
746 *
747 * @return void
748 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200749 public function createPayload()
Derek Allard2067d1a2008-11-13 22:59:24 +0000750 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300751 $this->payload = '<?xml version="1.0"?'.">\r\n<methodCall>\r\n"
752 .'<methodName>'.$this->method_name."</methodName>\r\n"
753 ."<params>\r\n";
Barry Mienydd671972010-10-04 16:33:58 +0200754
Andrey Andreeva30faf92011-12-25 18:15:34 +0200755 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000756 {
757 // $p = XML_RPC_Values
758 $p = $this->params[$i];
759 $this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n";
760 }
Barry Mienydd671972010-10-04 16:33:58 +0200761
Derek Allard2067d1a2008-11-13 22:59:24 +0000762 $this->payload .= "</params>\r\n</methodCall>\r\n";
763 }
Barry Mienydd671972010-10-04 16:33:58 +0200764
Andrey Andreevc8709832012-04-04 13:43:53 +0300765 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200766
Andrey Andreevc8709832012-04-04 13:43:53 +0300767 /**
768 * Parse External XML-RPC Server's Response
769 *
770 * @param resource
771 * @return object
772 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200773 public function parseResponse($fp)
Derek Allard2067d1a2008-11-13 22:59:24 +0000774 {
775 $data = '';
Barry Mienydd671972010-10-04 16:33:58 +0200776
Pascal Kriete14287f32011-02-14 13:39:34 -0500777 while ($datum = fread($fp, 4096))
Derek Allard2067d1a2008-11-13 22:59:24 +0000778 {
779 $data .= $datum;
780 }
Barry Mienydd671972010-10-04 16:33:58 +0200781
Andrey Andreevc8709832012-04-04 13:43:53 +0300782 // Display HTTP content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +0000783 if ($this->debug === TRUE)
784 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200785 echo "<pre>---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n</pre>";
Derek Allard2067d1a2008-11-13 22:59:24 +0000786 }
Barry Mienydd671972010-10-04 16:33:58 +0200787
Andrey Andreevc8709832012-04-04 13:43:53 +0300788 // Check for data
Andrey Andreeva30faf92011-12-25 18:15:34 +0200789 if ($data === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000790 {
791 error_log($this->xmlrpcstr['no_data']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300792 return new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000793 }
Barry Mienydd671972010-10-04 16:33:58 +0200794
Andrey Andreevc8709832012-04-04 13:43:53 +0300795 // Check for HTTP 200 Response
Andrey Andreev3dad2e72012-06-14 15:10:56 +0300796 if (strpos($data, 'HTTP') === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
Derek Allard2067d1a2008-11-13 22:59:24 +0000797 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300798 $errstr = substr($data, 0, strpos($data, "\n")-1);
799 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');
Derek Allard2067d1a2008-11-13 22:59:24 +0000800 }
Barry Mienydd671972010-10-04 16:33:58 +0200801
Derek Allard2067d1a2008-11-13 22:59:24 +0000802 //-------------------------------------
Derek Jones37f4b9c2011-07-01 17:56:50 -0500803 // Create and Set Up XML Parser
Derek Allard2067d1a2008-11-13 22:59:24 +0000804 //-------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200805
Derek Allard2067d1a2008-11-13 22:59:24 +0000806 $parser = xml_parser_create($this->xmlrpc_defencoding);
807
Andrey Andreeva30faf92011-12-25 18:15:34 +0200808 $this->xh[$parser] = array(
Andrey Andreevc8709832012-04-04 13:43:53 +0300809 'isf' => 0,
810 'ac' => '',
811 'headers' => array(),
812 'stack' => array(),
813 'valuestack' => array(),
814 'isf_reason' => 0
Andrey Andreeva30faf92011-12-25 18:15:34 +0200815 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000816
817 xml_set_object($parser, $this);
Andrey Andreevc8709832012-04-04 13:43:53 +0300818 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000819 xml_set_element_handler($parser, 'open_tag', 'closing_tag');
820 xml_set_character_data_handler($parser, 'character_data');
821 //xml_set_default_handler($parser, 'default_handler');
822
Andrey Andreevc8709832012-04-04 13:43:53 +0300823 // Get headers
Derek Allard2067d1a2008-11-13 22:59:24 +0000824 $lines = explode("\r\n", $data);
825 while (($line = array_shift($lines)))
826 {
827 if (strlen($line) < 1)
828 {
829 break;
830 }
831 $this->xh[$parser]['headers'][] = $line;
832 }
833 $data = implode("\r\n", $lines);
Barry Mienydd671972010-10-04 16:33:58 +0200834
Andrey Andreevc8709832012-04-04 13:43:53 +0300835 // Parse XML data
Derek Jones33559102009-02-02 18:50:38 +0000836 if ( ! xml_parse($parser, $data, count($data)))
Derek Allard2067d1a2008-11-13 22:59:24 +0000837 {
838 $errstr = sprintf('XML error: %s at line %d',
Andrey Andreevc8709832012-04-04 13:43:53 +0300839 xml_error_string(xml_get_error_code($parser)),
840 xml_get_current_line_number($parser));
Derek Allard2067d1a2008-11-13 22:59:24 +0000841 //error_log($errstr);
842 $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
843 xml_parser_free($parser);
844 return $r;
845 }
846 xml_parser_free($parser);
Barry Mienydd671972010-10-04 16:33:58 +0200847
Andrey Andreevc8709832012-04-04 13:43:53 +0300848 // Got ourselves some badness, it seems
Derek Allard2067d1a2008-11-13 22:59:24 +0000849 if ($this->xh[$parser]['isf'] > 1)
850 {
851 if ($this->debug === TRUE)
852 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200853 echo "---Invalid Return---\n".$this->xh[$parser]['isf_reason']."---Invalid Return---\n\n";
Derek Allard2067d1a2008-11-13 22:59:24 +0000854 }
Barry Mienydd671972010-10-04 16:33:58 +0200855
Andrey Andreevc8709832012-04-04 13:43:53 +0300856 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 +0000857 }
858 elseif ( ! is_object($this->xh[$parser]['value']))
859 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300860 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 +0000861 }
Barry Mienydd671972010-10-04 16:33:58 +0200862
Andrey Andreevc8709832012-04-04 13:43:53 +0300863 // Display XML content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +0000864 if ($this->debug === TRUE)
865 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300866 echo '<pre>';
Barry Mienydd671972010-10-04 16:33:58 +0200867
Derek Allard2067d1a2008-11-13 22:59:24 +0000868 if (count($this->xh[$parser]['headers'] > 0))
869 {
870 echo "---HEADERS---\n";
871 foreach ($this->xh[$parser]['headers'] as $header)
872 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300873 echo $header."\n";
Derek Allard2067d1a2008-11-13 22:59:24 +0000874 }
875 echo "---END HEADERS---\n\n";
876 }
Barry Mienydd671972010-10-04 16:33:58 +0200877
Andrey Andreeva30faf92011-12-25 18:15:34 +0200878 echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n---PARSED---\n";
Derek Allard2067d1a2008-11-13 22:59:24 +0000879 var_dump($this->xh[$parser]['value']);
880 echo "\n---END PARSED---</pre>";
881 }
Barry Mienydd671972010-10-04 16:33:58 +0200882
Andrey Andreevc8709832012-04-04 13:43:53 +0300883 // Send response
Derek Allard2067d1a2008-11-13 22:59:24 +0000884 $v = $this->xh[$parser]['value'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000885 if ($this->xh[$parser]['isf'])
886 {
887 $errno_v = $v->me['struct']['faultCode'];
888 $errstr_v = $v->me['struct']['faultString'];
889 $errno = $errno_v->scalarval();
890
Alex Bilbied261b1e2012-06-02 11:12:16 +0100891 if ($errno === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000892 {
893 // FAULT returned, errno needs to reflect that
894 $errno = -1;
895 }
896
897 $r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
898 }
899 else
900 {
901 $r = new XML_RPC_Response($v);
902 }
903
904 $r->headers = $this->xh[$parser]['headers'];
905 return $r;
906 }
Barry Mienydd671972010-10-04 16:33:58 +0200907
Andrey Andreevc8709832012-04-04 13:43:53 +0300908 // --------------------------------------------------------------------
909
Derek Allard2067d1a2008-11-13 22:59:24 +0000910 // ------------------------------------
Derek Jones37f4b9c2011-07-01 17:56:50 -0500911 // Begin Return Message Parsing section
Derek Allard2067d1a2008-11-13 22:59:24 +0000912 // ------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200913
Derek Allard2067d1a2008-11-13 22:59:24 +0000914 // quick explanation of components:
Derek Jones37f4b9c2011-07-01 17:56:50 -0500915 // ac - used to accumulate values
916 // isf - used to indicate a fault
917 // lv - used to indicate "looking for a value": implements
Derek Allard2067d1a2008-11-13 22:59:24 +0000918 // the logic to allow values with no types to be strings
Derek Jones37f4b9c2011-07-01 17:56:50 -0500919 // params - used to store parameters in method calls
920 // method - used to store method name
Derek Allard2067d1a2008-11-13 22:59:24 +0000921 // stack - array with parent tree of the xml element,
922 // used to validate the nesting of elements
923
Andrey Andreevc8709832012-04-04 13:43:53 +0300924 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000925
Andrey Andreevc8709832012-04-04 13:43:53 +0300926 /**
927 * Start Element Handler
928 *
929 * @param string
930 * @param string
931 * @return void
932 */
933 public function open_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +0000934 {
935 // If invalid nesting, then return
936 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +0200937
Derek Allard2067d1a2008-11-13 22:59:24 +0000938 // Evaluate and check for correct nesting of XML elements
Alex Bilbied261b1e2012-06-02 11:12:16 +0100939 if (count($this->xh[$the_parser]['stack']) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000940 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100941 if ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')
Derek Allard2067d1a2008-11-13 22:59:24 +0000942 {
943 $this->xh[$the_parser]['isf'] = 2;
944 $this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
945 return;
946 }
947 }
Andrey Andreevc8709832012-04-04 13:43:53 +0300948 // not top level element: see if parent is OK
949 elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +0000950 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300951 $this->xh[$the_parser]['isf'] = 2;
952 $this->xh[$the_parser]['isf_reason'] = 'XML-RPC element $name cannot be child of '.$this->xh[$the_parser]['stack'][0];
953 return;
Derek Allard2067d1a2008-11-13 22:59:24 +0000954 }
Barry Mienydd671972010-10-04 16:33:58 +0200955
Andrey Andreevc8709832012-04-04 13:43:53 +0300956 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +0000957 {
958 case 'STRUCT':
959 case 'ARRAY':
960 // Creates array for child elements
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300961 $cur_val = array('value' => array(), 'type' => $name);
Derek Allard2067d1a2008-11-13 22:59:24 +0000962 array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
Andrey Andreevc8709832012-04-04 13:43:53 +0300963 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000964 case 'METHODNAME':
965 case 'NAME':
966 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +0300967 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000968 case 'FAULT':
969 $this->xh[$the_parser]['isf'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +0300970 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000971 case 'PARAM':
Pascal Kriete8761ef52011-02-14 13:13:52 -0500972 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +0300973 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000974 case 'VALUE':
975 $this->xh[$the_parser]['vt'] = 'value';
976 $this->xh[$the_parser]['ac'] = '';
977 $this->xh[$the_parser]['lv'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +0300978 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000979 case 'I4':
980 case 'INT':
981 case 'STRING':
982 case 'BOOLEAN':
983 case 'DOUBLE':
984 case 'DATETIME.ISO8601':
985 case 'BASE64':
Alex Bilbied261b1e2012-06-02 11:12:16 +0100986 if ($this->xh[$the_parser]['vt'] !== 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +0000987 {
988 //two data elements inside a value: an error occurred!
989 $this->xh[$the_parser]['isf'] = 2;
Andrey Andreevc8709832012-04-04 13:43:53 +0300990 $this->xh[$the_parser]['isf_reason'] = "'Twas a ".$name.' element following a '
991 .$this->xh[$the_parser]['vt'].' element inside a single value';
Derek Allard2067d1a2008-11-13 22:59:24 +0000992 return;
993 }
Barry Mienydd671972010-10-04 16:33:58 +0200994
Derek Allard2067d1a2008-11-13 22:59:24 +0000995 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +0300996 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000997 case 'MEMBER':
998 // Set name of <member> to nothing to prevent errors later if no <name> is found
999 $this->xh[$the_parser]['valuestack'][0]['name'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001000
Derek Allard2067d1a2008-11-13 22:59:24 +00001001 // Set NULL value to check to see if value passed for this param/member
Pascal Kriete8761ef52011-02-14 13:13:52 -05001002 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +03001003 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001004 case 'DATA':
1005 case 'METHODCALL':
1006 case 'METHODRESPONSE':
1007 case 'PARAMS':
1008 // valid elements that add little to processing
Andrey Andreevc8709832012-04-04 13:43:53 +03001009 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001010 default:
1011 /// An Invalid Element is Found, so we have trouble
1012 $this->xh[$the_parser]['isf'] = 2;
Andrey Andreevc8709832012-04-04 13:43:53 +03001013 $this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;
1014 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001015 }
Barry Mienydd671972010-10-04 16:33:58 +02001016
Derek Allard2067d1a2008-11-13 22:59:24 +00001017 // Add current element name to stack, to allow validation of nesting
1018 array_unshift($this->xh[$the_parser]['stack'], $name);
1019
Alex Bilbied261b1e2012-06-02 11:12:16 +01001020 $name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001021 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001022
Andrey Andreevc8709832012-04-04 13:43:53 +03001023 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001024
Andrey Andreevc8709832012-04-04 13:43:53 +03001025 /**
1026 * End Element Handler
1027 *
1028 * @param string
1029 * @param string
1030 * @return void
1031 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001032 public function closing_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001033 {
1034 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001035
Derek Allard2067d1a2008-11-13 22:59:24 +00001036 // Remove current element from stack and set variable
1037 // NOTE: If the XML validates, then we do not have to worry about
Andrey Andreevc8709832012-04-04 13:43:53 +03001038 // the opening and closing of elements. Nesting is checked on the opening
Derek Allard2067d1a2008-11-13 22:59:24 +00001039 // tag so we be safe there as well.
Barry Mienydd671972010-10-04 16:33:58 +02001040
Derek Allard2067d1a2008-11-13 22:59:24 +00001041 $curr_elem = array_shift($this->xh[$the_parser]['stack']);
Barry Mienydd671972010-10-04 16:33:58 +02001042
Andrey Andreevc8709832012-04-04 13:43:53 +03001043 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001044 {
1045 case 'STRUCT':
1046 case 'ARRAY':
1047 $cur_val = array_shift($this->xh[$the_parser]['valuestack']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001048 $this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();
Derek Allard2067d1a2008-11-13 22:59:24 +00001049 $this->xh[$the_parser]['vt'] = strtolower($name);
Andrey Andreevc8709832012-04-04 13:43:53 +03001050 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001051 case 'NAME':
1052 $this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
Andrey Andreevc8709832012-04-04 13:43:53 +03001053 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001054 case 'BOOLEAN':
1055 case 'I4':
1056 case 'INT':
1057 case 'STRING':
1058 case 'DOUBLE':
1059 case 'DATETIME.ISO8601':
1060 case 'BASE64':
1061 $this->xh[$the_parser]['vt'] = strtolower($name);
Barry Mienydd671972010-10-04 16:33:58 +02001062
Alex Bilbied261b1e2012-06-02 11:12:16 +01001063 if ($name === 'STRING')
Derek Allard2067d1a2008-11-13 22:59:24 +00001064 {
1065 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1066 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001067 elseif ($name === 'DATETIME.ISO8601')
Derek Allard2067d1a2008-11-13 22:59:24 +00001068 {
1069 $this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime;
1070 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1071 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001072 elseif ($name === 'BASE64')
Derek Allard2067d1a2008-11-13 22:59:24 +00001073 {
1074 $this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
1075 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001076 elseif ($name === 'BOOLEAN')
Derek Allard2067d1a2008-11-13 22:59:24 +00001077 {
1078 // Translated BOOLEAN values to TRUE AND FALSE
Andrey Andreevc8709832012-04-04 13:43:53 +03001079 $this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001080 }
1081 elseif ($name=='DOUBLE')
1082 {
1083 // we have a DOUBLE
1084 // we must check that only 0123456789-.<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001085 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])
1086 ? (float) $this->xh[$the_parser]['ac']
1087 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001088 }
1089 else
1090 {
1091 // we have an I4/INT
1092 // we must check that only 0123456789-<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001093 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])
George Petsagourakis306b3782012-05-02 20:31:08 +03001094 ? (int) $this->xh[$the_parser]['ac']
Andrey Andreevc8709832012-04-04 13:43:53 +03001095 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001096 }
1097 $this->xh[$the_parser]['ac'] = '';
1098 $this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
Andrey Andreevc8709832012-04-04 13:43:53 +03001099 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001100 case 'VALUE':
1101 // This if() detects if no scalar was inside <VALUE></VALUE>
1102 if ($this->xh[$the_parser]['vt']=='value')
1103 {
1104 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1105 $this->xh[$the_parser]['vt'] = $this->xmlrpcString;
1106 }
Barry Mienydd671972010-10-04 16:33:58 +02001107
Derek Allard2067d1a2008-11-13 22:59:24 +00001108 // build the XML-RPC value out of the data received, and substitute it
1109 $temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
Barry Mienydd671972010-10-04 16:33:58 +02001110
Alex Bilbied261b1e2012-06-02 11:12:16 +01001111 if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')
Derek Allard2067d1a2008-11-13 22:59:24 +00001112 {
1113 // Array
1114 $this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
1115 }
1116 else
1117 {
1118 // Struct
1119 $this->xh[$the_parser]['value'] = $temp;
1120 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001121 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001122 case 'MEMBER':
Andrey Andreevc8709832012-04-04 13:43:53 +03001123 $this->xh[$the_parser]['ac'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001124
Derek Allard2067d1a2008-11-13 22:59:24 +00001125 // If value add to array in the stack for the last element built
1126 if ($this->xh[$the_parser]['value'])
1127 {
1128 $this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
1129 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001130 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001131 case 'DATA':
Andrey Andreevc8709832012-04-04 13:43:53 +03001132 $this->xh[$the_parser]['ac'] = '';
1133 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001134 case 'PARAM':
1135 if ($this->xh[$the_parser]['value'])
1136 {
1137 $this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
1138 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001139 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001140 case 'METHODNAME':
1141 $this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001142 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001143 case 'PARAMS':
1144 case 'FAULT':
1145 case 'METHODCALL':
1146 case 'METHORESPONSE':
1147 // We're all good kids with nuthin' to do
Andrey Andreevc8709832012-04-04 13:43:53 +03001148 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001149 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001150 // End of an Invalid Element. Taken care of during the opening tag though
1151 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001152 }
1153 }
1154
Andrey Andreevc8709832012-04-04 13:43:53 +03001155 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001156
Andrey Andreevc8709832012-04-04 13:43:53 +03001157 /**
1158 * Parse character data
1159 *
1160 * @param string
1161 * @param string
1162 * @return void
1163 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001164 public function character_data($the_parser, $data)
Derek Allard2067d1a2008-11-13 22:59:24 +00001165 {
1166 if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
Barry Mienydd671972010-10-04 16:33:58 +02001167
Derek Allard2067d1a2008-11-13 22:59:24 +00001168 // If a value has not been found
Alex Bilbied261b1e2012-06-02 11:12:16 +01001169 if ($this->xh[$the_parser]['lv'] !== 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001170 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001171 if ($this->xh[$the_parser]['lv'] === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001172 {
1173 $this->xh[$the_parser]['lv'] = 2; // Found a value
1174 }
Barry Mienydd671972010-10-04 16:33:58 +02001175
Andrey Andreevc8709832012-04-04 13:43:53 +03001176 if ( ! isset($this->xh[$the_parser]['ac']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001177 {
1178 $this->xh[$the_parser]['ac'] = '';
1179 }
Barry Mienydd671972010-10-04 16:33:58 +02001180
Derek Allard2067d1a2008-11-13 22:59:24 +00001181 $this->xh[$the_parser]['ac'] .= $data;
1182 }
1183 }
Barry Mienydd671972010-10-04 16:33:58 +02001184
Andrey Andreevc8709832012-04-04 13:43:53 +03001185 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001186
Andrey Andreevc8709832012-04-04 13:43:53 +03001187 /**
1188 * Add parameter
1189 *
1190 * @param mixed
1191 * @return void
1192 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001193 public function addParam($par)
1194 {
1195 $this->params[] = $par;
1196 }
Barry Mienydd671972010-10-04 16:33:58 +02001197
Andrey Andreevc8709832012-04-04 13:43:53 +03001198 // --------------------------------------------------------------------
1199
1200 /**
1201 * Output parameters
1202 *
1203 * @param array
1204 * @return array
1205 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001206 public function output_parameters($array = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001207 {
Barry Mienydd671972010-10-04 16:33:58 +02001208 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +02001209
1210 if (is_array($array))
Derek Allard2067d1a2008-11-13 22:59:24 +00001211 {
1212 while (list($key) = each($array))
1213 {
1214 if (is_array($array[$key]))
1215 {
1216 $array[$key] = $this->output_parameters($array[$key]);
1217 }
1218 else
1219 {
Derek Jonesa9647e82010-03-02 22:59:07 -06001220 // 'bits' is for the MetaWeblog API image bits
1221 // @todo - this needs to be made more general purpose
Alex Bilbied261b1e2012-06-02 11:12:16 +01001222 $array[$key] = ($key === 'bits' OR $this->xss_clean === FALSE) ? $array[$key] : $CI->security->xss_clean($array[$key]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001223 }
1224 }
Barry Mienydd671972010-10-04 16:33:58 +02001225
Andrey Andreevc8709832012-04-04 13:43:53 +03001226 return $array;
Derek Allard2067d1a2008-11-13 22:59:24 +00001227 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001228
1229 $parameters = array();
1230
1231 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001232 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001233 $a_param = $this->decode_message($this->params[$i]);
Barry Mienydd671972010-10-04 16:33:58 +02001234
Andrey Andreevc8709832012-04-04 13:43:53 +03001235 if (is_array($a_param))
Derek Allard2067d1a2008-11-13 22:59:24 +00001236 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001237 $parameters[] = $this->output_parameters($a_param);
1238 }
1239 else
1240 {
1241 $parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;
Barry Mienydd671972010-10-04 16:33:58 +02001242 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001243 }
Barry Mienydd671972010-10-04 16:33:58 +02001244
Derek Allard2067d1a2008-11-13 22:59:24 +00001245 return $parameters;
1246 }
Barry Mienydd671972010-10-04 16:33:58 +02001247
Andrey Andreevc8709832012-04-04 13:43:53 +03001248 // --------------------------------------------------------------------
1249
1250 /**
1251 * Decode message
1252 *
1253 * @param object
1254 * @return mixed
1255 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001256 public function decode_message($param)
Derek Allard2067d1a2008-11-13 22:59:24 +00001257 {
1258 $kind = $param->kindOf();
1259
Alex Bilbied261b1e2012-06-02 11:12:16 +01001260 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +00001261 {
1262 return $param->scalarval();
1263 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001264 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +00001265 {
1266 reset($param->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001267 $b = current($param->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001268 $arr = array();
1269
Andrey Andreevc8709832012-04-04 13:43:53 +03001270 for ($i = 0, $c = count($b); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001271 {
1272 $arr[] = $this->decode_message($param->me['array'][$i]);
1273 }
Barry Mienydd671972010-10-04 16:33:58 +02001274
Derek Allard2067d1a2008-11-13 22:59:24 +00001275 return $arr;
1276 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001277 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +00001278 {
1279 reset($param->me['struct']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001280 $arr = array();
1281
Pascal Kriete14287f32011-02-14 13:39:34 -05001282 while (list($key,$value) = each($param->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001283 {
1284 $arr[$key] = $this->decode_message($value);
1285 }
Barry Mienydd671972010-10-04 16:33:58 +02001286
Derek Allard2067d1a2008-11-13 22:59:24 +00001287 return $arr;
1288 }
1289 }
Barry Mienydd671972010-10-04 16:33:58 +02001290
Andrey Andreevc8709832012-04-04 13:43:53 +03001291} // END XML_RPC_Message Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001292
1293/**
1294 * XML-RPC Values class
1295 *
1296 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -05001297 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +00001298 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
1299 */
1300class XML_RPC_Values extends CI_Xmlrpc
1301{
Andrey Andreeva30faf92011-12-25 18:15:34 +02001302 public $me = array();
1303 public $mytype = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001304
Andrey Andreevc8709832012-04-04 13:43:53 +03001305 /**
1306 * Constructor
1307 *
1308 * @param mixed
1309 * @param string
1310 * @return void
1311 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001312 public function __construct($val = -1, $type = '')
Barry Mienydd671972010-10-04 16:33:58 +02001313 {
Greg Akera9263282010-11-10 15:26:43 -06001314 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +02001315
Alex Bilbied261b1e2012-06-02 11:12:16 +01001316 if ($val !== -1 OR $type !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001317 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001318 $type = $type === '' ? 'string' : $type;
Barry Mienydd671972010-10-04 16:33:58 +02001319
Alex Bilbied261b1e2012-06-02 11:12:16 +01001320 if ($this->xmlrpcTypes[$type] === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001321 {
1322 $this->addScalar($val,$type);
1323 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001324 elseif ($this->xmlrpcTypes[$type] === 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001325 {
1326 $this->addArray($val);
1327 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001328 elseif ($this->xmlrpcTypes[$type] === 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001329 {
1330 $this->addStruct($val);
1331 }
1332 }
1333 }
1334
Andrey Andreevc8709832012-04-04 13:43:53 +03001335 // --------------------------------------------------------------------
1336
1337 /**
1338 * Add scalar value
1339 *
1340 * @param scalar
1341 * @param string
1342 * @return int
1343 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001344 public function addScalar($val, $type = 'string')
Derek Allard2067d1a2008-11-13 22:59:24 +00001345 {
1346 $typeof = $this->xmlrpcTypes[$type];
Barry Mienydd671972010-10-04 16:33:58 +02001347
Alex Bilbied261b1e2012-06-02 11:12:16 +01001348 if ($this->mytype === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001349 {
1350 echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
1351 return 0;
1352 }
Barry Mienydd671972010-10-04 16:33:58 +02001353
Alex Bilbied261b1e2012-06-02 11:12:16 +01001354 if ($typeof !== 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001355 {
1356 echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';
1357 return 0;
1358 }
1359
Alex Bilbied261b1e2012-06-02 11:12:16 +01001360 if ($type === $this->xmlrpcBoolean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001361 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001362 $val = (int) (strcasecmp($val,'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
Derek Allard2067d1a2008-11-13 22:59:24 +00001363 }
1364
Alex Bilbied261b1e2012-06-02 11:12:16 +01001365 if ($this->mytype === 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001366 {
1367 // adding to an array here
1368 $ar = $this->me['array'];
1369 $ar[] = new XML_RPC_Values($val, $type);
1370 $this->me['array'] = $ar;
1371 }
1372 else
1373 {
1374 // a scalar, so set the value and remember we're scalar
1375 $this->me[$type] = $val;
1376 $this->mytype = $typeof;
1377 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001378
Derek Allard2067d1a2008-11-13 22:59:24 +00001379 return 1;
1380 }
1381
Andrey Andreevc8709832012-04-04 13:43:53 +03001382 // --------------------------------------------------------------------
1383
1384 /**
1385 * Add array value
1386 *
1387 * @param array
1388 * @return int
1389 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001390 public function addArray($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001391 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001392 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001393 {
1394 echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
1395 return 0;
1396 }
1397
1398 $this->mytype = $this->xmlrpcTypes['array'];
1399 $this->me['array'] = $vals;
1400 return 1;
1401 }
1402
Andrey Andreevc8709832012-04-04 13:43:53 +03001403 // --------------------------------------------------------------------
1404
1405 /**
1406 * Add struct value
1407 *
1408 * @param object
1409 * @return int
1410 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001411 public function addStruct($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001412 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001413 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001414 {
1415 echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
1416 return 0;
1417 }
1418 $this->mytype = $this->xmlrpcTypes['struct'];
1419 $this->me['struct'] = $vals;
1420 return 1;
1421 }
1422
Andrey Andreevc8709832012-04-04 13:43:53 +03001423 // --------------------------------------------------------------------
1424
1425 /**
1426 * Get value type
1427 *
1428 * @return string
1429 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001430 public function kindOf()
Derek Allard2067d1a2008-11-13 22:59:24 +00001431 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001432 switch ($this->mytype)
Derek Allard2067d1a2008-11-13 22:59:24 +00001433 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001434 case 3: return 'struct';
1435 case 2: return 'array';
1436 case 1: return 'scalar';
1437 default: return 'undef';
Derek Allard2067d1a2008-11-13 22:59:24 +00001438 }
1439 }
1440
Andrey Andreevc8709832012-04-04 13:43:53 +03001441 // --------------------------------------------------------------------
1442
1443 /**
1444 * Serialize data
1445 *
1446 * @param string
1447 * @param mixed
1448 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001449 public function serializedata($typ, $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001450 {
1451 $rs = '';
Derek Jonesa9647e82010-03-02 22:59:07 -06001452
Andrey Andreevc8709832012-04-04 13:43:53 +03001453 switch ($this->xmlrpcTypes[$typ])
Derek Allard2067d1a2008-11-13 22:59:24 +00001454 {
1455 case 3:
1456 // struct
1457 $rs .= "<struct>\n";
1458 reset($val);
Pascal Kriete14287f32011-02-14 13:39:34 -05001459 while (list($key2, $val2) = each($val))
Derek Allard2067d1a2008-11-13 22:59:24 +00001460 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001461 $rs .= "<member>\n<name>{$key2}</name>\n".$this->serializeval($val2)."</member>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001462 }
1463 $rs .= '</struct>';
Andrey Andreevc8709832012-04-04 13:43:53 +03001464 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001465 case 2:
1466 // array
1467 $rs .= "<array>\n<data>\n";
Andrey Andreevc8709832012-04-04 13:43:53 +03001468 for ($i = 0, $c = count($val); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001469 {
1470 $rs .= $this->serializeval($val[$i]);
1471 }
Andrey Andreeva30faf92011-12-25 18:15:34 +02001472 $rs .= "</data>\n</array>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001473 break;
1474 case 1:
1475 // others
1476 switch ($typ)
1477 {
1478 case $this->xmlrpcBase64:
Andrey Andreevc8709832012-04-04 13:43:53 +03001479 $rs .= '<'.$typ.'>'.base64_encode( (string) $val).'</'.$typ.">\n";
1480 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001481 case $this->xmlrpcBoolean:
Andrey Andreevc8709832012-04-04 13:43:53 +03001482 $rs .= '<'.$typ.'>'.( (bool) $val ? '1' : '0').'</'.$typ.">\n";
1483 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001484 case $this->xmlrpcString:
Andrey Andreevc8709832012-04-04 13:43:53 +03001485 $rs .= '<'.$typ.'>'.htmlspecialchars( (string) $val).'</'.$typ.">\n";
1486 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001487 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001488 $rs .= '<'.$typ.'>'.$val.'</'.$typ.">\n";
1489 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001490 }
1491 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001492 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001493 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001494
Derek Allard2067d1a2008-11-13 22:59:24 +00001495 return $rs;
1496 }
1497
Andrey Andreevc8709832012-04-04 13:43:53 +03001498 // --------------------------------------------------------------------
1499
1500 /**
1501 * Serialize class
1502 *
1503 * @return string
1504 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001505 public function serialize_class()
Derek Allard2067d1a2008-11-13 22:59:24 +00001506 {
1507 return $this->serializeval($this);
1508 }
1509
Andrey Andreevc8709832012-04-04 13:43:53 +03001510 // --------------------------------------------------------------------
1511
1512 /**
1513 * Serialize value
1514 *
1515 * @param object
1516 * @return string
1517 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001518 public function serializeval($o)
Derek Allard2067d1a2008-11-13 22:59:24 +00001519 {
1520 $ar = $o->me;
1521 reset($ar);
Barry Mienydd671972010-10-04 16:33:58 +02001522
Derek Allard2067d1a2008-11-13 22:59:24 +00001523 list($typ, $val) = each($ar);
Andrey Andreeva30faf92011-12-25 18:15:34 +02001524 return "<value>\n".$this->serializedata($typ, $val)."</value>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001525 }
Barry Mienydd671972010-10-04 16:33:58 +02001526
Andrey Andreevc8709832012-04-04 13:43:53 +03001527 // --------------------------------------------------------------------
1528
1529 /**
1530 * Scalar value
1531 *
1532 * @return mixed
1533 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001534 public function scalarval()
Derek Allard2067d1a2008-11-13 22:59:24 +00001535 {
1536 reset($this->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001537 return current($this->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001538 }
1539
Andrey Andreevc8709832012-04-04 13:43:53 +03001540 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001541
Andrey Andreevc8709832012-04-04 13:43:53 +03001542 /**
1543 * Encode time in ISO-8601 form.
1544 * Useful for sending time in XML-RPC
1545 *
1546 * @param int unix timestamp
1547 * @param bool
1548 * @return string
1549 */
1550 public function iso8601_encode($time, $utc = FALSE)
Barry Mienydd671972010-10-04 16:33:58 +02001551 {
Andrey Andreev62090152011-12-30 12:49:27 +02001552 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 +00001553 }
Barry Mienydd671972010-10-04 16:33:58 +02001554
Andrey Andreevc8709832012-04-04 13:43:53 +03001555} // END XML_RPC_Values Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001556
1557/* End of file Xmlrpc.php */
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001558/* Location: ./system/libraries/Xmlrpc.php */