Issues (4511)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

web_interface/astpp/system/libraries/Xmlrpc.php (34 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php  if ( ! defined('BASEPATH')) {
2
	exit('No direct script access allowed');
3
}
4
/**
5
 * CodeIgniter
6
 *
7
 * An open source application development framework for PHP 5.1.6 or newer
8
 *
9
 * @package		CodeIgniter
10
 * @author		ExpressionEngine Dev Team
11
 * @copyright	Copyright (c) 2008 - 2011, EllisLab, Inc.
12
 * @license		http://codeigniter.com/user_guide/license.html
13
 * @link		http://codeigniter.com
14
 * @since		Version 1.0
15
 * @filesource
16
 */
17
18
if ( ! function_exists('xml_parser_create'))
19
{
20
	show_error('Your PHP installation does not support XML');
21
}
22
23
24
// ------------------------------------------------------------------------
25
26
/**
27
 * XML-RPC request handler class
28
 *
29
 * @package		CodeIgniter
30
 * @subpackage	Libraries
31
 * @category	XML-RPC
32
 * @author		ExpressionEngine Dev Team
33
 * @link		http://codeigniter.com/user_guide/libraries/xmlrpc.html
34
 */
35
class CI_Xmlrpc {
36
37
	var $debug = FALSE; // Debugging on or off
38
	var $xmlrpcI4 = 'i4';
39
	var $xmlrpcInt = 'int';
40
	var $xmlrpcBoolean = 'boolean';
41
	var $xmlrpcDouble	= 'double';
42
	var $xmlrpcString	= 'string';
43
	var $xmlrpcDateTime = 'dateTime.iso8601';
44
	var $xmlrpcBase64	= 'base64';
45
	var $xmlrpcArray	= 'array';
46
	var $xmlrpcStruct	= 'struct';
47
48
	var $xmlrpcTypes	= array();
49
	var $valid_parents = array();
50
	var $xmlrpcerr		= array(); // Response numbers
51
	var $xmlrpcstr		= array(); // Response strings
52
53
	var $xmlrpc_defencoding = 'UTF-8';
54
	var $xmlrpcName = 'XML-RPC for CodeIgniter';
55
	var $xmlrpcVersion		= '1.1';
56
	var $xmlrpcerruser		= 800; // Start of user errors
57
	var $xmlrpcerrxml = 100; // Start of XML Parse errors
58
	var $xmlrpc_backslash = ''; // formulate backslashes for escaping regexp
59
60
	var $client;
61
	var $method;
62
	var $data;
63
	var $message = '';
64
	var $error = ''; // Error string for request
65
	var $result;
66
	var $response = array(); // Response from remote server
67
68
	var $xss_clean = TRUE;
69
70
	//-------------------------------------
71
	//  VALUES THAT MULTIPLE CLASSES NEED
72
	//-------------------------------------
73
74
	public function __construct($config = array())
75
	{
76
		$this->xmlrpcName = $this->xmlrpcName;
77
		$this->xmlrpc_backslash = chr(92).chr(92);
78
79
		// Types for info sent back and forth
80
		$this->xmlrpcTypes = array(
81
			$this->xmlrpcI4	 		=> '1',
82
			$this->xmlrpcInt		=> '1',
83
			$this->xmlrpcBoolean	=> '1',
84
			$this->xmlrpcString		=> '1',
85
			$this->xmlrpcDouble		=> '1',
86
			$this->xmlrpcDateTime	=> '1',
87
			$this->xmlrpcBase64		=> '1',
88
			$this->xmlrpcArray		=> '2',
89
			$this->xmlrpcStruct		=> '3'
90
			);
91
92
		// Array of Valid Parents for Various XML-RPC elements
93
		$this->valid_parents = array('BOOLEAN'			=> array('VALUE'),
94
									 'I4'				=> array('VALUE'),
95
									 'INT'				=> array('VALUE'),
96
									 'STRING'			=> array('VALUE'),
97
									 'DOUBLE'			=> array('VALUE'),
98
									 'DATETIME.ISO8601'	=> array('VALUE'),
99
									 'BASE64'			=> array('VALUE'),
100
									 'ARRAY'			=> array('VALUE'),
101
									 'STRUCT'			=> array('VALUE'),
102
									 'PARAM'			=> array('PARAMS'),
103
									 'METHODNAME'		=> array('METHODCALL'),
104
									 'PARAMS'			=> array('METHODCALL', 'METHODRESPONSE'),
105
									 'MEMBER'			=> array('STRUCT'),
106
									 'NAME'				=> array('MEMBER'),
107
									 'DATA'				=> array('ARRAY'),
108
									 'FAULT'			=> array('METHODRESPONSE'),
109
									 'VALUE'			=> array('MEMBER', 'DATA', 'PARAM', 'FAULT')
110
									 );
111
112
113
		// XML-RPC Responses
114
		$this->xmlrpcerr['unknown_method'] = '1';
115
		$this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server';
116
		$this->xmlrpcerr['invalid_return'] = '2';
117
		$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.';
118
		$this->xmlrpcerr['incorrect_params'] = '3';
119
		$this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method';
120
		$this->xmlrpcerr['introspect_unknown'] = '4';
121
		$this->xmlrpcstr['introspect_unknown'] = "Cannot inspect signature for request: method unknown";
122
		$this->xmlrpcerr['http_error'] = '5';
123
		$this->xmlrpcstr['http_error'] = "Did not receive a '200 OK' response from remote server.";
124
		$this->xmlrpcerr['no_data'] = '6';
125
		$this->xmlrpcstr['no_data'] = 'No data received from server.';
126
127
		$this->initialize($config);
128
129
		log_message('debug', "XML-RPC Class Initialized");
130
	}
131
132
133
	//-------------------------------------
134
	//  Initialize Prefs
135
	//-------------------------------------
136
137
	function initialize($config = array())
138
	{
139
		if (count($config) > 0)
140
		{
141
			foreach ($config as $key => $val)
142
			{
143
				if (isset($this->$key))
144
				{
145
					$this->$key = $val;
146
				}
147
			}
148
		}
149
	}
150
	// END
151
152
	//-------------------------------------
153
	//  Take URL and parse it
154
	//-------------------------------------
155
156
	function server($url, $port = 80)
157
	{
158
		if (substr($url, 0, 4) != "http")
159
		{
160
			$url = "http://".$url;
161
		}
162
163
		$parts = parse_url($url);
164
165
		$path = ( ! isset($parts['path'])) ? '/' : $parts['path'];
166
167
		if (isset($parts['query']) && $parts['query'] != '')
168
		{
169
			$path .= '?'.$parts['query'];
170
		}
171
172
		$this->client = new XML_RPC_Client($path, $parts['host'], $port);
173
	}
174
	// END
175
176
	//-------------------------------------
177
	//  Set Timeout
178
	//-------------------------------------
179
180
	function timeout($seconds = 5)
181
	{
182
		if ( ! is_null($this->client) && is_int($seconds))
183
		{
184
			$this->client->timeout = $seconds;
185
		}
186
	}
187
	// END
188
189
	//-------------------------------------
190
	//  Set Methods
191
	//-------------------------------------
192
193
	function method($function)
194
	{
195
		$this->method = $function;
196
	}
197
	// END
198
199
	//-------------------------------------
200
	//  Take Array of Data and Create Objects
201
	//-------------------------------------
202
203
	function request($incoming)
204
	{
205
		if ( ! is_array($incoming))
0 ignored issues
show
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
206
		{
207
			// Send Error
208
		}
209
210
		$this->data = array();
211
212
		foreach ($incoming as $key => $value)
213
		{
214
			$this->data[$key] = $this->values_parsing($value);
215
		}
216
	}
217
	// END
218
219
220
	//-------------------------------------
221
	//  Set Debug
222
	//-------------------------------------
223
224
	function set_debug($flag = TRUE)
225
	{
226
		$this->debug = ($flag == TRUE) ? TRUE : FALSE;
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
227
	}
228
229
	//-------------------------------------
230
	//  Values Parsing
231
	//-------------------------------------
232
233
	function values_parsing($value, $return = FALSE)
0 ignored issues
show
The parameter $return is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
234
	{
235
		if (is_array($value) && array_key_exists(0, $value))
236
		{
237
			if ( ! isset($value['1']) OR ( ! isset($this->xmlrpcTypes[$value['1']])))
238
			{
239
				if (is_array($value[0]))
240
				{
241
					$temp = new XML_RPC_Values($value['0'], 'array');
0 ignored issues
show
$value['0'] is of type array, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
242
				} else
243
				{
244
					$temp = new XML_RPC_Values($value['0'], 'string');
245
				}
246
			} elseif (is_array($value['0']) && ($value['1'] == 'struct' OR $value['1'] == 'array'))
247
			{
248
				while (list($k) = each($value['0']))
249
				{
250
					$value['0'][$k] = $this->values_parsing($value['0'][$k], TRUE);
251
				}
252
253
				$temp = new XML_RPC_Values($value['0'], $value['1']);
0 ignored issues
show
$value['0'] is of type array, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
254
			} else
255
			{
256
				$temp = new XML_RPC_Values($value['0'], $value['1']);
257
			}
258
		} else
259
		{
260
			$temp = new XML_RPC_Values($value, 'string');
261
		}
262
263
		return $temp;
264
	}
265
	// END
266
267
268
	//-------------------------------------
269
	//  Sends XML-RPC Request
270
	//-------------------------------------
271
272
	function send_request()
273
	{
274
		$this->message = new XML_RPC_Message($this->method, $this->data);
0 ignored issues
show
$this->data is of type array, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation Bug introduced by
It seems like new \XML_RPC_Message($this->method, $this->data) of type object<XML_RPC_Message> is incompatible with the declared type string of property $message.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
275
		$this->message->debug = $this->debug;
276
277
		if ( ! $this->result = $this->client->send($this->message))
278
		{
279
			$this->error = $this->result->errstr;
280
			return FALSE;
281
		} elseif ( ! is_object($this->result->val))
282
		{
283
			$this->error = $this->result->errstr;
284
			return FALSE;
285
		}
286
287
		$this->response = $this->result->decode();
288
289
		return TRUE;
290
	}
291
	// END
292
293
	//-------------------------------------
294
	//  Returns Error
295
	//-------------------------------------
296
297
	function display_error()
298
	{
299
		return $this->error;
300
	}
301
	// END
302
303
	//-------------------------------------
304
	//  Returns Remote Server Response
305
	//-------------------------------------
306
307
	function display_response()
308
	{
309
		return $this->response;
310
	}
311
	// END
312
313
	//-------------------------------------
314
	//  Sends an Error Message for Server Request
315
	//-------------------------------------
316
317
	function send_error_message($number, $message)
318
	{
319
		return new XML_RPC_Response('0', $number, $message);
320
	}
321
	// END
322
323
324
	//-------------------------------------
325
	//  Send Response for Server Request
326
	//-------------------------------------
327
328
	function send_response($response)
329
	{
330
		// $response should be array of values, which will be parsed
331
		// based on their data and type into a valid group of XML-RPC values
332
333
		$response = $this->values_parsing($response);
334
335
		return new XML_RPC_Response($response);
336
	}
337
	// END
338
339
} // END XML_RPC Class
340
341
342
343
/**
344
 * XML-RPC Client class
345
 *
346
 * @category	XML-RPC
347
 * @author		ExpressionEngine Dev Team
348
 * @link		http://codeigniter.com/user_guide/libraries/xmlrpc.html
349
 */
350
class XML_RPC_Client extends CI_Xmlrpc
351
{
352
	var $path			= '';
353
	var $server = '';
354
	var $port			= 80;
355
	var $errno = '';
356
	var $errstring = '';
357
	var $timeout = 5;
358
	var $no_multicall = FALSE;
359
360
	public function __construct($path, $server, $port = 80)
361
	{
362
		parent::__construct();
363
364
		$this->port = $port;
365
		$this->server = $server;
366
		$this->path = $path;
367
	}
368
369
	/**
370
	 * @param XML_RPC_Message $msg
371
	 */
372
	function send($msg)
373
	{
374
		if (is_array($msg))
375
		{
376
			// Multi-call disabled
377
			$r = new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'], $this->xmlrpcstr['multicall_recursion']);
378
			return $r;
379
		}
380
381
		return $this->sendPayload($msg);
382
	}
383
384
	function sendPayload($msg)
385
	{
386
		$fp = @fsockopen($this->server, $this->port, $this->errno, $this->errstr, $this->timeout);
0 ignored issues
show
The property errstr does not seem to exist. Did you mean errstring?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
387
388
		if ( ! is_resource($fp))
389
		{
390
			error_log($this->xmlrpcstr['http_error']);
391
			$r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
392
			return $r;
393
		}
394
395
		if (empty($msg->payload))
396
		{
397
			// $msg = XML_RPC_Messages
398
			$msg->createPayload();
399
		}
400
401
		$r = "\r\n";
402
		$op  = "POST {$this->path} HTTP/1.0$r";
403
		$op .= "Host: {$this->server}$r";
404
		$op .= "Content-Type: text/xml$r";
405
		$op .= "User-Agent: {$this->xmlrpcName}$r";
406
		$op .= "Content-Length: ".strlen($msg->payload)."$r$r";
407
		$op .= $msg->payload;
408
409
410
		if ( ! fputs($fp, $op, strlen($op)))
411
		{
412
			error_log($this->xmlrpcstr['http_error']);
413
			$r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
414
			return $r;
415
		}
416
		$resp = $msg->parseResponse($fp);
417
		fclose($fp);
418
		return $resp;
419
	}
420
421
} // end class XML_RPC_Client
422
423
424
/**
425
 * XML-RPC Response class
426
 *
427
 * @category	XML-RPC
428
 * @author		ExpressionEngine Dev Team
429
 * @link		http://codeigniter.com/user_guide/libraries/xmlrpc.html
430
 */
431
class XML_RPC_Response
432
{
433
	var $val = 0;
434
	var $errno = 0;
435
	var $errstr = '';
436
	var $headers = array();
437
	var $xss_clean = TRUE;
438
439
	public function __construct($val, $code = 0, $fstr = '')
440
	{
441
		if ($code != 0)
442
		{
443
			// error
444
			$this->errno = $code;
445
			$this->errstr = htmlentities($fstr);
446
		}
447
		else if ( ! is_object($val))
448
		{
449
			// programmer error, not an object
450
			error_log("Invalid type '".gettype($val)."' (value: $val) passed to XML_RPC_Response.  Defaulting to empty value.");
451
			$this->val = new XML_RPC_Values();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \XML_RPC_Values() of type object<XML_RPC_Values> is incompatible with the declared type integer of property $val.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
452
		}
453
		else
454
		{
455
			$this->val = $val;
0 ignored issues
show
Documentation Bug introduced by
It seems like $val of type object is incompatible with the declared type integer of property $val.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
456
		}
457
	}
458
459
	function faultCode()
460
	{
461
		return $this->errno;
462
	}
463
464
	function faultString()
465
	{
466
		return $this->errstr;
467
	}
468
469
	function value()
470
	{
471
		return $this->val;
472
	}
473
474
	function prepare_response()
475
	{
476
		$result = "<methodResponse>\n";
477
		if ($this->errno)
478
		{
479
			$result .= '<fault>
480
	<value>
481
		<struct>
482
			<member>
483
				<name>faultCode</name>
484
				<value><int>' . $this->errno.'</int></value>
485
			</member>
486
			<member>
487
				<name>faultString</name>
488
				<value><string>' . $this->errstr.'</string></value>
489
			</member>
490
		</struct>
491
	</value>
492
</fault>';
493
		} else
494
		{
495
			$result .= "<params>\n<param>\n".
496
					$this->val->serialize_class().
0 ignored issues
show
The method serialize_class cannot be called on $this->val (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
497
					"</param>\n</params>";
498
		}
499
		$result .= "\n</methodResponse>";
500
		return $result;
501
	}
502
503
	function decode($array = FALSE)
504
	{
505
		$CI = & get_instance();
506
		
507
		if ($array !== FALSE && is_array($array))
508
		{
509 View Code Duplication
			while (list($key) = each($array))
510
			{
511
				if (is_array($array[$key]))
512
				{
513
					$array[$key] = $this->decode($array[$key]);
514
				} else
515
				{
516
					$array[$key] = ($this->xss_clean) ? $CI->security->xss_clean($array[$key]) : $array[$key];
0 ignored issues
show
The property security does not seem to exist in CI_Controller.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
517
				}
518
			}
519
520
			$result = $array;
521
		} else
522
		{
523
			$result = $this->xmlrpc_decoder($this->val);
524
525
			if (is_array($result))
526
			{
527
				$result = $this->decode($result);
0 ignored issues
show
$result is of type array, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
528
			} else
529
			{
530
				$result = ($this->xss_clean) ? $CI->security->xss_clean($result) : $result;
531
			}
532
		}
533
534
		return $result;
535
	}
536
537
538
539
	//-------------------------------------
540
	//  XML-RPC Object to PHP Types
541
	//-------------------------------------
542
543
	/**
544
	 * @param integer $xmlrpc_val
545
	 */
546 View Code Duplication
	function xmlrpc_decoder($xmlrpc_val)
547
	{
548
		$kind = $xmlrpc_val->kindOf();
0 ignored issues
show
The method kindOf cannot be called on $xmlrpc_val (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
549
550
		if ($kind == 'scalar')
551
		{
552
			return $xmlrpc_val->scalarval();
0 ignored issues
show
The method scalarval cannot be called on $xmlrpc_val (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
553
		} elseif ($kind == 'array')
554
		{
555
			reset($xmlrpc_val->me);
556
			list($a, $b) = each($xmlrpc_val->me);
0 ignored issues
show
The assignment to $a is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
557
			$size = count($b);
558
559
			$arr = array();
560
561
			for ($i = 0; $i < $size; $i++)
562
			{
563
				$arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);
564
			}
565
			return $arr;
566
		} elseif ($kind == 'struct')
567
		{
568
			reset($xmlrpc_val->me['struct']);
569
			$arr = array();
570
571
			while (list($key, $value) = each($xmlrpc_val->me['struct']))
572
			{
573
				$arr[$key] = $this->xmlrpc_decoder($value);
574
			}
575
			return $arr;
576
		}
577
	}
578
579
580
	//-------------------------------------
581
	//  ISO-8601 time to server or UTC time
582
	//-------------------------------------
583
584
	function iso8601_decode($time, $utc = 0)
585
	{
586
		// return a timet in the localtime, or UTC
587
		$t = 0;
588
		if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))
589
		{
590
			$fnc = ($utc == 1) ? 'gmmktime' : 'mktime';
591
			$t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
592
		}
593
		return $t;
594
	}
595
596
} // End Response Class
597
598
599
600
/**
601
 * XML-RPC Message class
602
 *
603
 * @category	XML-RPC
604
 * @author		ExpressionEngine Dev Team
605
 * @link		http://codeigniter.com/user_guide/libraries/xmlrpc.html
606
 */
607
class XML_RPC_Message extends CI_Xmlrpc
608
{
609
	var $payload;
610
	var $method_name;
611
	var $params = array();
612
	var $xh = array();
613
614
	public function __construct($method, $pars = 0)
615
	{
616
		parent::__construct();
617
618
		$this->method_name = $method;
619
		if (is_array($pars) && count($pars) > 0)
620
		{
621
			for ($i = 0; $i < count($pars); $i++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
622
			{
623
				// $pars[$i] = XML_RPC_Values
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
624
				$this->params[] = $pars[$i];
625
			}
626
		}
627
	}
628
629
	//-------------------------------------
630
	//  Create Payload to Send
631
	//-------------------------------------
632
633
	function createPayload()
634
	{
635
		$this->payload = "<?xml version=\"1.0\"?".">\r\n<methodCall>\r\n";
636
		$this->payload .= '<methodName>'.$this->method_name."</methodName>\r\n";
637
		$this->payload .= "<params>\r\n";
638
639
		for ($i = 0; $i < count($this->params); $i++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
640
		{
641
			// $p = XML_RPC_Values
642
			$p = $this->params[$i];
643
			$this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n";
644
		}
645
646
		$this->payload .= "</params>\r\n</methodCall>\r\n";
647
	}
648
649
	//-------------------------------------
650
	//  Parse External XML-RPC Server's Response
651
	//-------------------------------------
652
653
	function parseResponse($fp)
654
	{
655
		$data = '';
656
657
		while ($datum = fread($fp, 4096))
658
		{
659
			$data .= $datum;
660
		}
661
662
		//-------------------------------------
663
		//  DISPLAY HTTP CONTENT for DEBUGGING
664
		//-------------------------------------
665
666
		if ($this->debug === TRUE)
667
		{
668
			echo "<pre>";
669
			echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n";
670
			echo "</pre>";
671
		}
672
673
		//-------------------------------------
674
		//  Check for data
675
		//-------------------------------------
676
677
		if ($data == "")
678
		{
679
			error_log($this->xmlrpcstr['no_data']);
680
			$r = new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
681
			return $r;
682
		}
683
684
685
		//-------------------------------------
686
		//  Check for HTTP 200 Response
687
		//-------------------------------------
688
689
		if (strncmp($data, 'HTTP', 4) == 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
690
		{
691
			$errstr = substr($data, 0, strpos($data, "\n") - 1);
692
			$r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');
693
			return $r;
694
		}
695
696
		//-------------------------------------
697
		//  Create and Set Up XML Parser
698
		//-------------------------------------
699
700
		$parser = xml_parser_create($this->xmlrpc_defencoding);
701
702
		$this->xh[$parser] = array();
703
		$this->xh[$parser]['isf'] = 0;
704
		$this->xh[$parser]['ac'] = '';
705
		$this->xh[$parser]['headers'] = array();
706
		$this->xh[$parser]['stack'] = array();
707
		$this->xh[$parser]['valuestack']	= array();
708
		$this->xh[$parser]['isf_reason']	= 0;
709
710
		xml_set_object($parser, $this);
711
		xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
712
		xml_set_element_handler($parser, 'open_tag', 'closing_tag');
713
		xml_set_character_data_handler($parser, 'character_data');
714
		//xml_set_default_handler($parser, 'default_handler');
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
715
716
717
		//-------------------------------------
718
		//  GET HEADERS
719
		//-------------------------------------
720
721
		$lines = explode("\r\n", $data);
722
		while (($line = array_shift($lines)))
723
		{
724
			if (strlen($line) < 1)
725
			{
726
				break;
727
			}
728
			$this->xh[$parser]['headers'][] = $line;
729
		}
730
		$data = implode("\r\n", $lines);
731
732
733
		//-------------------------------------
734
		//  PARSE XML DATA
735
		//-------------------------------------
736
737
		if ( ! xml_parse($parser, $data, count($data)))
738
		{
739
			$errstr = sprintf('XML error: %s at line %d',
740
					xml_error_string(xml_get_error_code($parser)),
741
					xml_get_current_line_number($parser));
742
			//error_log($errstr);
743
			$r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
744
			xml_parser_free($parser);
745
			return $r;
746
		}
747
		xml_parser_free($parser);
748
749
		// ---------------------------------------
750
		//  Got Ourselves Some Badness, It Seems
751
		// ---------------------------------------
752
753
		if ($this->xh[$parser]['isf'] > 1)
754
		{
755
			if ($this->debug === TRUE)
756
			{
757
				echo "---Invalid Return---\n";
758
				echo $this->xh[$parser]['isf_reason'];
759
				echo "---Invalid Return---\n\n";
760
			}
761
762
			$r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
763
			return $r;
764
		} elseif ( ! is_object($this->xh[$parser]['value']))
765
		{
766
			$r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
767
			return $r;
768
		}
769
770
		//-------------------------------------
771
		//  DISPLAY XML CONTENT for DEBUGGING
772
		//-------------------------------------
773
774
		if ($this->debug === TRUE)
775
		{
776
			echo "<pre>";
777
778
			if (count($this->xh[$parser]['headers'] > 0))
779
			{
780
				echo "---HEADERS---\n";
781
				foreach ($this->xh[$parser]['headers'] as $header)
782
				{
783
					echo "$header\n";
784
				}
785
				echo "---END HEADERS---\n\n";
786
			}
787
788
			echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n";
789
790
			echo "---PARSED---\n";
791
			var_dump($this->xh[$parser]['value']);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($this->xh[$parser]['value']); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
792
			echo "\n---END PARSED---</pre>";
793
		}
794
795
		//-------------------------------------
796
		//  SEND RESPONSE
797
		//-------------------------------------
798
799
		$v = $this->xh[$parser]['value'];
800
801
		if ($this->xh[$parser]['isf'])
802
		{
803
			$errno_v = $v->me['struct']['faultCode'];
804
			$errstr_v = $v->me['struct']['faultString'];
805
			$errno = $errno_v->scalarval();
806
807
			if ($errno == 0)
808
			{
809
				// FAULT returned, errno needs to reflect that
810
				$errno = -1;
811
			}
812
813
			$r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
814
		} else
815
		{
816
			$r = new XML_RPC_Response($v);
817
		}
818
819
		$r->headers = $this->xh[$parser]['headers'];
820
		return $r;
821
	}
822
823
	// ------------------------------------
824
	//  Begin Return Message Parsing section
825
	// ------------------------------------
826
827
	// quick explanation of components:
828
	//   ac - used to accumulate values
829
	//   isf - used to indicate a fault
830
	//   lv - used to indicate "looking for a value": implements
831
	//		the logic to allow values with no types to be strings
832
	//   params - used to store parameters in method calls
833
	//   method - used to store method name
834
	//	 stack - array with parent tree of the xml element,
835
	//			 used to validate the nesting of elements
836
837
	//-------------------------------------
838
	//  Start Element Handler
839
	//-------------------------------------
840
841
	function open_tag($the_parser, $name, $attrs)
0 ignored issues
show
The parameter $attrs is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
842
	{
843
		// If invalid nesting, then return
844
		if ($this->xh[$the_parser]['isf'] > 1) {
845
			return;
846
		}
847
848
		// Evaluate and check for correct nesting of XML elements
849
850
		if (count($this->xh[$the_parser]['stack']) == 0)
851
		{
852
			if ($name != 'METHODRESPONSE' && $name != 'METHODCALL')
853
			{
854
				$this->xh[$the_parser]['isf'] = 2;
855
				$this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
856
				return;
857
			}
858
		} else
859
		{
860
			// not top level element: see if parent is OK
861
			if ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
862
			{
863
				$this->xh[$the_parser]['isf'] = 2;
864
				$this->xh[$the_parser]['isf_reason'] = "XML-RPC element $name cannot be child of ".$this->xh[$the_parser]['stack'][0];
865
				return;
866
			}
867
		}
868
869
		switch ($name)
870
		{
871
			case 'STRUCT':
872
			case 'ARRAY':
873
				// Creates array for child elements
874
875
				$cur_val = array('value' => array(),
876
								 'type'	 => $name);
877
878
				array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
879
			break;
880
			case 'METHODNAME':
881
			case 'NAME':
882
				$this->xh[$the_parser]['ac'] = '';
883
			break;
884
			case 'FAULT':
885
				$this->xh[$the_parser]['isf'] = 1;
886
			break;
887
			case 'PARAM':
888
				$this->xh[$the_parser]['value'] = NULL;
889
			break;
890
			case 'VALUE':
891
				$this->xh[$the_parser]['vt'] = 'value';
892
				$this->xh[$the_parser]['ac'] = '';
893
				$this->xh[$the_parser]['lv'] = 1;
894
			break;
895
			case 'I4':
896
			case 'INT':
897
			case 'STRING':
898
			case 'BOOLEAN':
899
			case 'DOUBLE':
900
			case 'DATETIME.ISO8601':
901
			case 'BASE64':
902
				if ($this->xh[$the_parser]['vt'] != 'value')
903
				{
904
					//two data elements inside a value: an error occurred!
905
					$this->xh[$the_parser]['isf'] = 2;
906
					$this->xh[$the_parser]['isf_reason'] = "'Twas a $name element following a ".$this->xh[$the_parser]['vt']." element inside a single value";
907
					return;
908
				}
909
910
				$this->xh[$the_parser]['ac'] = '';
911
			break;
912
			case 'MEMBER':
913
				// Set name of <member> to nothing to prevent errors later if no <name> is found
914
				$this->xh[$the_parser]['valuestack'][0]['name'] = '';
915
916
				// Set NULL value to check to see if value passed for this param/member
917
				$this->xh[$the_parser]['value'] = NULL;
918
			break;
919
			case 'DATA':
920
			case 'METHODCALL':
921
			case 'METHODRESPONSE':
922
			case 'PARAMS':
923
				// valid elements that add little to processing
924
			break;
925
			default:
926
				/// An Invalid Element is Found, so we have trouble
927
				$this->xh[$the_parser]['isf'] = 2;
928
				$this->xh[$the_parser]['isf_reason'] = "Invalid XML-RPC element found: $name";
929
			break;
930
		}
931
932
		// Add current element name to stack, to allow validation of nesting
933
		array_unshift($this->xh[$the_parser]['stack'], $name);
934
935
		if ($name != 'VALUE') {
936
			$this->xh[$the_parser]['lv'] = 0;
937
		}
938
	}
939
	// END
940
941
942
	//-------------------------------------
943
	//  End Element Handler
944
	//-------------------------------------
945
946
	function closing_tag($the_parser, $name)
947
	{
948
		if ($this->xh[$the_parser]['isf'] > 1) {
949
			return;
950
		}
951
952
		// Remove current element from stack and set variable
953
		// NOTE: If the XML validates, then we do not have to worry about
954
		// the opening and closing of elements.  Nesting is checked on the opening
955
		// tag so we be safe there as well.
956
957
		$curr_elem = array_shift($this->xh[$the_parser]['stack']);
958
959
		switch ($name)
960
		{
961
			case 'STRUCT':
962
			case 'ARRAY':
963
				$cur_val = array_shift($this->xh[$the_parser]['valuestack']);
964
				$this->xh[$the_parser]['value'] = ( ! isset($cur_val['values'])) ? array() : $cur_val['values'];
965
				$this->xh[$the_parser]['vt'] = strtolower($name);
966
			break;
967
			case 'NAME':
968
				$this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
969
			break;
970
			case 'BOOLEAN':
971
			case 'I4':
972
			case 'INT':
973
			case 'STRING':
974
			case 'DOUBLE':
975
			case 'DATETIME.ISO8601':
976
			case 'BASE64':
977
				$this->xh[$the_parser]['vt'] = strtolower($name);
978
979
				if ($name == 'STRING')
980
				{
981
					$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
982
				}
983
				elseif ($name == 'DATETIME.ISO8601')
984
				{
985
					$this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime;
986
					$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
987
				}
988
				elseif ($name == 'BASE64')
989
				{
990
					$this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
991
				}
992
				elseif ($name == 'BOOLEAN')
993
				{
994
					// Translated BOOLEAN values to TRUE AND FALSE
995
					if ($this->xh[$the_parser]['ac'] == '1')
996
					{
997
						$this->xh[$the_parser]['value'] = TRUE;
998
					}
999
					else
1000
					{
1001
						$this->xh[$the_parser]['value'] = FALSE;
1002
					}
1003
				}
1004 View Code Duplication
				elseif ($name == 'DOUBLE')
1005
				{
1006
					// we have a DOUBLE
1007
					// we must check that only 0123456789-.<space> are characters here
1008
					if ( ! preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac']))
1009
					{
1010
						$this->xh[$the_parser]['value'] = 'ERROR_NON_NUMERIC_FOUND';
1011
					}
1012
					else
1013
					{
1014
						$this->xh[$the_parser]['value'] = (double)$this->xh[$the_parser]['ac'];
1015
					}
1016
				}
1017 View Code Duplication
				else
1018
				{
1019
					// we have an I4/INT
1020
					// we must check that only 0123456789-<space> are characters here
1021
					if ( ! preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac']))
1022
					{
1023
						$this->xh[$the_parser]['value'] = 'ERROR_NON_NUMERIC_FOUND';
1024
					}
1025
					else
1026
					{
1027
						$this->xh[$the_parser]['value'] = (int)$this->xh[$the_parser]['ac'];
1028
					}
1029
				}
1030
				$this->xh[$the_parser]['ac'] = '';
1031
				$this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
1032
			break;
1033
			case 'VALUE':
1034
				// This if() detects if no scalar was inside <VALUE></VALUE>
1035 View Code Duplication
				if ($this->xh[$the_parser]['vt'] == 'value')
1036
				{
1037
					$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1038
					$this->xh[$the_parser]['vt'] = $this->xmlrpcString;
1039
				}
1040
1041
				// build the XML-RPC value out of the data received, and substitute it
1042
				$temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
1043
1044
				if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] == 'ARRAY')
1045
				{
1046
					// Array
1047
					$this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
1048
				} else
1049
				{
1050
					// Struct
1051
					$this->xh[$the_parser]['value'] = $temp;
1052
				}
1053
			break;
1054
			case 'MEMBER':
1055
				$this->xh[$the_parser]['ac'] = '';
1056
1057
				// If value add to array in the stack for the last element built
1058
				if ($this->xh[$the_parser]['value'])
1059
				{
1060
					$this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
1061
				}
1062
			break;
1063
			case 'DATA':
1064
				$this->xh[$the_parser]['ac'] = '';
1065
			break;
1066
			case 'PARAM':
1067
				if ($this->xh[$the_parser]['value'])
1068
				{
1069
					$this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
1070
				}
1071
			break;
1072
			case 'METHODNAME':
1073
				$this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
1074
			break;
1075
			case 'PARAMS':
1076
			case 'FAULT':
1077
			case 'METHODCALL':
1078
			case 'METHORESPONSE':
1079
				// We're all good kids with nuthin' to do
1080
			break;
1081
			default:
1082
				// End of an Invalid Element.  Taken care of during the opening tag though
1083
			break;
1084
		}
1085
	}
1086
1087
	//-------------------------------------
1088
	//  Parses Character Data
1089
	//-------------------------------------
1090
1091
	function character_data($the_parser, $data)
1092
	{
1093
		if ($this->xh[$the_parser]['isf'] > 1) {
1094
			return;
1095
		}
1096
		// XML Fault found already
1097
1098
		// If a value has not been found
1099
		if ($this->xh[$the_parser]['lv'] != 3)
1100
		{
1101
			if ($this->xh[$the_parser]['lv'] == 1)
1102
			{
1103
				$this->xh[$the_parser]['lv'] = 2; // Found a value
1104
			}
1105
1106
			if ( ! @isset($this->xh[$the_parser]['ac']))
1107
			{
1108
				$this->xh[$the_parser]['ac'] = '';
1109
			}
1110
1111
			$this->xh[$the_parser]['ac'] .= $data;
1112
		}
1113
	}
1114
1115
1116
	function addParam($par) { $this->params[] = $par; }
1117
1118
	function output_parameters($array = FALSE)
1119
	{
1120
		$CI = & get_instance();
1121
		
1122
		if ($array !== FALSE && is_array($array))
1123
		{
1124 View Code Duplication
			while (list($key) = each($array))
1125
			{
1126
				if (is_array($array[$key]))
1127
				{
1128
					$array[$key] = $this->output_parameters($array[$key]);
1129
				} else
1130
				{
1131
					// 'bits' is for the MetaWeblog API image bits
1132
					// @todo - this needs to be made more general purpose
1133
					$array[$key] = ($key == 'bits' OR $this->xss_clean == FALSE) ? $array[$key] : $CI->security->xss_clean($array[$key]);
0 ignored issues
show
The property security does not seem to exist in CI_Controller.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1134
				}
1135
			}
1136
1137
			$parameters = $array;
1138
		} else
1139
		{
1140
			$parameters = array();
1141
1142
			for ($i = 0; $i < count($this->params); $i++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1143
			{
1144
				$a_param = $this->decode_message($this->params[$i]);
1145
1146
				if (is_array($a_param))
1147
				{
1148
					$parameters[] = $this->output_parameters($a_param);
0 ignored issues
show
$a_param is of type array, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1149
				} else
1150
				{
1151
					$parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;
1152
				}
1153
			}
1154
		}
1155
1156
		return $parameters;
1157
	}
1158
1159
1160 View Code Duplication
	function decode_message($param)
1161
	{
1162
		$kind = $param->kindOf();
1163
1164
		if ($kind == 'scalar')
1165
		{
1166
			return $param->scalarval();
1167
		} elseif ($kind == 'array')
1168
		{
1169
			reset($param->me);
1170
			list($a, $b) = each($param->me);
0 ignored issues
show
The assignment to $a is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
1171
1172
			$arr = array();
1173
1174
			for ($i = 0; $i < count($b); $i++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1175
			{
1176
				$arr[] = $this->decode_message($param->me['array'][$i]);
1177
			}
1178
1179
			return $arr;
1180
		} elseif ($kind == 'struct')
1181
		{
1182
			reset($param->me['struct']);
1183
1184
			$arr = array();
1185
1186
			while (list($key, $value) = each($param->me['struct']))
1187
			{
1188
				$arr[$key] = $this->decode_message($value);
1189
			}
1190
1191
			return $arr;
1192
		}
1193
	}
1194
1195
} // End XML_RPC_Messages class
1196
1197
1198
1199
/**
1200
 * XML-RPC Values class
1201
 *
1202
 * @category	XML-RPC
1203
 * @author		ExpressionEngine Dev Team
1204
 * @link		http://codeigniter.com/user_guide/libraries/xmlrpc.html
1205
 */
1206
class XML_RPC_Values extends CI_Xmlrpc
1207
{
1208
	var $me = array();
1209
	var $mytype = 0;
1210
1211
	public function __construct($val = -1, $type = '')
1212
	{
1213
		parent::__construct();
1214
1215
		if ($val != -1 OR $type != '')
1216
		{
1217
			$type = $type == '' ? 'string' : $type;
1218
1219
			if ($this->xmlrpcTypes[$type] == 1)
1220
			{
1221
				$this->addScalar($val, $type);
1222
			}
1223
			elseif ($this->xmlrpcTypes[$type] == 2)
1224
			{
1225
				$this->addArray($val);
1226
			}
1227
			elseif ($this->xmlrpcTypes[$type] == 3)
1228
			{
1229
				$this->addStruct($val);
1230
			}
1231
		}
1232
	}
1233
1234
	/**
1235
	 * @param integer $val
1236
	 */
1237
	function addScalar($val, $type='string')
1238
	{
1239
		$typeof = $this->xmlrpcTypes[$type];
1240
1241
		if ($this->mytype==1)
1242
		{
1243
			echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
1244
			return 0;
1245
		}
1246
1247
		if ($typeof != 1)
1248
		{
1249
			echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';
1250
			return 0;
1251
		}
1252
1253
		if ($type == $this->xmlrpcBoolean)
1254
		{
1255
			if (strcasecmp($val, 'true') == 0 OR $val == 1 OR ($val == true && strcasecmp($val, 'false')))
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $val of type integer to the boolean true. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
1256
			{
1257
				$val = 1;
1258
			} else
1259
			{
1260
				$val = 0;
1261
			}
1262
		}
1263
1264
		if ($this->mytype == 2)
1265
		{
1266
			// adding to an array here
1267
			$ar = $this->me['array'];
1268
			$ar[] = new XML_RPC_Values($val, $type);
1269
			$this->me['array'] = $ar;
1270
		} else
1271
		{
1272
			// a scalar, so set the value and remember we're scalar
1273
			$this->me[$type] = $val;
1274
			$this->mytype = $typeof;
1275
		}
1276
		return 1;
1277
	}
1278
1279 View Code Duplication
	function addArray($vals)
1280
	{
1281
		if ($this->mytype != 0)
1282
		{
1283
			echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
1284
			return 0;
1285
		}
1286
1287
		$this->mytype = $this->xmlrpcTypes['array'];
1288
		$this->me['array'] = $vals;
1289
		return 1;
1290
	}
1291
1292
	/**
1293
	 * @param integer $vals
1294
	 */
1295 View Code Duplication
	function addStruct($vals)
1296
	{
1297
		if ($this->mytype != 0)
1298
		{
1299
			echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
1300
			return 0;
1301
		}
1302
		$this->mytype = $this->xmlrpcTypes['struct'];
1303
		$this->me['struct'] = $vals;
1304
		return 1;
1305
	}
1306
1307
	function kindOf()
1308
	{
1309
		switch ($this->mytype)
1310
		{
1311
			case 3:
1312
				return 'struct';
1313
				break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1314
			case 2:
1315
				return 'array';
1316
				break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1317
			case 1:
1318
				return 'scalar';
1319
				break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1320
			default:
1321
				return 'undef';
1322
		}
1323
	}
1324
1325
	function serializedata($typ, $val)
1326
	{
1327
		$rs = '';
1328
1329
		switch ($this->xmlrpcTypes[$typ])
1330
		{
1331
			case 3:
1332
				// struct
1333
				$rs .= "<struct>\n";
1334
				reset($val);
1335
				while (list($key2, $val2) = each($val))
1336
				{
1337
					$rs .= "<member>\n<name>{$key2}</name>\n";
1338
					$rs .= $this->serializeval($val2);
1339
					$rs .= "</member>\n";
1340
				}
1341
				$rs .= '</struct>';
1342
			break;
1343
			case 2:
1344
				// array
1345
				$rs .= "<array>\n<data>\n";
1346
				for ($i = 0; $i < count($val); $i++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1347
				{
1348
					$rs .= $this->serializeval($val[$i]);
1349
				}
1350
				$rs .= "</data>\n</array>\n";
1351
				break;
1352
			case 1:
1353
				// others
1354
				switch ($typ)
1355
				{
1356
					case $this->xmlrpcBase64:
1357
						$rs .= "<{$typ}>".base64_encode((string)$val)."</{$typ}>\n";
1358
					break;
1359
					case $this->xmlrpcBoolean:
1360
						$rs .= "<{$typ}>".((bool)$val ? '1' : '0')."</{$typ}>\n";
1361
					break;
1362
					case $this->xmlrpcString:
1363
						$rs .= "<{$typ}>".htmlspecialchars((string)$val)."</{$typ}>\n";
1364
					break;
1365
					default:
1366
						$rs .= "<{$typ}>{$val}</{$typ}>\n";
1367
					break;
1368
				}
1369
			default:
1370
			break;
1371
		}
1372
		return $rs;
1373
	}
1374
1375
	function serialize_class()
1376
	{
1377
		return $this->serializeval($this);
1378
	}
1379
1380
	function serializeval($o)
1381
	{
1382
		$ar = $o->me;
1383
		reset($ar);
1384
1385
		list($typ, $val) = each($ar);
1386
		$rs = "<value>\n".$this->serializedata($typ, $val)."</value>\n";
1387
		return $rs;
1388
	}
1389
1390
	function scalarval()
1391
	{
1392
		reset($this->me);
1393
		list($a, $b) = each($this->me);
0 ignored issues
show
The assignment to $a is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
1394
		return $b;
1395
	}
1396
1397
1398
	//-------------------------------------
1399
	// Encode time in ISO-8601 form.
1400
	//-------------------------------------
1401
1402
	// Useful for sending time in XML-RPC
1403
1404
	function iso8601_encode($time, $utc = 0)
1405
	{
1406
		if ($utc == 1)
1407
		{
1408
			$t = strftime("%Y%m%dT%H:%i:%s", $time);
1409
		} else
1410
		{
1411
			if (function_exists('gmstrftime')) {
1412
							$t = gmstrftime("%Y%m%dT%H:%i:%s", $time);
1413
			} else {
1414
							$t = strftime("%Y%m%dT%H:%i:%s", $time - date('Z'));
1415
			}
1416
		}
1417
		return $t;
1418
	}
1419
1420
}
1421
// END XML_RPC_Values Class
1422
1423
/* End of file Xmlrpc.php */
1424
/* Location: ./system/libraries/Xmlrpc.php */