blob: 58389bf328874f25e9e75e7ec5b834854baba32f [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 {
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300443 if ($this->proxy === FALSE)
444 {
445 $server = $this->server;
446 $port = $this->port;
447 } else {
Valio9dee5352012-07-02 10:42:28 +0300448 $server = $this->proxy;
449 $port = $this->proxy_port;
450 }
Valentin Sheyretskicfcf34e2012-07-02 12:04:36 +0300451
Valio9dee5352012-07-02 10:42:28 +0300452 $fp = @fsockopen($server, $port, $this->errno, $this->errstring, $this->timeout);
Barry Mienydd671972010-10-04 16:33:58 +0200453
Derek Allard2067d1a2008-11-13 22:59:24 +0000454 if ( ! is_resource($fp))
455 {
456 error_log($this->xmlrpcstr['http_error']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300457 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000458 }
Barry Mienydd671972010-10-04 16:33:58 +0200459
Pascal Kriete14287f32011-02-14 13:39:34 -0500460 if (empty($msg->payload))
Derek Allard2067d1a2008-11-13 22:59:24 +0000461 {
462 // $msg = XML_RPC_Messages
463 $msg->createPayload();
464 }
Barry Mienydd671972010-10-04 16:33:58 +0200465
Derek Allard2067d1a2008-11-13 22:59:24 +0000466 $r = "\r\n";
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300467 $op = 'POST '.$this->path.' HTTP/1.0'.$r
468 .'Host: '.$this->server.$r
469 .'Content-Type: text/xml'.$r
470 .'User-Agent: '.$this->xmlrpcName.$r
471 .'Content-Length: '.strlen($msg->payload).$r.$r
472 .$msg->payload;
Barry Mienydd671972010-10-04 16:33:58 +0200473
George Petsagourakis306b3782012-05-02 20:31:08 +0300474 if ( ! fwrite($fp, $op, strlen($op)))
Derek Allard2067d1a2008-11-13 22:59:24 +0000475 {
476 error_log($this->xmlrpcstr['http_error']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300477 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000478 }
Andrey Andreevc8709832012-04-04 13:43:53 +0300479
Derek Allard2067d1a2008-11-13 22:59:24 +0000480 $resp = $msg->parseResponse($fp);
481 fclose($fp);
482 return $resp;
483 }
484
Andrey Andreevc8709832012-04-04 13:43:53 +0300485} // END XML_RPC_Client Class
Derek Allard2067d1a2008-11-13 22:59:24 +0000486
487/**
488 * XML-RPC Response class
489 *
490 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500491 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000492 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
493 */
494class XML_RPC_Response
495{
Andrey Andreevc8709832012-04-04 13:43:53 +0300496 public $val = 0;
497 public $errno = 0;
498 public $errstr = '';
499 public $headers = array();
500 public $xss_clean = TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000501
Andrey Andreevc8709832012-04-04 13:43:53 +0300502 /**
503 * Constructor
504 *
505 * @param mixed
506 * @param int
507 * @param string
508 * @return void
509 */
Greg Akera9263282010-11-10 15:26:43 -0600510 public function __construct($val, $code = 0, $fstr = '')
Barry Mienydd671972010-10-04 16:33:58 +0200511 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100512 if ($code !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000513 {
514 // error
515 $this->errno = $code;
Andrey Andreevc8709832012-04-04 13:43:53 +0300516 $this->errstr = htmlspecialchars($fstr,
517 (is_php('5.4') ? ENT_XML1 | ENT_NOQUOTES : ENT_NOQUOTES),
518 'UTF-8');
Derek Allard2067d1a2008-11-13 22:59:24 +0000519 }
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300520 elseif ( ! is_object($val))
Derek Allard2067d1a2008-11-13 22:59:24 +0000521 {
522 // programmer error, not an object
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300523 error_log("Invalid type '".gettype($val)."' (value: ".$val.') passed to XML_RPC_Response. Defaulting to empty value.');
Derek Allard2067d1a2008-11-13 22:59:24 +0000524 $this->val = new XML_RPC_Values();
525 }
526 else
527 {
528 $this->val = $val;
529 }
530 }
531
Andrey Andreevc8709832012-04-04 13:43:53 +0300532 // --------------------------------------------------------------------
533
534 /**
535 * Fault code
536 *
537 * @return int
538 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200539 public function faultCode()
Derek Allard2067d1a2008-11-13 22:59:24 +0000540 {
541 return $this->errno;
542 }
543
Andrey Andreevc8709832012-04-04 13:43:53 +0300544 // --------------------------------------------------------------------
545
546 /**
547 * Fault string
548 *
549 * @return string
550 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200551 public function faultString()
Derek Allard2067d1a2008-11-13 22:59:24 +0000552 {
553 return $this->errstr;
554 }
555
Andrey Andreevc8709832012-04-04 13:43:53 +0300556 // --------------------------------------------------------------------
557
558 /**
559 * Value
560 *
561 * @return mixed
562 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200563 public function value()
Derek Allard2067d1a2008-11-13 22:59:24 +0000564 {
565 return $this->val;
566 }
Barry Mienydd671972010-10-04 16:33:58 +0200567
Andrey Andreevc8709832012-04-04 13:43:53 +0300568 // --------------------------------------------------------------------
569
570 /**
571 * Prepare response
572 *
573 * @return string xml
574 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200575 public function prepare_response()
Derek Allard2067d1a2008-11-13 22:59:24 +0000576 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200577 return "<methodResponse>\n"
Andrey Andreevc8709832012-04-04 13:43:53 +0300578 .($this->errno
579 ? '<fault>
Derek Allard2067d1a2008-11-13 22:59:24 +0000580 <value>
581 <struct>
582 <member>
583 <name>faultCode</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300584 <value><int>'.$this->errno.'</int></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000585 </member>
586 <member>
587 <name>faultString</name>
Andrey Andreevc8709832012-04-04 13:43:53 +0300588 <value><string>'.$this->errstr.'</string></value>
Derek Allard2067d1a2008-11-13 22:59:24 +0000589 </member>
590 </struct>
591 </value>
Andrey Andreeva30faf92011-12-25 18:15:34 +0200592</fault>'
Andrey Andreevc8709832012-04-04 13:43:53 +0300593 : "<params>\n<param>\n".$this->val->serialize_class()."</param>\n</params>")
594 ."\n</methodResponse>";
Derek Allard2067d1a2008-11-13 22:59:24 +0000595 }
Barry Mienydd671972010-10-04 16:33:58 +0200596
Andrey Andreevc8709832012-04-04 13:43:53 +0300597 // --------------------------------------------------------------------
598
599 /**
600 * Decode
601 *
602 * @param mixed
603 * @return array
604 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200605 public function decode($array = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000606 {
607 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +0200608
609 if (is_array($array))
Derek Allard2067d1a2008-11-13 22:59:24 +0000610 {
611 while (list($key) = each($array))
612 {
613 if (is_array($array[$key]))
614 {
615 $array[$key] = $this->decode($array[$key]);
616 }
617 else
618 {
Robin Sowell66a3fc02010-03-18 09:44:55 -0400619 $array[$key] = ($this->xss_clean) ? $CI->security->xss_clean($array[$key]) : $array[$key];
Derek Allard2067d1a2008-11-13 22:59:24 +0000620 }
621 }
Barry Mienydd671972010-10-04 16:33:58 +0200622
Andrey Andreevc8709832012-04-04 13:43:53 +0300623 return $array;
624 }
625
626 $result = $this->xmlrpc_decoder($this->val);
627
628 if (is_array($result))
629 {
630 $result = $this->decode($result);
Derek Allard2067d1a2008-11-13 22:59:24 +0000631 }
632 else
633 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300634 $result = ($this->xss_clean) ? $CI->security->xss_clean($result) : $result;
Derek Allard2067d1a2008-11-13 22:59:24 +0000635 }
Barry Mienydd671972010-10-04 16:33:58 +0200636
Derek Allard2067d1a2008-11-13 22:59:24 +0000637 return $result;
638 }
639
Andrey Andreevc8709832012-04-04 13:43:53 +0300640 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000641
Andrey Andreevc8709832012-04-04 13:43:53 +0300642 /**
643 * XML-RPC Object to PHP Types
644 *
645 * @param object
646 * @return array
647 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200648 public function xmlrpc_decoder($xmlrpc_val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000649 {
650 $kind = $xmlrpc_val->kindOf();
651
Alex Bilbied261b1e2012-06-02 11:12:16 +0100652 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +0000653 {
654 return $xmlrpc_val->scalarval();
655 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100656 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +0000657 {
658 reset($xmlrpc_val->me);
Andrey Andreevadc11752011-12-30 14:46:08 +0200659 $b = current($xmlrpc_val->me);
Derek Allard2067d1a2008-11-13 22:59:24 +0000660 $arr = array();
661
Andrey Andreeva30faf92011-12-25 18:15:34 +0200662 for ($i = 0, $size = count($b); $i < $size; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000663 {
664 $arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);
665 }
666 return $arr;
667 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100668 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +0000669 {
670 reset($xmlrpc_val->me['struct']);
671 $arr = array();
672
Pascal Kriete14287f32011-02-14 13:39:34 -0500673 while (list($key,$value) = each($xmlrpc_val->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000674 {
675 $arr[$key] = $this->xmlrpc_decoder($value);
676 }
677 return $arr;
678 }
679 }
Barry Mienydd671972010-10-04 16:33:58 +0200680
Andrey Andreevc8709832012-04-04 13:43:53 +0300681 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000682
Andrey Andreevc8709832012-04-04 13:43:53 +0300683 /**
684 * ISO-8601 time to server or UTC time
685 *
686 * @param string
687 * @param bool
688 * @return int unix timestamp
689 */
690 public function iso8601_decode($time, $utc = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000691 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300692 // return a time in the localtime, or UTC
Derek Allard2067d1a2008-11-13 22:59:24 +0000693 $t = 0;
694 if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))
695 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100696 $fnc = ($utc === TRUE) ? 'gmmktime' : 'mktime';
Pascal Kriete14287f32011-02-14 13:39:34 -0500697 $t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
Derek Allard2067d1a2008-11-13 22:59:24 +0000698 }
699 return $t;
700 }
Barry Mienydd671972010-10-04 16:33:58 +0200701
Andrey Andreevc8709832012-04-04 13:43:53 +0300702} // END XML_RPC_Response Class
Derek Allard2067d1a2008-11-13 22:59:24 +0000703
704/**
705 * XML-RPC Message class
706 *
707 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -0500708 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +0000709 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
710 */
711class XML_RPC_Message extends CI_Xmlrpc
712{
Andrey Andreeva30faf92011-12-25 18:15:34 +0200713 public $payload;
714 public $method_name;
Andrey Andreevc8709832012-04-04 13:43:53 +0300715 public $params = array();
716 public $xh = array();
Derek Allard2067d1a2008-11-13 22:59:24 +0000717
Andrey Andreevc8709832012-04-04 13:43:53 +0300718 /**
719 * Constructor
720 *
721 * @param string method name
722 * @param array
723 * @return void
724 */
725 public function __construct($method, $pars = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000726 {
Greg Akera9263282010-11-10 15:26:43 -0600727 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +0200728
Derek Allard2067d1a2008-11-13 22:59:24 +0000729 $this->method_name = $method;
Derek Jones33559102009-02-02 18:50:38 +0000730 if (is_array($pars) && count($pars) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000731 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200732 for ($i = 0, $c = count($pars); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000733 {
734 // $pars[$i] = XML_RPC_Values
735 $this->params[] = $pars[$i];
736 }
737 }
738 }
Barry Mienydd671972010-10-04 16:33:58 +0200739
Andrey Andreevc8709832012-04-04 13:43:53 +0300740 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200741
Andrey Andreevc8709832012-04-04 13:43:53 +0300742 /**
743 * Create Payload to Send
744 *
745 * @return void
746 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200747 public function createPayload()
Derek Allard2067d1a2008-11-13 22:59:24 +0000748 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300749 $this->payload = '<?xml version="1.0"?'.">\r\n<methodCall>\r\n"
750 .'<methodName>'.$this->method_name."</methodName>\r\n"
751 ."<params>\r\n";
Barry Mienydd671972010-10-04 16:33:58 +0200752
Andrey Andreeva30faf92011-12-25 18:15:34 +0200753 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000754 {
755 // $p = XML_RPC_Values
756 $p = $this->params[$i];
757 $this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n";
758 }
Barry Mienydd671972010-10-04 16:33:58 +0200759
Derek Allard2067d1a2008-11-13 22:59:24 +0000760 $this->payload .= "</params>\r\n</methodCall>\r\n";
761 }
Barry Mienydd671972010-10-04 16:33:58 +0200762
Andrey Andreevc8709832012-04-04 13:43:53 +0300763 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200764
Andrey Andreevc8709832012-04-04 13:43:53 +0300765 /**
766 * Parse External XML-RPC Server's Response
767 *
768 * @param resource
769 * @return object
770 */
Andrey Andreeva30faf92011-12-25 18:15:34 +0200771 public function parseResponse($fp)
Derek Allard2067d1a2008-11-13 22:59:24 +0000772 {
773 $data = '';
Barry Mienydd671972010-10-04 16:33:58 +0200774
Pascal Kriete14287f32011-02-14 13:39:34 -0500775 while ($datum = fread($fp, 4096))
Derek Allard2067d1a2008-11-13 22:59:24 +0000776 {
777 $data .= $datum;
778 }
Barry Mienydd671972010-10-04 16:33:58 +0200779
Andrey Andreevc8709832012-04-04 13:43:53 +0300780 // Display HTTP content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +0000781 if ($this->debug === TRUE)
782 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200783 echo "<pre>---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n</pre>";
Derek Allard2067d1a2008-11-13 22:59:24 +0000784 }
Barry Mienydd671972010-10-04 16:33:58 +0200785
Andrey Andreevc8709832012-04-04 13:43:53 +0300786 // Check for data
Andrey Andreeva30faf92011-12-25 18:15:34 +0200787 if ($data === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000788 {
789 error_log($this->xmlrpcstr['no_data']);
Andrey Andreevc8709832012-04-04 13:43:53 +0300790 return new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
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 HTTP 200 Response
Andrey Andreev3dad2e72012-06-14 15:10:56 +0300794 if (strpos($data, 'HTTP') === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
Derek Allard2067d1a2008-11-13 22:59:24 +0000795 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300796 $errstr = substr($data, 0, strpos($data, "\n")-1);
797 return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');
Derek Allard2067d1a2008-11-13 22:59:24 +0000798 }
Barry Mienydd671972010-10-04 16:33:58 +0200799
Derek Allard2067d1a2008-11-13 22:59:24 +0000800 //-------------------------------------
Derek Jones37f4b9c2011-07-01 17:56:50 -0500801 // Create and Set Up XML Parser
Derek Allard2067d1a2008-11-13 22:59:24 +0000802 //-------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200803
Derek Allard2067d1a2008-11-13 22:59:24 +0000804 $parser = xml_parser_create($this->xmlrpc_defencoding);
805
Andrey Andreeva30faf92011-12-25 18:15:34 +0200806 $this->xh[$parser] = array(
Andrey Andreevc8709832012-04-04 13:43:53 +0300807 'isf' => 0,
808 'ac' => '',
809 'headers' => array(),
810 'stack' => array(),
811 'valuestack' => array(),
812 'isf_reason' => 0
Andrey Andreeva30faf92011-12-25 18:15:34 +0200813 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000814
815 xml_set_object($parser, $this);
Andrey Andreevc8709832012-04-04 13:43:53 +0300816 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000817 xml_set_element_handler($parser, 'open_tag', 'closing_tag');
818 xml_set_character_data_handler($parser, 'character_data');
819 //xml_set_default_handler($parser, 'default_handler');
820
Andrey Andreevc8709832012-04-04 13:43:53 +0300821 // Get headers
Derek Allard2067d1a2008-11-13 22:59:24 +0000822 $lines = explode("\r\n", $data);
823 while (($line = array_shift($lines)))
824 {
825 if (strlen($line) < 1)
826 {
827 break;
828 }
829 $this->xh[$parser]['headers'][] = $line;
830 }
831 $data = implode("\r\n", $lines);
Barry Mienydd671972010-10-04 16:33:58 +0200832
Andrey Andreevc8709832012-04-04 13:43:53 +0300833 // Parse XML data
Derek Jones33559102009-02-02 18:50:38 +0000834 if ( ! xml_parse($parser, $data, count($data)))
Derek Allard2067d1a2008-11-13 22:59:24 +0000835 {
836 $errstr = sprintf('XML error: %s at line %d',
Andrey Andreevc8709832012-04-04 13:43:53 +0300837 xml_error_string(xml_get_error_code($parser)),
838 xml_get_current_line_number($parser));
Derek Allard2067d1a2008-11-13 22:59:24 +0000839 //error_log($errstr);
840 $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
841 xml_parser_free($parser);
842 return $r;
843 }
844 xml_parser_free($parser);
Barry Mienydd671972010-10-04 16:33:58 +0200845
Andrey Andreevc8709832012-04-04 13:43:53 +0300846 // Got ourselves some badness, it seems
Derek Allard2067d1a2008-11-13 22:59:24 +0000847 if ($this->xh[$parser]['isf'] > 1)
848 {
849 if ($this->debug === TRUE)
850 {
Andrey Andreeva30faf92011-12-25 18:15:34 +0200851 echo "---Invalid Return---\n".$this->xh[$parser]['isf_reason']."---Invalid Return---\n\n";
Derek Allard2067d1a2008-11-13 22:59:24 +0000852 }
Barry Mienydd671972010-10-04 16:33:58 +0200853
Andrey Andreevc8709832012-04-04 13:43:53 +0300854 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 +0000855 }
856 elseif ( ! is_object($this->xh[$parser]['value']))
857 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300858 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 +0000859 }
Barry Mienydd671972010-10-04 16:33:58 +0200860
Andrey Andreevc8709832012-04-04 13:43:53 +0300861 // Display XML content for debugging
Derek Allard2067d1a2008-11-13 22:59:24 +0000862 if ($this->debug === TRUE)
863 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300864 echo '<pre>';
Barry Mienydd671972010-10-04 16:33:58 +0200865
Derek Allard2067d1a2008-11-13 22:59:24 +0000866 if (count($this->xh[$parser]['headers'] > 0))
867 {
868 echo "---HEADERS---\n";
869 foreach ($this->xh[$parser]['headers'] as $header)
870 {
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300871 echo $header."\n";
Derek Allard2067d1a2008-11-13 22:59:24 +0000872 }
873 echo "---END HEADERS---\n\n";
874 }
Barry Mienydd671972010-10-04 16:33:58 +0200875
Andrey Andreeva30faf92011-12-25 18:15:34 +0200876 echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n---PARSED---\n";
Derek Allard2067d1a2008-11-13 22:59:24 +0000877 var_dump($this->xh[$parser]['value']);
878 echo "\n---END PARSED---</pre>";
879 }
Barry Mienydd671972010-10-04 16:33:58 +0200880
Andrey Andreevc8709832012-04-04 13:43:53 +0300881 // Send response
Derek Allard2067d1a2008-11-13 22:59:24 +0000882 $v = $this->xh[$parser]['value'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000883 if ($this->xh[$parser]['isf'])
884 {
885 $errno_v = $v->me['struct']['faultCode'];
886 $errstr_v = $v->me['struct']['faultString'];
887 $errno = $errno_v->scalarval();
888
Alex Bilbied261b1e2012-06-02 11:12:16 +0100889 if ($errno === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000890 {
891 // FAULT returned, errno needs to reflect that
892 $errno = -1;
893 }
894
895 $r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
896 }
897 else
898 {
899 $r = new XML_RPC_Response($v);
900 }
901
902 $r->headers = $this->xh[$parser]['headers'];
903 return $r;
904 }
Barry Mienydd671972010-10-04 16:33:58 +0200905
Andrey Andreevc8709832012-04-04 13:43:53 +0300906 // --------------------------------------------------------------------
907
Derek Allard2067d1a2008-11-13 22:59:24 +0000908 // ------------------------------------
Derek Jones37f4b9c2011-07-01 17:56:50 -0500909 // Begin Return Message Parsing section
Derek Allard2067d1a2008-11-13 22:59:24 +0000910 // ------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200911
Derek Allard2067d1a2008-11-13 22:59:24 +0000912 // quick explanation of components:
Derek Jones37f4b9c2011-07-01 17:56:50 -0500913 // ac - used to accumulate values
914 // isf - used to indicate a fault
915 // lv - used to indicate "looking for a value": implements
Derek Allard2067d1a2008-11-13 22:59:24 +0000916 // the logic to allow values with no types to be strings
Derek Jones37f4b9c2011-07-01 17:56:50 -0500917 // params - used to store parameters in method calls
918 // method - used to store method name
Derek Allard2067d1a2008-11-13 22:59:24 +0000919 // stack - array with parent tree of the xml element,
920 // used to validate the nesting of elements
921
Andrey Andreevc8709832012-04-04 13:43:53 +0300922 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000923
Andrey Andreevc8709832012-04-04 13:43:53 +0300924 /**
925 * Start Element Handler
926 *
927 * @param string
928 * @param string
929 * @return void
930 */
931 public function open_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +0000932 {
933 // If invalid nesting, then return
934 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +0200935
Derek Allard2067d1a2008-11-13 22:59:24 +0000936 // Evaluate and check for correct nesting of XML elements
Alex Bilbied261b1e2012-06-02 11:12:16 +0100937 if (count($this->xh[$the_parser]['stack']) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000938 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100939 if ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')
Derek Allard2067d1a2008-11-13 22:59:24 +0000940 {
941 $this->xh[$the_parser]['isf'] = 2;
942 $this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
943 return;
944 }
945 }
Andrey Andreevc8709832012-04-04 13:43:53 +0300946 // not top level element: see if parent is OK
947 elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +0000948 {
Andrey Andreevc8709832012-04-04 13:43:53 +0300949 $this->xh[$the_parser]['isf'] = 2;
950 $this->xh[$the_parser]['isf_reason'] = 'XML-RPC element $name cannot be child of '.$this->xh[$the_parser]['stack'][0];
951 return;
Derek Allard2067d1a2008-11-13 22:59:24 +0000952 }
Barry Mienydd671972010-10-04 16:33:58 +0200953
Andrey Andreevc8709832012-04-04 13:43:53 +0300954 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +0000955 {
956 case 'STRUCT':
957 case 'ARRAY':
958 // Creates array for child elements
Andrey Andreev8f50b6b2012-03-28 14:12:09 +0300959 $cur_val = array('value' => array(), 'type' => $name);
Derek Allard2067d1a2008-11-13 22:59:24 +0000960 array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
Andrey Andreevc8709832012-04-04 13:43:53 +0300961 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000962 case 'METHODNAME':
963 case 'NAME':
964 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +0300965 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000966 case 'FAULT':
967 $this->xh[$the_parser]['isf'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +0300968 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000969 case 'PARAM':
Pascal Kriete8761ef52011-02-14 13:13:52 -0500970 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +0300971 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000972 case 'VALUE':
973 $this->xh[$the_parser]['vt'] = 'value';
974 $this->xh[$the_parser]['ac'] = '';
975 $this->xh[$the_parser]['lv'] = 1;
Andrey Andreevc8709832012-04-04 13:43:53 +0300976 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000977 case 'I4':
978 case 'INT':
979 case 'STRING':
980 case 'BOOLEAN':
981 case 'DOUBLE':
982 case 'DATETIME.ISO8601':
983 case 'BASE64':
Alex Bilbied261b1e2012-06-02 11:12:16 +0100984 if ($this->xh[$the_parser]['vt'] !== 'value')
Derek Allard2067d1a2008-11-13 22:59:24 +0000985 {
986 //two data elements inside a value: an error occurred!
987 $this->xh[$the_parser]['isf'] = 2;
Andrey Andreevc8709832012-04-04 13:43:53 +0300988 $this->xh[$the_parser]['isf_reason'] = "'Twas a ".$name.' element following a '
989 .$this->xh[$the_parser]['vt'].' element inside a single value';
Derek Allard2067d1a2008-11-13 22:59:24 +0000990 return;
991 }
Barry Mienydd671972010-10-04 16:33:58 +0200992
Derek Allard2067d1a2008-11-13 22:59:24 +0000993 $this->xh[$the_parser]['ac'] = '';
Andrey Andreevc8709832012-04-04 13:43:53 +0300994 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000995 case 'MEMBER':
996 // Set name of <member> to nothing to prevent errors later if no <name> is found
997 $this->xh[$the_parser]['valuestack'][0]['name'] = '';
Barry Mienydd671972010-10-04 16:33:58 +0200998
Derek Allard2067d1a2008-11-13 22:59:24 +0000999 // Set NULL value to check to see if value passed for this param/member
Pascal Kriete8761ef52011-02-14 13:13:52 -05001000 $this->xh[$the_parser]['value'] = NULL;
Andrey Andreevc8709832012-04-04 13:43:53 +03001001 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001002 case 'DATA':
1003 case 'METHODCALL':
1004 case 'METHODRESPONSE':
1005 case 'PARAMS':
1006 // valid elements that add little to processing
Andrey Andreevc8709832012-04-04 13:43:53 +03001007 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001008 default:
1009 /// An Invalid Element is Found, so we have trouble
1010 $this->xh[$the_parser]['isf'] = 2;
Andrey Andreevc8709832012-04-04 13:43:53 +03001011 $this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;
1012 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001013 }
Barry Mienydd671972010-10-04 16:33:58 +02001014
Derek Allard2067d1a2008-11-13 22:59:24 +00001015 // Add current element name to stack, to allow validation of nesting
1016 array_unshift($this->xh[$the_parser]['stack'], $name);
1017
Alex Bilbied261b1e2012-06-02 11:12:16 +01001018 $name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001019 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001020
Andrey Andreevc8709832012-04-04 13:43:53 +03001021 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001022
Andrey Andreevc8709832012-04-04 13:43:53 +03001023 /**
1024 * End Element Handler
1025 *
1026 * @param string
1027 * @param string
1028 * @return void
1029 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001030 public function closing_tag($the_parser, $name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001031 {
1032 if ($this->xh[$the_parser]['isf'] > 1) return;
Barry Mienydd671972010-10-04 16:33:58 +02001033
Derek Allard2067d1a2008-11-13 22:59:24 +00001034 // Remove current element from stack and set variable
1035 // NOTE: If the XML validates, then we do not have to worry about
Andrey Andreevc8709832012-04-04 13:43:53 +03001036 // the opening and closing of elements. Nesting is checked on the opening
Derek Allard2067d1a2008-11-13 22:59:24 +00001037 // tag so we be safe there as well.
Barry Mienydd671972010-10-04 16:33:58 +02001038
Derek Allard2067d1a2008-11-13 22:59:24 +00001039 $curr_elem = array_shift($this->xh[$the_parser]['stack']);
Barry Mienydd671972010-10-04 16:33:58 +02001040
Andrey Andreevc8709832012-04-04 13:43:53 +03001041 switch ($name)
Derek Allard2067d1a2008-11-13 22:59:24 +00001042 {
1043 case 'STRUCT':
1044 case 'ARRAY':
1045 $cur_val = array_shift($this->xh[$the_parser]['valuestack']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001046 $this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();
Derek Allard2067d1a2008-11-13 22:59:24 +00001047 $this->xh[$the_parser]['vt'] = strtolower($name);
Andrey Andreevc8709832012-04-04 13:43:53 +03001048 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001049 case 'NAME':
1050 $this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
Andrey Andreevc8709832012-04-04 13:43:53 +03001051 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001052 case 'BOOLEAN':
1053 case 'I4':
1054 case 'INT':
1055 case 'STRING':
1056 case 'DOUBLE':
1057 case 'DATETIME.ISO8601':
1058 case 'BASE64':
1059 $this->xh[$the_parser]['vt'] = strtolower($name);
Barry Mienydd671972010-10-04 16:33:58 +02001060
Alex Bilbied261b1e2012-06-02 11:12:16 +01001061 if ($name === 'STRING')
Derek Allard2067d1a2008-11-13 22:59:24 +00001062 {
1063 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1064 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001065 elseif ($name === 'DATETIME.ISO8601')
Derek Allard2067d1a2008-11-13 22:59:24 +00001066 {
1067 $this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime;
1068 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1069 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001070 elseif ($name === 'BASE64')
Derek Allard2067d1a2008-11-13 22:59:24 +00001071 {
1072 $this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
1073 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001074 elseif ($name === 'BOOLEAN')
Derek Allard2067d1a2008-11-13 22:59:24 +00001075 {
1076 // Translated BOOLEAN values to TRUE AND FALSE
Andrey Andreevc8709832012-04-04 13:43:53 +03001077 $this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001078 }
1079 elseif ($name=='DOUBLE')
1080 {
1081 // we have a DOUBLE
1082 // we must check that only 0123456789-.<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001083 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])
1084 ? (float) $this->xh[$the_parser]['ac']
1085 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001086 }
1087 else
1088 {
1089 // we have an I4/INT
1090 // we must check that only 0123456789-<space> are characters here
Andrey Andreevc8709832012-04-04 13:43:53 +03001091 $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])
George Petsagourakis306b3782012-05-02 20:31:08 +03001092 ? (int) $this->xh[$the_parser]['ac']
Andrey Andreevc8709832012-04-04 13:43:53 +03001093 : 'ERROR_NON_NUMERIC_FOUND';
Derek Allard2067d1a2008-11-13 22:59:24 +00001094 }
1095 $this->xh[$the_parser]['ac'] = '';
1096 $this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
Andrey Andreevc8709832012-04-04 13:43:53 +03001097 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001098 case 'VALUE':
1099 // This if() detects if no scalar was inside <VALUE></VALUE>
1100 if ($this->xh[$the_parser]['vt']=='value')
1101 {
1102 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1103 $this->xh[$the_parser]['vt'] = $this->xmlrpcString;
1104 }
Barry Mienydd671972010-10-04 16:33:58 +02001105
Derek Allard2067d1a2008-11-13 22:59:24 +00001106 // build the XML-RPC value out of the data received, and substitute it
1107 $temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
Barry Mienydd671972010-10-04 16:33:58 +02001108
Alex Bilbied261b1e2012-06-02 11:12:16 +01001109 if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')
Derek Allard2067d1a2008-11-13 22:59:24 +00001110 {
1111 // Array
1112 $this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
1113 }
1114 else
1115 {
1116 // Struct
1117 $this->xh[$the_parser]['value'] = $temp;
1118 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001119 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001120 case 'MEMBER':
Andrey Andreevc8709832012-04-04 13:43:53 +03001121 $this->xh[$the_parser]['ac'] = '';
Barry Mienydd671972010-10-04 16:33:58 +02001122
Derek Allard2067d1a2008-11-13 22:59:24 +00001123 // If value add to array in the stack for the last element built
1124 if ($this->xh[$the_parser]['value'])
1125 {
1126 $this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
1127 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001128 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001129 case 'DATA':
Andrey Andreevc8709832012-04-04 13:43:53 +03001130 $this->xh[$the_parser]['ac'] = '';
1131 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001132 case 'PARAM':
1133 if ($this->xh[$the_parser]['value'])
1134 {
1135 $this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
1136 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001137 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001138 case 'METHODNAME':
1139 $this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
Andrey Andreevc8709832012-04-04 13:43:53 +03001140 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001141 case 'PARAMS':
1142 case 'FAULT':
1143 case 'METHODCALL':
1144 case 'METHORESPONSE':
1145 // We're all good kids with nuthin' to do
Andrey Andreevc8709832012-04-04 13:43:53 +03001146 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001147 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001148 // End of an Invalid Element. Taken care of during the opening tag though
1149 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001150 }
1151 }
1152
Andrey Andreevc8709832012-04-04 13:43:53 +03001153 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001154
Andrey Andreevc8709832012-04-04 13:43:53 +03001155 /**
1156 * Parse character data
1157 *
1158 * @param string
1159 * @param string
1160 * @return void
1161 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001162 public function character_data($the_parser, $data)
Derek Allard2067d1a2008-11-13 22:59:24 +00001163 {
1164 if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
Barry Mienydd671972010-10-04 16:33:58 +02001165
Derek Allard2067d1a2008-11-13 22:59:24 +00001166 // If a value has not been found
Alex Bilbied261b1e2012-06-02 11:12:16 +01001167 if ($this->xh[$the_parser]['lv'] !== 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001168 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001169 if ($this->xh[$the_parser]['lv'] === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001170 {
1171 $this->xh[$the_parser]['lv'] = 2; // Found a value
1172 }
Barry Mienydd671972010-10-04 16:33:58 +02001173
Andrey Andreevc8709832012-04-04 13:43:53 +03001174 if ( ! isset($this->xh[$the_parser]['ac']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001175 {
1176 $this->xh[$the_parser]['ac'] = '';
1177 }
Barry Mienydd671972010-10-04 16:33:58 +02001178
Derek Allard2067d1a2008-11-13 22:59:24 +00001179 $this->xh[$the_parser]['ac'] .= $data;
1180 }
1181 }
Barry Mienydd671972010-10-04 16:33:58 +02001182
Andrey Andreevc8709832012-04-04 13:43:53 +03001183 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001184
Andrey Andreevc8709832012-04-04 13:43:53 +03001185 /**
1186 * Add parameter
1187 *
1188 * @param mixed
1189 * @return void
1190 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001191 public function addParam($par)
1192 {
1193 $this->params[] = $par;
1194 }
Barry Mienydd671972010-10-04 16:33:58 +02001195
Andrey Andreevc8709832012-04-04 13:43:53 +03001196 // --------------------------------------------------------------------
1197
1198 /**
1199 * Output parameters
1200 *
1201 * @param array
1202 * @return array
1203 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001204 public function output_parameters($array = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001205 {
Barry Mienydd671972010-10-04 16:33:58 +02001206 $CI =& get_instance();
Andrey Andreeva30faf92011-12-25 18:15:34 +02001207
1208 if (is_array($array))
Derek Allard2067d1a2008-11-13 22:59:24 +00001209 {
1210 while (list($key) = each($array))
1211 {
1212 if (is_array($array[$key]))
1213 {
1214 $array[$key] = $this->output_parameters($array[$key]);
1215 }
1216 else
1217 {
Derek Jonesa9647e82010-03-02 22:59:07 -06001218 // 'bits' is for the MetaWeblog API image bits
1219 // @todo - this needs to be made more general purpose
Alex Bilbied261b1e2012-06-02 11:12:16 +01001220 $array[$key] = ($key === 'bits' OR $this->xss_clean === FALSE) ? $array[$key] : $CI->security->xss_clean($array[$key]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001221 }
1222 }
Barry Mienydd671972010-10-04 16:33:58 +02001223
Andrey Andreevc8709832012-04-04 13:43:53 +03001224 return $array;
Derek Allard2067d1a2008-11-13 22:59:24 +00001225 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001226
1227 $parameters = array();
1228
1229 for ($i = 0, $c = count($this->params); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001230 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001231 $a_param = $this->decode_message($this->params[$i]);
Barry Mienydd671972010-10-04 16:33:58 +02001232
Andrey Andreevc8709832012-04-04 13:43:53 +03001233 if (is_array($a_param))
Derek Allard2067d1a2008-11-13 22:59:24 +00001234 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001235 $parameters[] = $this->output_parameters($a_param);
1236 }
1237 else
1238 {
1239 $parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;
Barry Mienydd671972010-10-04 16:33:58 +02001240 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001241 }
Barry Mienydd671972010-10-04 16:33:58 +02001242
Derek Allard2067d1a2008-11-13 22:59:24 +00001243 return $parameters;
1244 }
Barry Mienydd671972010-10-04 16:33:58 +02001245
Andrey Andreevc8709832012-04-04 13:43:53 +03001246 // --------------------------------------------------------------------
1247
1248 /**
1249 * Decode message
1250 *
1251 * @param object
1252 * @return mixed
1253 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001254 public function decode_message($param)
Derek Allard2067d1a2008-11-13 22:59:24 +00001255 {
1256 $kind = $param->kindOf();
1257
Alex Bilbied261b1e2012-06-02 11:12:16 +01001258 if ($kind === 'scalar')
Derek Allard2067d1a2008-11-13 22:59:24 +00001259 {
1260 return $param->scalarval();
1261 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001262 elseif ($kind === 'array')
Derek Allard2067d1a2008-11-13 22:59:24 +00001263 {
1264 reset($param->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001265 $b = current($param->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001266 $arr = array();
1267
Andrey Andreevc8709832012-04-04 13:43:53 +03001268 for ($i = 0, $c = count($b); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001269 {
1270 $arr[] = $this->decode_message($param->me['array'][$i]);
1271 }
Barry Mienydd671972010-10-04 16:33:58 +02001272
Derek Allard2067d1a2008-11-13 22:59:24 +00001273 return $arr;
1274 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001275 elseif ($kind === 'struct')
Derek Allard2067d1a2008-11-13 22:59:24 +00001276 {
1277 reset($param->me['struct']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001278 $arr = array();
1279
Pascal Kriete14287f32011-02-14 13:39:34 -05001280 while (list($key,$value) = each($param->me['struct']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001281 {
1282 $arr[$key] = $this->decode_message($value);
1283 }
Barry Mienydd671972010-10-04 16:33:58 +02001284
Derek Allard2067d1a2008-11-13 22:59:24 +00001285 return $arr;
1286 }
1287 }
Barry Mienydd671972010-10-04 16:33:58 +02001288
Andrey Andreevc8709832012-04-04 13:43:53 +03001289} // END XML_RPC_Message Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001290
1291/**
1292 * XML-RPC Values class
1293 *
1294 * @category XML-RPC
Derek Jonesf4a4bd82011-10-20 12:18:42 -05001295 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +00001296 * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
1297 */
1298class XML_RPC_Values extends CI_Xmlrpc
1299{
Andrey Andreeva30faf92011-12-25 18:15:34 +02001300 public $me = array();
1301 public $mytype = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001302
Andrey Andreevc8709832012-04-04 13:43:53 +03001303 /**
1304 * Constructor
1305 *
1306 * @param mixed
1307 * @param string
1308 * @return void
1309 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001310 public function __construct($val = -1, $type = '')
Barry Mienydd671972010-10-04 16:33:58 +02001311 {
Greg Akera9263282010-11-10 15:26:43 -06001312 parent::__construct();
Barry Mienydd671972010-10-04 16:33:58 +02001313
Alex Bilbied261b1e2012-06-02 11:12:16 +01001314 if ($val !== -1 OR $type !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001315 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001316 $type = $type === '' ? 'string' : $type;
Barry Mienydd671972010-10-04 16:33:58 +02001317
Alex Bilbied261b1e2012-06-02 11:12:16 +01001318 if ($this->xmlrpcTypes[$type] === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001319 {
1320 $this->addScalar($val,$type);
1321 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001322 elseif ($this->xmlrpcTypes[$type] === 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001323 {
1324 $this->addArray($val);
1325 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001326 elseif ($this->xmlrpcTypes[$type] === 3)
Derek Allard2067d1a2008-11-13 22:59:24 +00001327 {
1328 $this->addStruct($val);
1329 }
1330 }
1331 }
1332
Andrey Andreevc8709832012-04-04 13:43:53 +03001333 // --------------------------------------------------------------------
1334
1335 /**
1336 * Add scalar value
1337 *
1338 * @param scalar
1339 * @param string
1340 * @return int
1341 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001342 public function addScalar($val, $type = 'string')
Derek Allard2067d1a2008-11-13 22:59:24 +00001343 {
1344 $typeof = $this->xmlrpcTypes[$type];
Barry Mienydd671972010-10-04 16:33:58 +02001345
Alex Bilbied261b1e2012-06-02 11:12:16 +01001346 if ($this->mytype === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001347 {
1348 echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
1349 return 0;
1350 }
Barry Mienydd671972010-10-04 16:33:58 +02001351
Alex Bilbied261b1e2012-06-02 11:12:16 +01001352 if ($typeof !== 1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001353 {
1354 echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';
1355 return 0;
1356 }
1357
Alex Bilbied261b1e2012-06-02 11:12:16 +01001358 if ($type === $this->xmlrpcBoolean)
Derek Allard2067d1a2008-11-13 22:59:24 +00001359 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001360 $val = (int) (strcasecmp($val,'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
Derek Allard2067d1a2008-11-13 22:59:24 +00001361 }
1362
Alex Bilbied261b1e2012-06-02 11:12:16 +01001363 if ($this->mytype === 2)
Derek Allard2067d1a2008-11-13 22:59:24 +00001364 {
1365 // adding to an array here
1366 $ar = $this->me['array'];
1367 $ar[] = new XML_RPC_Values($val, $type);
1368 $this->me['array'] = $ar;
1369 }
1370 else
1371 {
1372 // a scalar, so set the value and remember we're scalar
1373 $this->me[$type] = $val;
1374 $this->mytype = $typeof;
1375 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001376
Derek Allard2067d1a2008-11-13 22:59:24 +00001377 return 1;
1378 }
1379
Andrey Andreevc8709832012-04-04 13:43:53 +03001380 // --------------------------------------------------------------------
1381
1382 /**
1383 * Add array value
1384 *
1385 * @param array
1386 * @return int
1387 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001388 public function addArray($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001389 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001390 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001391 {
1392 echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
1393 return 0;
1394 }
1395
1396 $this->mytype = $this->xmlrpcTypes['array'];
1397 $this->me['array'] = $vals;
1398 return 1;
1399 }
1400
Andrey Andreevc8709832012-04-04 13:43:53 +03001401 // --------------------------------------------------------------------
1402
1403 /**
1404 * Add struct value
1405 *
1406 * @param object
1407 * @return int
1408 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001409 public function addStruct($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001410 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001411 if ($this->mytype !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001412 {
1413 echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
1414 return 0;
1415 }
1416 $this->mytype = $this->xmlrpcTypes['struct'];
1417 $this->me['struct'] = $vals;
1418 return 1;
1419 }
1420
Andrey Andreevc8709832012-04-04 13:43:53 +03001421 // --------------------------------------------------------------------
1422
1423 /**
1424 * Get value type
1425 *
1426 * @return string
1427 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001428 public function kindOf()
Derek Allard2067d1a2008-11-13 22:59:24 +00001429 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001430 switch ($this->mytype)
Derek Allard2067d1a2008-11-13 22:59:24 +00001431 {
Andrey Andreevc8709832012-04-04 13:43:53 +03001432 case 3: return 'struct';
1433 case 2: return 'array';
1434 case 1: return 'scalar';
1435 default: return 'undef';
Derek Allard2067d1a2008-11-13 22:59:24 +00001436 }
1437 }
1438
Andrey Andreevc8709832012-04-04 13:43:53 +03001439 // --------------------------------------------------------------------
1440
1441 /**
1442 * Serialize data
1443 *
1444 * @param string
1445 * @param mixed
1446 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001447 public function serializedata($typ, $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001448 {
1449 $rs = '';
Derek Jonesa9647e82010-03-02 22:59:07 -06001450
Andrey Andreevc8709832012-04-04 13:43:53 +03001451 switch ($this->xmlrpcTypes[$typ])
Derek Allard2067d1a2008-11-13 22:59:24 +00001452 {
1453 case 3:
1454 // struct
1455 $rs .= "<struct>\n";
1456 reset($val);
Pascal Kriete14287f32011-02-14 13:39:34 -05001457 while (list($key2, $val2) = each($val))
Derek Allard2067d1a2008-11-13 22:59:24 +00001458 {
Andrey Andreeva30faf92011-12-25 18:15:34 +02001459 $rs .= "<member>\n<name>{$key2}</name>\n".$this->serializeval($val2)."</member>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001460 }
1461 $rs .= '</struct>';
Andrey Andreevc8709832012-04-04 13:43:53 +03001462 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001463 case 2:
1464 // array
1465 $rs .= "<array>\n<data>\n";
Andrey Andreevc8709832012-04-04 13:43:53 +03001466 for ($i = 0, $c = count($val); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00001467 {
1468 $rs .= $this->serializeval($val[$i]);
1469 }
Andrey Andreeva30faf92011-12-25 18:15:34 +02001470 $rs .= "</data>\n</array>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001471 break;
1472 case 1:
1473 // others
1474 switch ($typ)
1475 {
1476 case $this->xmlrpcBase64:
Andrey Andreevc8709832012-04-04 13:43:53 +03001477 $rs .= '<'.$typ.'>'.base64_encode( (string) $val).'</'.$typ.">\n";
1478 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001479 case $this->xmlrpcBoolean:
Andrey Andreevc8709832012-04-04 13:43:53 +03001480 $rs .= '<'.$typ.'>'.( (bool) $val ? '1' : '0').'</'.$typ.">\n";
1481 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001482 case $this->xmlrpcString:
Andrey Andreevc8709832012-04-04 13:43:53 +03001483 $rs .= '<'.$typ.'>'.htmlspecialchars( (string) $val).'</'.$typ.">\n";
1484 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001485 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001486 $rs .= '<'.$typ.'>'.$val.'</'.$typ.">\n";
1487 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001488 }
1489 default:
Andrey Andreevc8709832012-04-04 13:43:53 +03001490 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001491 }
Andrey Andreevc8709832012-04-04 13:43:53 +03001492
Derek Allard2067d1a2008-11-13 22:59:24 +00001493 return $rs;
1494 }
1495
Andrey Andreevc8709832012-04-04 13:43:53 +03001496 // --------------------------------------------------------------------
1497
1498 /**
1499 * Serialize class
1500 *
1501 * @return string
1502 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001503 public function serialize_class()
Derek Allard2067d1a2008-11-13 22:59:24 +00001504 {
1505 return $this->serializeval($this);
1506 }
1507
Andrey Andreevc8709832012-04-04 13:43:53 +03001508 // --------------------------------------------------------------------
1509
1510 /**
1511 * Serialize value
1512 *
1513 * @param object
1514 * @return string
1515 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001516 public function serializeval($o)
Derek Allard2067d1a2008-11-13 22:59:24 +00001517 {
1518 $ar = $o->me;
1519 reset($ar);
Barry Mienydd671972010-10-04 16:33:58 +02001520
Derek Allard2067d1a2008-11-13 22:59:24 +00001521 list($typ, $val) = each($ar);
Andrey Andreeva30faf92011-12-25 18:15:34 +02001522 return "<value>\n".$this->serializedata($typ, $val)."</value>\n";
Derek Allard2067d1a2008-11-13 22:59:24 +00001523 }
Barry Mienydd671972010-10-04 16:33:58 +02001524
Andrey Andreevc8709832012-04-04 13:43:53 +03001525 // --------------------------------------------------------------------
1526
1527 /**
1528 * Scalar value
1529 *
1530 * @return mixed
1531 */
Andrey Andreeva30faf92011-12-25 18:15:34 +02001532 public function scalarval()
Derek Allard2067d1a2008-11-13 22:59:24 +00001533 {
1534 reset($this->me);
Andrey Andreevadc11752011-12-30 14:46:08 +02001535 return current($this->me);
Derek Allard2067d1a2008-11-13 22:59:24 +00001536 }
1537
Andrey Andreevc8709832012-04-04 13:43:53 +03001538 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +00001539
Andrey Andreevc8709832012-04-04 13:43:53 +03001540 /**
1541 * Encode time in ISO-8601 form.
1542 * Useful for sending time in XML-RPC
1543 *
1544 * @param int unix timestamp
1545 * @param bool
1546 * @return string
1547 */
1548 public function iso8601_encode($time, $utc = FALSE)
Barry Mienydd671972010-10-04 16:33:58 +02001549 {
Andrey Andreev62090152011-12-30 12:49:27 +02001550 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 +00001551 }
Barry Mienydd671972010-10-04 16:33:58 +02001552
Andrey Andreevc8709832012-04-04 13:43:53 +03001553} // END XML_RPC_Values Class
Derek Allard2067d1a2008-11-13 22:59:24 +00001554
1555/* End of file Xmlrpc.php */
Andrey Andreev8f50b6b2012-03-28 14:12:09 +03001556/* Location: ./system/libraries/Xmlrpc.php */