GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (423)

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.

system/libraries/Xmlrpc.php (11 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
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 56 and the first side effect is on line 38.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * CodeIgniter
4
 *
5
 * An open source application development framework for PHP
6
 *
7
 * This content is released under the MIT License (MIT)
8
 *
9
 * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a copy
12
 * of this software and associated documentation files (the "Software"), to deal
13
 * in the Software without restriction, including without limitation the rights
14
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
 * copies of the Software, and to permit persons to whom the Software is
16
 * furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies or substantial portions of the Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
 * THE SOFTWARE.
28
 *
29
 * @package	CodeIgniter
30
 * @author	EllisLab Dev Team
31
 * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
32
 * @copyright	Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
33
 * @license	http://opensource.org/licenses/MIT	MIT License
34
 * @link	http://codeigniter.com
35
 * @since	Version 1.0.0
36
 * @filesource
37
 */
38
defined('BASEPATH') OR exit('No direct script access allowed');
39
40
if ( ! function_exists('xml_parser_create'))
41
{
42
	show_error('Your PHP installation does not support XML');
43
}
44
45
// ------------------------------------------------------------------------
46
47
/**
48
 * XML-RPC request handler class
49
 *
50
 * @package		CodeIgniter
51
 * @subpackage	Libraries
52
 * @category	XML-RPC
53
 * @author		EllisLab Dev Team
54
 * @link		http://codeigniter.com/user_guide/libraries/xmlrpc.html
55
 */
56
class CI_Xmlrpc {
57
58
	/**
59
	 * Debug flag
60
	 *
61
	 * @var	bool
62
	 */
63
	public $debug		= FALSE;
64
65
	/**
66
	 * I4 data type
67
	 *
68
	 * @var	string
69
	 */
70
	public $xmlrpcI4	= 'i4';
71
72
	/**
73
	 * Integer data type
74
	 *
75
	 * @var	string
76
	 */
77
	public $xmlrpcInt	= 'int';
78
79
	/**
80
	 * Boolean data type
81
	 *
82
	 * @var	string
83
	 */
84
	public $xmlrpcBoolean	= 'boolean';
85
86
	/**
87
	 * Double data type
88
	 *
89
	 * @var	string
90
	 */
91
	public $xmlrpcDouble	= 'double';
92
93
	/**
94
	 * String data type
95
	 *
96
	 * @var	string
97
	 */
98
	public $xmlrpcString	= 'string';
99
100
	/**
101
	 * DateTime format
102
	 *
103
	 * @var	string
104
	 */
105
	public $xmlrpcDateTime	= 'dateTime.iso8601';
106
107
	/**
108
	 * Base64 data type
109
	 *
110
	 * @var	string
111
	 */
112
	public $xmlrpcBase64	= 'base64';
113
114
	/**
115
	 * Array data type
116
	 *
117
	 * @var	string
118
	 */
119
	public $xmlrpcArray	= 'array';
120
121
	/**
122
	 * Struct data type
123
	 *
124
	 * @var	string
125
	 */
126
	public $xmlrpcStruct	= 'struct';
127
128
	/**
129
	 * Data types list
130
	 *
131
	 * @var	array
132
	 */
133
	public $xmlrpcTypes	= array();
134
135
	/**
136
	 * Valid parents list
137
	 *
138
	 * @var	array
139
	 */
140
	public $valid_parents	= array();
141
142
	/**
143
	 * Response error numbers list
144
	 *
145
	 * @var	array
146
	 */
147
	public $xmlrpcerr		= array();
148
149
	/**
150
	 * Response error messages list
151
	 *
152
	 * @var	string[]
153
	 */
154
	public $xmlrpcstr		= array();
155
156
	/**
157
	 * Encoding charset
158
	 *
159
	 * @var	string
160
	 */
161
	public $xmlrpc_defencoding	= 'UTF-8';
162
163
	/**
164
	 * XML-RPC client name
165
	 *
166
	 * @var	string
167
	 */
168
	public $xmlrpcName		= 'XML-RPC for CodeIgniter';
169
170
	/**
171
	 * XML-RPC version
172
	 *
173
	 * @var	string
174
	 */
175
	public $xmlrpcVersion		= '1.1';
176
177
	/**
178
	 * Start of user errors
179
	 *
180
	 * @var	int
181
	 */
182
	public $xmlrpcerruser		= 800;
183
184
	/**
185
	 * Start of XML parse errors
186
	 *
187
	 * @var	int
188
	 */
189
	public $xmlrpcerrxml		= 100;
190
191
	/**
192
	 * Backslash replacement value
193
	 *
194
	 * @var	string
195
	 */
196
	public $xmlrpc_backslash	= '';
197
198
	/**
199
	 * XML-RPC Client object
200
	 *
201
	 * @var	object
202
	 */
203
	public $client;
204
205
	/**
206
	 * XML-RPC Method name
207
	 *
208
	 * @var	string
209
	 */
210
	public $method;
211
212
	/**
213
	 * XML-RPC Data
214
	 *
215
	 * @var	array
216
	 */
217
	public $data;
218
219
	/**
220
	 * XML-RPC Message
221
	 *
222
	 * @var	string
223
	 */
224
	public $message			= '';
225
226
	/**
227
	 * Request error message
228
	 *
229
	 * @var	string
230
	 */
231
	public $error			= '';
232
233
	/**
234
	 * XML-RPC result object
235
	 *
236
	 * @var	object
237
	 */
238
	public $result;
239
240
	/**
241
	 * XML-RPC Reponse
242
	 *
243
	 * @var	array
244
	 */
245
	public $response		= array(); // Response from remote server
246
247
	/**
248
	 * XSS Filter flag
249
	 *
250
	 * @var	bool
251
	 */
252
	public $xss_clean		= TRUE;
253
254
	// --------------------------------------------------------------------
255
256
	/**
257
	 * Constructor
258
	 *
259
	 * Initializes property default values
260
	 *
261
	 * @param	array	$config
262
	 * @return	void
263
	 */
264
	public function __construct($config = array())
265
	{
266
		$this->xmlrpc_backslash = chr(92).chr(92);
267
268
		// Types for info sent back and forth
269
		$this->xmlrpcTypes = array(
270
			$this->xmlrpcI4	 		=> '1',
271
			$this->xmlrpcInt		=> '1',
272
			$this->xmlrpcBoolean	=> '1',
273
			$this->xmlrpcString		=> '1',
274
			$this->xmlrpcDouble		=> '1',
275
			$this->xmlrpcDateTime	=> '1',
276
			$this->xmlrpcBase64		=> '1',
277
			$this->xmlrpcArray		=> '2',
278
			$this->xmlrpcStruct		=> '3'
279
		);
280
281
		// Array of Valid Parents for Various XML-RPC elements
282
		$this->valid_parents = array('BOOLEAN' => array('VALUE'),
283
			'I4'				=> array('VALUE'),
284
			'INT'				=> array('VALUE'),
285
			'STRING'			=> array('VALUE'),
286
			'DOUBLE'			=> array('VALUE'),
287
			'DATETIME.ISO8601'	=> array('VALUE'),
288
			'BASE64'			=> array('VALUE'),
289
			'ARRAY'			=> array('VALUE'),
290
			'STRUCT'			=> array('VALUE'),
291
			'PARAM'			=> array('PARAMS'),
292
			'METHODNAME'		=> array('METHODCALL'),
293
			'PARAMS'			=> array('METHODCALL', 'METHODRESPONSE'),
294
			'MEMBER'			=> array('STRUCT'),
295
			'NAME'				=> array('MEMBER'),
296
			'DATA'				=> array('ARRAY'),
297
			'FAULT'			=> array('METHODRESPONSE'),
298
			'VALUE'			=> array('MEMBER', 'DATA', 'PARAM', 'FAULT')
299
		);
300
301
		// XML-RPC Responses
302
		$this->xmlrpcerr['unknown_method'] = '1';
303
		$this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server';
304
		$this->xmlrpcerr['invalid_return'] = '2';
305
		$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.';
306
		$this->xmlrpcerr['incorrect_params'] = '3';
307
		$this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method';
308
		$this->xmlrpcerr['introspect_unknown'] = '4';
309
		$this->xmlrpcstr['introspect_unknown'] = 'Cannot inspect signature for request: method unknown';
310
		$this->xmlrpcerr['http_error'] = '5';
311
		$this->xmlrpcstr['http_error'] = "Did not receive a '200 OK' response from remote server.";
312
		$this->xmlrpcerr['no_data'] = '6';
313
		$this->xmlrpcstr['no_data'] = 'No data received from server.';
314
315
		$this->initialize($config);
316
317
		log_message('info', 'XML-RPC Class Initialized');
318
	}
319
320
	// --------------------------------------------------------------------
321
322
	/**
323
	 * Initialize
324
	 *
325
	 * @param	array	$config
326
	 * @return	void
327
	 */
328
	public function initialize($config = array())
329
	{
330
		if (count($config) > 0)
331
		{
332
			foreach ($config as $key => $val)
333
			{
334
				if (isset($this->$key))
335
				{
336
					$this->$key = $val;
337
				}
338
			}
339
		}
340
	}
341
342
	// --------------------------------------------------------------------
343
344
	/**
345
	 * Parse server URL
346
	 *
347
	 * @param	string	$url
348
	 * @param	int	$port
349
	 * @param	string	$proxy
350
	 * @param	int	$proxy_port
351
	 * @return	void
352
	 */
353
	public function server($url, $port = 80, $proxy = FALSE, $proxy_port = 8080)
354
	{
355
		if (strpos($url, 'http') !== 0)
356
		{
357
			$url = 'http://'.$url;
358
		}
359
360
		$parts = parse_url($url);
361
362
		if (isset($parts['user'], $parts['pass']))
363
		{
364
			$parts['host'] = $parts['user'].':'.$parts['pass'].'@'.$parts['host'];
365
		}
366
367
		$path = isset($parts['path']) ? $parts['path'] : '/';
368
369
		if ( ! empty($parts['query']))
370
		{
371
			$path .= '?'.$parts['query'];
372
		}
373
374
		$this->client = new XML_RPC_Client($path, $parts['host'], $port, $proxy, $proxy_port);
375
	}
376
377
	// --------------------------------------------------------------------
378
379
	/**
380
	 * Set Timeout
381
	 *
382
	 * @param	int	$seconds
383
	 * @return	void
384
	 */
385
	public function timeout($seconds = 5)
386
	{
387
		if ($this->client !== NULL && is_int($seconds))
388
		{
389
			$this->client->timeout = $seconds;
390
		}
391
	}
392
393
	// --------------------------------------------------------------------
394
395
	/**
396
	 * Set Methods
397
	 *
398
	 * @param	string	$function	Method name
399
	 * @return	void
400
	 */
401
	public function method($function)
402
	{
403
		$this->method = $function;
404
	}
405
406
	// --------------------------------------------------------------------
407
408
	/**
409
	 * Take Array of Data and Create Objects
410
	 *
411
	 * @param	array	$incoming
412
	 * @return	void
413
	 */
414
	public function request($incoming)
415
	{
416
		if ( ! is_array($incoming))
417
		{
418
			// Send Error
419
			return;
420
		}
421
422
		$this->data = array();
423
424
		foreach ($incoming as $key => $value)
425
		{
426
			$this->data[$key] = $this->values_parsing($value);
427
		}
428
	}
429
430
	// --------------------------------------------------------------------
431
432
	/**
433
	 * Set Debug
434
	 *
435
	 * @param	bool	$flag
436
	 * @return	void
437
	 */
438
	public function set_debug($flag = TRUE)
439
	{
440
		$this->debug = ($flag === TRUE);
441
	}
442
443
	// --------------------------------------------------------------------
444
445
	/**
446
	 * Values Parsing
447
	 *
448
	 * @param	mixed	$value
449
	 * @return	object
450
	 */
451
	public function values_parsing($value)
452
	{
453
		if (is_array($value) && array_key_exists(0, $value))
454
		{
455
			if ( ! isset($value[1], $this->xmlrpcTypes[$value[1]]))
456
			{
457
				$temp = new XML_RPC_Values($value[0], (is_array($value[0]) ? 'array' : 'string'));
458
			}
459
			else
460
			{
461
				if (is_array($value[0]) && ($value[1] === 'struct' OR $value[1] === 'array'))
462
				{
463
					while (list($k) = each($value[0]))
464
					{
465
						$value[0][$k] = $this->values_parsing($value[0][$k]);
466
					}
467
				}
468
469
				$temp = new XML_RPC_Values($value[0], $value[1]);
470
			}
471
		}
472
		else
473
		{
474
			$temp = new XML_RPC_Values($value, 'string');
475
		}
476
477
		return $temp;
478
	}
479
480
	// --------------------------------------------------------------------
481
482
	/**
483
	 * Sends XML-RPC Request
484
	 *
485
	 * @return	bool
486
	 */
487
	public function send_request()
488
	{
489
		$this->message = new XML_RPC_Message($this->method, $this->data);
490
		$this->message->debug = $this->debug;
491
492
		if ( ! $this->result = $this->client->send($this->message) OR ! is_object($this->result->val))
493
		{
494
			$this->error = $this->result->errstr;
495
			return FALSE;
496
		}
497
498
		$this->response = $this->result->decode();
499
		return TRUE;
500
	}
501
502
	// --------------------------------------------------------------------
503
504
	/**
505
	 * Returns Error
506
	 *
507
	 * @return	string
508
	 */
509
	public function display_error()
510
	{
511
		return $this->error;
512
	}
513
514
	// --------------------------------------------------------------------
515
516
	/**
517
	 * Returns Remote Server Response
518
	 *
519
	 * @return	string
520
	 */
521
	public function display_response()
522
	{
523
		return $this->response;
524
	}
525
526
	// --------------------------------------------------------------------
527
528
	/**
529
	 * Sends an Error Message for Server Request
530
	 *
531
	 * @param	int	$number
532
	 * @param	string	$message
533
	 * @return	object
534
	 */
535
	public function send_error_message($number, $message)
536
	{
537
		return new XML_RPC_Response(0, $number, $message);
538
	}
539
540
	// --------------------------------------------------------------------
541
542
	/**
543
	 * Send Response for Server Request
544
	 *
545
	 * @param	array	$response
546
	 * @return	object
547
	 */
548
	public function send_response($response)
549
	{
550
		// $response should be array of values, which will be parsed
551
		// based on their data and type into a valid group of XML-RPC values
552
		return new XML_RPC_Response($this->values_parsing($response));
553
	}
554
555
} // END XML_RPC Class
556
557
/**
558
 * XML-RPC Client class
559
 *
560
 * @category	XML-RPC
561
 * @author		EllisLab Dev Team
562
 * @link		http://codeigniter.com/user_guide/libraries/xmlrpc.html
563
 */
564
class XML_RPC_Client extends CI_Xmlrpc
565
{
566
	/**
567
	 * Path
568
	 *
569
	 * @var	string
570
	 */
571
	public $path			= '';
572
573
	/**
574
	 * Server hostname
575
	 *
576
	 * @var	string
577
	 */
578
	public $server			= '';
579
580
	/**
581
	 * Server port
582
	 *
583
	 * @var	int
584
	 */
585
	public $port			= 80;
586
587
	/**
588
	 *
589
	 * Server username
590
	 *
591
	 * @var	string
592
	 */
593
	public $username;
594
595
	/**
596
	 * Server password
597
	 *
598
	 * @var	string
599
	 */
600
	public $password;
601
602
	/**
603
	 * Proxy hostname
604
	 *
605
	 * @var	string
606
	 */
607
	public $proxy			= FALSE;
608
609
	/**
610
	 * Proxy port
611
	 *
612
	 * @var	int
613
	 */
614
	public $proxy_port		= 8080;
615
616
	/**
617
	 * Error number
618
	 *
619
	 * @var	string
620
	 */
621
	public $errno			= '';
622
623
	/**
624
	 * Error message
625
	 *
626
	 * @var	string
627
	 */
628
	public $errstring		= '';
629
630
	/**
631
	 * Timeout in seconds
632
	 *
633
	 * @var	int
634
	 */
635
	public $timeout		= 5;
636
637
	/**
638
	 * No Multicall flag
639
	 *
640
	 * @var	bool
641
	 */
642
	public $no_multicall	= FALSE;
643
644
	// --------------------------------------------------------------------
645
646
	/**
647
	 * Constructor
648
	 *
649
	 * @param	string	$path
650
	 * @param	object	$server
651
	 * @param	int	$port
652
	 * @param	string	$proxy
653
	 * @param	int	$proxy_port
654
	 * @return	void
655
	 */
656
	public function __construct($path, $server, $port = 80, $proxy = FALSE, $proxy_port = 8080)
657
	{
658
		parent::__construct();
659
660
		$url = parse_url('http://'.$server);
661
662
		if (isset($url['user'], $url['pass']))
663
		{
664
			$this->username = $url['user'];
665
			$this->password = $url['pass'];
666
		}
667
668
		$this->port = $port;
669
		$this->server = $url['host'];
670
		$this->path = $path;
671
		$this->proxy = $proxy;
672
		$this->proxy_port = $proxy_port;
673
	}
674
675
	// --------------------------------------------------------------------
676
677
	/**
678
	 * Send message
679
	 *
680
	 * @param	mixed	$msg
681
	 * @return	object
682
	 */
683
	public function send($msg)
684
	{
685
		if (is_array($msg))
686
		{
687
			// Multi-call disabled
688
			return new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'], $this->xmlrpcstr['multicall_recursion']);
689
		}
690
691
		return $this->sendPayload($msg);
692
	}
693
694
	// --------------------------------------------------------------------
695
696
	/**
697
	 * Send payload
698
	 *
699
	 * @param	object	$msg
700
	 * @return	object
701
	 */
702
	public function sendPayload($msg)
703
	{
704
		if ($this->proxy === FALSE)
705
		{
706
			$server = $this->server;
707
			$port = $this->port;
708
		}
709
		else
710
		{
711
			$server = $this->proxy;
712
			$port = $this->proxy_port;
713
		}
714
715
		$fp = @fsockopen($server, $port, $this->errno, $this->errstring, $this->timeout);
716
717
		if ( ! is_resource($fp))
718
		{
719
			error_log($this->xmlrpcstr['http_error']);
720
			return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
721
		}
722
723
		if (empty($msg->payload))
724
		{
725
			// $msg = XML_RPC_Messages
726
			$msg->createPayload();
727
		}
728
729
		$r = "\r\n";
730
		$op = 'POST '.$this->path.' HTTP/1.0'.$r
731
			.'Host: '.$this->server.$r
732
			.'Content-Type: text/xml'.$r
733
			.(isset($this->username, $this->password) ? 'Authorization: Basic '.base64_encode($this->username.':'.$this->password).$r : '')
734
			.'User-Agent: '.$this->xmlrpcName.$r
735
			.'Content-Length: '.strlen($msg->payload).$r.$r
736
			.$msg->payload;
737
738 View Code Duplication
		for ($written = $timestamp = 0, $length = strlen($op); $written < $length; $written += $result)
739
		{
740
			if (($result = fwrite($fp, substr($op, $written))) === FALSE)
741
			{
742
				break;
743
			}
744
			// See https://bugs.php.net/bug.php?id=39598 and http://php.net/manual/en/function.fwrite.php#96951
745
			elseif ($result === 0)
746
			{
747
				if ($timestamp === 0)
748
				{
749
					$timestamp = time();
750
				}
751
				elseif ($timestamp < (time() - $this->timeout))
752
				{
753
					$result = FALSE;
754
					break;
755
				}
756
757
				usleep(250000);
758
				continue;
759
			}
760
			else
761
			{
762
				$timestamp = 0;
763
			}
764
		}
765
766
		if ($result === FALSE)
767
		{
768
			error_log($this->xmlrpcstr['http_error']);
769
			return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
770
		}
771
772
		$resp = $msg->parseResponse($fp);
773
		fclose($fp);
774
		return $resp;
775
	}
776
777
} // END XML_RPC_Client Class
778
779
/**
780
 * XML-RPC Response class
781
 *
782
 * @category	XML-RPC
783
 * @author		EllisLab Dev Team
784
 * @link		http://codeigniter.com/user_guide/libraries/xmlrpc.html
785
 */
786
class XML_RPC_Response
787
{
788
789
	/**
790
	 * Value
791
	 *
792
	 * @var	mixed
793
	 */
794
	public $val		= 0;
795
796
	/**
797
	 * Error number
798
	 *
799
	 * @var	int
800
	 */
801
	public $errno		= 0;
802
803
	/**
804
	 * Error message
805
	 *
806
	 * @var	string
807
	 */
808
	public $errstr		= '';
809
810
	/**
811
	 * Headers list
812
	 *
813
	 * @var	array
814
	 */
815
	public $headers		= array();
816
817
	/**
818
	 * XSS Filter flag
819
	 *
820
	 * @var	bool
821
	 */
822
	public $xss_clean	= TRUE;
823
824
	// --------------------------------------------------------------------
825
826
	/**
827
	 * Constructor
828
	 *
829
	 * @param	mixed	$val
830
	 * @param	int	$code
831
	 * @param	string	$fstr
832
	 * @return	void
833
	 */
834
	public function __construct($val, $code = 0, $fstr = '')
835
	{
836
		if ($code !== 0)
837
		{
838
			// error
839
			$this->errno = $code;
840
			$this->errstr = htmlspecialchars($fstr,
841
							(is_php('5.4') ? ENT_XML1 | ENT_NOQUOTES : ENT_NOQUOTES),
842
							'UTF-8');
843
		}
844
		elseif ( ! is_object($val))
845
		{
846
			// programmer error, not an object
847
			error_log("Invalid type '".gettype($val)."' (value: ".$val.') passed to XML_RPC_Response. Defaulting to empty value.');
848
			$this->val = new XML_RPC_Values();
849
		}
850
		else
851
		{
852
			$this->val = $val;
853
		}
854
	}
855
856
	// --------------------------------------------------------------------
857
858
	/**
859
	 * Fault code
860
	 *
861
	 * @return	int
862
	 */
863
	public function faultCode()
864
	{
865
		return $this->errno;
866
	}
867
868
	// --------------------------------------------------------------------
869
870
	/**
871
	 * Fault string
872
	 *
873
	 * @return	string
874
	 */
875
	public function faultString()
876
	{
877
		return $this->errstr;
878
	}
879
880
	// --------------------------------------------------------------------
881
882
	/**
883
	 * Value
884
	 *
885
	 * @return	mixed
886
	 */
887
	public function value()
888
	{
889
		return $this->val;
890
	}
891
892
	// --------------------------------------------------------------------
893
894
	/**
895
	 * Prepare response
896
	 *
897
	 * @return	string	xml
898
	 */
899
	public function prepare_response()
900
	{
901
		return "<methodResponse>\n"
902
			.($this->errno
903
				? '<fault>
904
	<value>
905
		<struct>
906
			<member>
907
				<name>faultCode</name>
908
				<value><int>'.$this->errno.'</int></value>
909
			</member>
910
			<member>
911
				<name>faultString</name>
912
				<value><string>'.$this->errstr.'</string></value>
913
			</member>
914
		</struct>
915
	</value>
916
</fault>'
917
				: "<params>\n<param>\n".$this->val->serialize_class()."</param>\n</params>")
918
			."\n</methodResponse>";
919
	}
920
921
	// --------------------------------------------------------------------
922
923
	/**
924
	 * Decode
925
	 *
926
	 * @param	mixed	$array
927
	 * @return	array
928
	 */
929
	public function decode($array = NULL)
930
	{
931
		$CI =& get_instance();
932
933 View Code Duplication
		if (is_array($array))
934
		{
935
			while (list($key) = each($array))
936
			{
937
				if (is_array($array[$key]))
938
				{
939
					$array[$key] = $this->decode($array[$key]);
940
				}
941
				elseif ($this->xss_clean)
942
				{
943
					$array[$key] = $CI->security->xss_clean($array[$key]);
944
				}
945
			}
946
947
			return $array;
948
		}
949
950
		$result = $this->xmlrpc_decoder($this->val);
951
952
		if (is_array($result))
953
		{
954
			$result = $this->decode($result);
955
		}
956
		elseif ($this->xss_clean)
957
		{
958
			$result = $CI->security->xss_clean($result);
959
		}
960
961
		return $result;
962
	}
963
964
	// --------------------------------------------------------------------
965
966
	/**
967
	 * XML-RPC Object to PHP Types
968
	 *
969
	 * @param	object
970
	 * @return	array
971
	 */
972 View Code Duplication
	public function xmlrpc_decoder($xmlrpc_val)
973
	{
974
		$kind = $xmlrpc_val->kindOf();
975
976
		if ($kind === 'scalar')
977
		{
978
			return $xmlrpc_val->scalarval();
979
		}
980
		elseif ($kind === 'array')
981
		{
982
			reset($xmlrpc_val->me);
983
			$b = current($xmlrpc_val->me);
984
			$arr = array();
985
986
			for ($i = 0, $size = count($b); $i < $size; $i++)
987
			{
988
				$arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);
989
			}
990
			return $arr;
991
		}
992
		elseif ($kind === 'struct')
993
		{
994
			reset($xmlrpc_val->me['struct']);
995
			$arr = array();
996
997
			while (list($key,$value) = each($xmlrpc_val->me['struct']))
998
			{
999
				$arr[$key] = $this->xmlrpc_decoder($value);
1000
			}
1001
			return $arr;
1002
		}
1003
	}
1004
1005
	// --------------------------------------------------------------------
1006
1007
	/**
1008
	 * ISO-8601 time to server or UTC time
1009
	 *
1010
	 * @param	string
1011
	 * @param	bool
1012
	 * @return	int	unix timestamp
1013
	 */
1014
	public function iso8601_decode($time, $utc = FALSE)
1015
	{
1016
		// Return a time in the localtime, or UTC
1017
		$t = 0;
1018
		if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))
1019
		{
1020
			$fnc = ($utc === TRUE) ? 'gmmktime' : 'mktime';
1021
			$t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
1022
		}
1023
		return $t;
1024
	}
1025
1026
} // END XML_RPC_Response Class
1027
1028
/**
1029
 * XML-RPC Message class
1030
 *
1031
 * @category	XML-RPC
1032
 * @author		EllisLab Dev Team
1033
 * @link		http://codeigniter.com/user_guide/libraries/xmlrpc.html
1034
 */
1035
class XML_RPC_Message extends CI_Xmlrpc
1036
{
1037
1038
	/**
1039
	 * Payload
1040
	 *
1041
	 * @var	string
1042
	 */
1043
	public $payload;
1044
1045
	/**
1046
	 * Method name
1047
	 *
1048
	 * @var	string
1049
	 */
1050
	public $method_name;
1051
1052
	/**
1053
	 * Parameter list
1054
	 *
1055
	 * @var	array
1056
	 */
1057
	public $params		= array();
1058
1059
	/**
1060
	 * XH?
1061
	 *
1062
	 * @var	array
1063
	 */
1064
	public $xh		= array();
1065
1066
	// --------------------------------------------------------------------
1067
1068
	/**
1069
	 * Constructor
1070
	 *
1071
	 * @param	string	$method
1072
	 * @param	array	$pars
1073
	 * @return	void
1074
	 */
1075
	public function __construct($method, $pars = FALSE)
1076
	{
1077
		parent::__construct();
1078
1079
		$this->method_name = $method;
1080
		if (is_array($pars) && count($pars) > 0)
1081
		{
1082
			for ($i = 0, $c = count($pars); $i < $c; $i++)
1083
			{
1084
				// $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...
1085
				$this->params[] = $pars[$i];
1086
			}
1087
		}
1088
	}
1089
1090
	// --------------------------------------------------------------------
1091
1092
	/**
1093
	 * Create Payload to Send
1094
	 *
1095
	 * @return	void
1096
	 */
1097
	public function createPayload()
1098
	{
1099
		$this->payload = '<?xml version="1.0"?'.">\r\n<methodCall>\r\n"
1100
				.'<methodName>'.$this->method_name."</methodName>\r\n"
1101
				."<params>\r\n";
1102
1103
		for ($i = 0, $c = count($this->params); $i < $c; $i++)
1104
		{
1105
			// $p = XML_RPC_Values
1106
			$p = $this->params[$i];
1107
			$this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n";
1108
		}
1109
1110
		$this->payload .= "</params>\r\n</methodCall>\r\n";
1111
	}
1112
1113
	// --------------------------------------------------------------------
1114
1115
	/**
1116
	 * Parse External XML-RPC Server's Response
1117
	 *
1118
	 * @param	resource
1119
	 * @return	object
1120
	 */
1121
	public function parseResponse($fp)
1122
	{
1123
		$data = '';
1124
1125
		while ($datum = fread($fp, 4096))
1126
		{
1127
			$data .= $datum;
1128
		}
1129
1130
		// Display HTTP content for debugging
1131
		if ($this->debug === TRUE)
1132
		{
1133
			echo "<pre>---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n</pre>";
1134
		}
1135
1136
		// Check for data
1137 View Code Duplication
		if ($data === '')
1138
		{
1139
			error_log($this->xmlrpcstr['no_data']);
1140
			return new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
1141
		}
1142
1143
		// Check for HTTP 200 Response
1144
		if (strpos($data, 'HTTP') === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
1145
		{
1146
			$errstr = substr($data, 0, strpos($data, "\n")-1);
1147
			return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');
1148
		}
1149
1150
		//-------------------------------------
1151
		// Create and Set Up XML Parser
1152
		//-------------------------------------
1153
1154
		$parser = xml_parser_create($this->xmlrpc_defencoding);
1155
		$pname = (string) $parser;
1156
		$this->xh[$pname] = array(
1157
			'isf'		=> 0,
1158
			'ac'		=> '',
1159
			'headers'	=> array(),
1160
			'stack'		=> array(),
1161
			'valuestack'	=> array(),
1162
			'isf_reason'	=> 0
1163
		);
1164
1165
		xml_set_object($parser, $this);
1166
		xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);
1167
		xml_set_element_handler($parser, 'open_tag', 'closing_tag');
1168
		xml_set_character_data_handler($parser, 'character_data');
1169
		//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...
1170
1171
		// Get headers
1172
		$lines = explode("\r\n", $data);
1173
		while (($line = array_shift($lines)))
1174
		{
1175
			if (strlen($line) < 1)
1176
			{
1177
				break;
1178
			}
1179
			$this->xh[$pname]['headers'][] = $line;
1180
		}
1181
		$data = implode("\r\n", $lines);
1182
1183
		// Parse XML data
1184
		if ( ! xml_parse($parser, $data, count($data)))
1185
		{
1186
			$errstr = sprintf('XML error: %s at line %d',
1187
						xml_error_string(xml_get_error_code($parser)),
1188
						xml_get_current_line_number($parser));
1189
1190
			$r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
1191
			xml_parser_free($parser);
1192
			return $r;
1193
		}
1194
		xml_parser_free($parser);
1195
1196
		// Got ourselves some badness, it seems
1197
		if ($this->xh[$pname]['isf'] > 1)
1198
		{
1199
			if ($this->debug === TRUE)
1200
			{
1201
				echo "---Invalid Return---\n".$this->xh[$pname]['isf_reason']."---Invalid Return---\n\n";
1202
			}
1203
1204
			return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['isf_reason']);
1205
		}
1206
		elseif ( ! is_object($this->xh[$pname]['value']))
1207
		{
1208
			return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['isf_reason']);
1209
		}
1210
1211
		// Display XML content for debugging
1212
		if ($this->debug === TRUE)
1213
		{
1214
			echo '<pre>';
1215
1216
			if (count($this->xh[$pname]['headers'] > 0))
1217
			{
1218
				echo "---HEADERS---\n";
1219
				foreach ($this->xh[$pname]['headers'] as $header)
1220
				{
1221
					echo $header."\n";
1222
				}
1223
				echo "---END HEADERS---\n\n";
1224
			}
1225
1226
			echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n---PARSED---\n";
1227
			var_dump($this->xh[$pname]['value']);
1228
			echo "\n---END PARSED---</pre>";
1229
		}
1230
1231
		// Send response
1232
		$v = $this->xh[$pname]['value'];
1233
		if ($this->xh[$pname]['isf'])
1234
		{
1235
			$errno_v = $v->me['struct']['faultCode'];
1236
			$errstr_v = $v->me['struct']['faultString'];
1237
			$errno = $errno_v->scalarval();
1238
1239
			if ($errno === 0)
1240
			{
1241
				// FAULT returned, errno needs to reflect that
1242
				$errno = -1;
1243
			}
1244
1245
			$r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
1246
		}
1247
		else
1248
		{
1249
			$r = new XML_RPC_Response($v);
1250
		}
1251
1252
		$r->headers = $this->xh[$pname]['headers'];
1253
		return $r;
1254
	}
1255
1256
	// --------------------------------------------------------------------
1257
1258
	// ------------------------------------
1259
	//  Begin Return Message Parsing section
1260
	// ------------------------------------
1261
1262
	// quick explanation of components:
1263
	//   ac - used to accumulate values
1264
	//   isf - used to indicate a fault
1265
	//   lv - used to indicate "looking for a value": implements
1266
	//		the logic to allow values with no types to be strings
1267
	//   params - used to store parameters in method calls
1268
	//   method - used to store method name
1269
	//	 stack - array with parent tree of the xml element,
1270
	//			 used to validate the nesting of elements
1271
1272
	// --------------------------------------------------------------------
1273
1274
	/**
1275
	 * Start Element Handler
1276
	 *
1277
	 * @param	string
1278
	 * @param	string
1279
	 * @return	void
1280
	 */
1281
	public function open_tag($the_parser, $name)
1282
	{
1283
		$the_parser = (string) $the_parser;
1284
1285
		// If invalid nesting, then return
1286
		if ($this->xh[$the_parser]['isf'] > 1) return;
1287
1288
		// Evaluate and check for correct nesting of XML elements
1289
		if (count($this->xh[$the_parser]['stack']) === 0)
1290
		{
1291
			if ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')
1292
			{
1293
				$this->xh[$the_parser]['isf'] = 2;
1294
				$this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
1295
				return;
1296
			}
1297
		}
1298
		// not top level element: see if parent is OK
1299
		elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
1300
		{
1301
			$this->xh[$the_parser]['isf'] = 2;
1302
			$this->xh[$the_parser]['isf_reason'] = 'XML-RPC element '.$name.' cannot be child of '.$this->xh[$the_parser]['stack'][0];
1303
			return;
1304
		}
1305
1306
		switch ($name)
1307
		{
1308
			case 'STRUCT':
1309
			case 'ARRAY':
1310
				// Creates array for child elements
1311
				$cur_val = array('value' => array(), 'type' => $name);
1312
				array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
1313
				break;
1314
			case 'METHODNAME':
1315
			case 'NAME':
1316
				$this->xh[$the_parser]['ac'] = '';
1317
				break;
1318
			case 'FAULT':
1319
				$this->xh[$the_parser]['isf'] = 1;
1320
				break;
1321
			case 'PARAM':
1322
				$this->xh[$the_parser]['value'] = NULL;
1323
				break;
1324
			case 'VALUE':
1325
				$this->xh[$the_parser]['vt'] = 'value';
1326
				$this->xh[$the_parser]['ac'] = '';
1327
				$this->xh[$the_parser]['lv'] = 1;
1328
				break;
1329
			case 'I4':
1330
			case 'INT':
1331
			case 'STRING':
1332
			case 'BOOLEAN':
1333
			case 'DOUBLE':
1334
			case 'DATETIME.ISO8601':
1335
			case 'BASE64':
1336
				if ($this->xh[$the_parser]['vt'] !== 'value')
1337
				{
1338
					//two data elements inside a value: an error occurred!
1339
					$this->xh[$the_parser]['isf'] = 2;
1340
					$this->xh[$the_parser]['isf_reason'] = 'There is a '.$name.' element following a '
1341
										.$this->xh[$the_parser]['vt'].' element inside a single value';
1342
					return;
1343
				}
1344
1345
				$this->xh[$the_parser]['ac'] = '';
1346
				break;
1347
			case 'MEMBER':
1348
				// Set name of <member> to nothing to prevent errors later if no <name> is found
1349
				$this->xh[$the_parser]['valuestack'][0]['name'] = '';
1350
1351
				// Set NULL value to check to see if value passed for this param/member
1352
				$this->xh[$the_parser]['value'] = NULL;
1353
				break;
1354
			case 'DATA':
1355
			case 'METHODCALL':
1356
			case 'METHODRESPONSE':
1357
			case 'PARAMS':
1358
				// valid elements that add little to processing
1359
				break;
1360
			default:
1361
				/// An Invalid Element is Found, so we have trouble
1362
				$this->xh[$the_parser]['isf'] = 2;
1363
				$this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;
1364
				break;
1365
		}
1366
1367
		// Add current element name to stack, to allow validation of nesting
1368
		array_unshift($this->xh[$the_parser]['stack'], $name);
1369
1370
		$name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;
1371
	}
1372
1373
	// --------------------------------------------------------------------
1374
1375
	/**
1376
	 * End Element Handler
1377
	 *
1378
	 * @param	string
1379
	 * @param	string
1380
	 * @return	void
1381
	 */
1382
	public function closing_tag($the_parser, $name)
1383
	{
1384
		$the_parser = (string) $the_parser;
1385
1386
		if ($this->xh[$the_parser]['isf'] > 1) return;
1387
1388
		// Remove current element from stack and set variable
1389
		// NOTE: If the XML validates, then we do not have to worry about
1390
		// the opening and closing of elements. Nesting is checked on the opening
1391
		// tag so we be safe there as well.
1392
1393
		$curr_elem = array_shift($this->xh[$the_parser]['stack']);
1394
1395
		switch ($name)
1396
		{
1397
			case 'STRUCT':
1398
			case 'ARRAY':
1399
				$cur_val = array_shift($this->xh[$the_parser]['valuestack']);
1400
				$this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();
1401
				$this->xh[$the_parser]['vt']	= strtolower($name);
1402
				break;
1403
			case 'NAME':
1404
				$this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
1405
				break;
1406
			case 'BOOLEAN':
1407
			case 'I4':
1408
			case 'INT':
1409
			case 'STRING':
1410
			case 'DOUBLE':
1411
			case 'DATETIME.ISO8601':
1412
			case 'BASE64':
1413
				$this->xh[$the_parser]['vt'] = strtolower($name);
1414
1415
				if ($name === 'STRING')
1416
				{
1417
					$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1418
				}
1419
				elseif ($name === 'DATETIME.ISO8601')
1420
				{
1421
					$this->xh[$the_parser]['vt']	= $this->xmlrpcDateTime;
1422
					$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
1423
				}
1424
				elseif ($name === 'BASE64')
1425
				{
1426
					$this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
1427
				}
1428
				elseif ($name === 'BOOLEAN')
1429
				{
1430
					// Translated BOOLEAN values to TRUE AND FALSE
1431
					$this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];
1432
				}
1433 View Code Duplication
				elseif ($name=='DOUBLE')
1434
				{
1435
					// we have a DOUBLE
1436
					// we must check that only 0123456789-.<space> are characters here
1437
					$this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])
1438
										? (float) $this->xh[$the_parser]['ac']
1439
										: 'ERROR_NON_NUMERIC_FOUND';
1440
				}
1441 View Code Duplication
				else
1442
				{
1443
					// we have an I4/INT
1444
					// we must check that only 0123456789-<space> are characters here
1445
					$this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])
1446
										? (int) $this->xh[$the_parser]['ac']
1447
										: 'ERROR_NON_NUMERIC_FOUND';
1448
				}
1449
				$this->xh[$the_parser]['ac'] = '';
1450
				$this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
1451
				break;
1452
			case 'VALUE':
1453
				// This if() detects if no scalar was inside <VALUE></VALUE>
1454
				if ($this->xh[$the_parser]['vt'] == 'value')
1455
				{
1456
					$this->xh[$the_parser]['value']	= $this->xh[$the_parser]['ac'];
1457
					$this->xh[$the_parser]['vt']	= $this->xmlrpcString;
1458
				}
1459
1460
				// build the XML-RPC value out of the data received, and substitute it
1461
				$temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
1462
1463
				if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')
1464
				{
1465
					// Array
1466
					$this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
1467
				}
1468
				else
1469
				{
1470
					// Struct
1471
					$this->xh[$the_parser]['value'] = $temp;
1472
				}
1473
				break;
1474
			case 'MEMBER':
1475
				$this->xh[$the_parser]['ac'] = '';
1476
1477
				// If value add to array in the stack for the last element built
1478
				if ($this->xh[$the_parser]['value'])
1479
				{
1480
					$this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
1481
				}
1482
				break;
1483
			case 'DATA':
1484
				$this->xh[$the_parser]['ac'] = '';
1485
				break;
1486
			case 'PARAM':
1487
				if ($this->xh[$the_parser]['value'])
1488
				{
1489
					$this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
1490
				}
1491
				break;
1492
			case 'METHODNAME':
1493
				$this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
1494
				break;
1495
			case 'PARAMS':
1496
			case 'FAULT':
1497
			case 'METHODCALL':
1498
			case 'METHORESPONSE':
1499
				// We're all good kids with nuthin' to do
1500
				break;
1501
			default:
1502
				// End of an Invalid Element. Taken care of during the opening tag though
1503
				break;
1504
		}
1505
	}
1506
1507
	// --------------------------------------------------------------------
1508
1509
	/**
1510
	 * Parse character data
1511
	 *
1512
	 * @param	string
1513
	 * @param	string
1514
	 * @return	void
1515
	 */
1516
	public function character_data($the_parser, $data)
1517
	{
1518
		$the_parser = (string) $the_parser;
1519
1520
		if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
1521
1522
		// If a value has not been found
1523
		if ($this->xh[$the_parser]['lv'] !== 3)
1524
		{
1525
			if ($this->xh[$the_parser]['lv'] === 1)
1526
			{
1527
				$this->xh[$the_parser]['lv'] = 2; // Found a value
1528
			}
1529
1530
			if ( ! isset($this->xh[$the_parser]['ac']))
1531
			{
1532
				$this->xh[$the_parser]['ac'] = '';
1533
			}
1534
1535
			$this->xh[$the_parser]['ac'] .= $data;
1536
		}
1537
	}
1538
1539
	// --------------------------------------------------------------------
1540
1541
	/**
1542
	 * Add parameter
1543
	 *
1544
	 * @param	mixed
1545
	 * @return	void
1546
	 */
1547
	public function addParam($par)
1548
	{
1549
		$this->params[] = $par;
1550
	}
1551
1552
	// --------------------------------------------------------------------
1553
1554
	/**
1555
	 * Output parameters
1556
	 *
1557
	 * @param	array	$array
1558
	 * @return	array
1559
	 */
1560
	public function output_parameters(array $array = array())
1561
	{
1562
		$CI =& get_instance();
1563
1564 View Code Duplication
		if ( ! empty($array))
1565
		{
1566
			while (list($key) = each($array))
1567
			{
1568
				if (is_array($array[$key]))
1569
				{
1570
					$array[$key] = $this->output_parameters($array[$key]);
1571
				}
1572
				elseif ($key !== 'bits' && $this->xss_clean)
1573
				{
1574
					// 'bits' is for the MetaWeblog API image bits
1575
					// @todo - this needs to be made more general purpose
1576
					$array[$key] = $CI->security->xss_clean($array[$key]);
1577
				}
1578
			}
1579
1580
			return $array;
1581
		}
1582
1583
		$parameters = array();
1584
1585
		for ($i = 0, $c = count($this->params); $i < $c; $i++)
1586
		{
1587
			$a_param = $this->decode_message($this->params[$i]);
1588
1589
			if (is_array($a_param))
1590
			{
1591
				$parameters[] = $this->output_parameters($a_param);
1592
			}
1593
			else
1594
			{
1595
				$parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;
1596
			}
1597
		}
1598
1599
		return $parameters;
1600
	}
1601
1602
	// --------------------------------------------------------------------
1603
1604
	/**
1605
	 * Decode message
1606
	 *
1607
	 * @param	object
1608
	 * @return	mixed
1609
	 */
1610 View Code Duplication
	public function decode_message($param)
1611
	{
1612
		$kind = $param->kindOf();
1613
1614
		if ($kind === 'scalar')
1615
		{
1616
			return $param->scalarval();
1617
		}
1618
		elseif ($kind === 'array')
1619
		{
1620
			reset($param->me);
1621
			$b = current($param->me);
1622
			$arr = array();
1623
1624
			for ($i = 0, $c = count($b); $i < $c; $i++)
1625
			{
1626
				$arr[] = $this->decode_message($param->me['array'][$i]);
1627
			}
1628
1629
			return $arr;
1630
		}
1631
		elseif ($kind === 'struct')
1632
		{
1633
			reset($param->me['struct']);
1634
			$arr = array();
1635
1636
			while (list($key,$value) = each($param->me['struct']))
1637
			{
1638
				$arr[$key] = $this->decode_message($value);
1639
			}
1640
1641
			return $arr;
1642
		}
1643
	}
1644
1645
} // END XML_RPC_Message Class
1646
1647
/**
1648
 * XML-RPC Values class
1649
 *
1650
 * @category	XML-RPC
1651
 * @author		EllisLab Dev Team
1652
 * @link		http://codeigniter.com/user_guide/libraries/xmlrpc.html
1653
 */
1654
class XML_RPC_Values extends CI_Xmlrpc
1655
{
1656
	/**
1657
	 * Value data
1658
	 *
1659
	 * @var	array
1660
	 */
1661
	public $me	= array();
1662
1663
	/**
1664
	 * Value type
1665
	 *
1666
	 * @var	int
1667
	 */
1668
	public $mytype	= 0;
1669
1670
	// --------------------------------------------------------------------
1671
1672
	/**
1673
	 * Constructor
1674
	 *
1675
	 * @param	mixed	$val
1676
	 * @param	string	$type
1677
	 * @return	void
1678
	 */
1679
	public function __construct($val = -1, $type = '')
1680
	{
1681
		parent::__construct();
1682
1683
		if ($val !== -1 OR $type !== '')
1684
		{
1685
			$type = $type === '' ? 'string' : $type;
1686
1687
			if ($this->xmlrpcTypes[$type] == 1)
1688
			{
1689
				$this->addScalar($val, $type);
1690
			}
1691
			elseif ($this->xmlrpcTypes[$type] == 2)
1692
			{
1693
				$this->addArray($val);
1694
			}
1695
			elseif ($this->xmlrpcTypes[$type] == 3)
1696
			{
1697
				$this->addStruct($val);
1698
			}
1699
		}
1700
	}
1701
1702
	// --------------------------------------------------------------------
1703
1704
	/**
1705
	 * Add scalar value
1706
	 *
1707
	 * @param	scalar
1708
	 * @param	string
1709
	 * @return	int
1710
	 */
1711
	public function addScalar($val, $type = 'string')
1712
	{
1713
		$typeof = $this->xmlrpcTypes[$type];
1714
1715
		if ($this->mytype === 1)
1716
		{
1717
			echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
1718
			return 0;
1719
		}
1720
1721
		if ($typeof != 1)
1722
		{
1723
			echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';
1724
			return 0;
1725
		}
1726
1727
		if ($type === $this->xmlrpcBoolean)
1728
		{
1729
			$val = (int) (strcasecmp($val, 'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
1730
		}
1731
1732
		if ($this->mytype === 2)
1733
		{
1734
			// adding to an array here
1735
			$ar = $this->me['array'];
1736
			$ar[] = new XML_RPC_Values($val, $type);
1737
			$this->me['array'] = $ar;
1738
		}
1739
		else
1740
		{
1741
			// a scalar, so set the value and remember we're scalar
1742
			$this->me[$type] = $val;
1743
			$this->mytype = $typeof;
1744
		}
1745
1746
		return 1;
1747
	}
1748
1749
	// --------------------------------------------------------------------
1750
1751
	/**
1752
	 * Add array value
1753
	 *
1754
	 * @param	array
1755
	 * @return	int
1756
	 */
1757 View Code Duplication
	public function addArray($vals)
1758
	{
1759
		if ($this->mytype !== 0)
1760
		{
1761
			echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
1762
			return 0;
1763
		}
1764
1765
		$this->mytype = $this->xmlrpcTypes['array'];
1766
		$this->me['array'] = $vals;
1767
		return 1;
1768
	}
1769
1770
	// --------------------------------------------------------------------
1771
1772
	/**
1773
	 * Add struct value
1774
	 *
1775
	 * @param	object
1776
	 * @return	int
1777
	 */
1778 View Code Duplication
	public function addStruct($vals)
1779
	{
1780
		if ($this->mytype !== 0)
1781
		{
1782
			echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
1783
			return 0;
1784
		}
1785
		$this->mytype = $this->xmlrpcTypes['struct'];
1786
		$this->me['struct'] = $vals;
1787
		return 1;
1788
	}
1789
1790
	// --------------------------------------------------------------------
1791
1792
	/**
1793
	 * Get value type
1794
	 *
1795
	 * @return	string
1796
	 */
1797
	public function kindOf()
1798
	{
1799
		switch ($this->mytype)
1800
		{
1801
			case 3: return 'struct';
0 ignored issues
show
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1802
			case 2: return 'array';
0 ignored issues
show
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1803
			case 1: return 'scalar';
0 ignored issues
show
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1804
			default: return 'undef';
0 ignored issues
show
The default body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a default statement must start on the line immediately following the statement.

switch ($expr) {
    default:
        doSomething(); //right
        break;
}


switch ($expr) {
    default:

        doSomething(); //wrong
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1805
		}
1806
	}
1807
1808
	// --------------------------------------------------------------------
1809
1810
	/**
1811
	 * Serialize data
1812
	 *
1813
	 * @param	string
1814
	 * @param	mixed
1815
	 * @return	string
1816
	 */
1817
	public function serializedata($typ, $val)
1818
	{
1819
		$rs = '';
1820
1821
		switch ($this->xmlrpcTypes[$typ])
1822
		{
1823
			case 3:
1824
				// struct
1825
				$rs .= "<struct>\n";
1826
				reset($val);
1827
				while (list($key2, $val2) = each($val))
1828
				{
1829
					$rs .= "<member>\n<name>{$key2}</name>\n".$this->serializeval($val2)."</member>\n";
1830
				}
1831
				$rs .= '</struct>';
1832
				break;
1833
			case 2:
1834
				// array
1835
				$rs .= "<array>\n<data>\n";
1836
				for ($i = 0, $c = count($val); $i < $c; $i++)
1837
				{
1838
					$rs .= $this->serializeval($val[$i]);
1839
				}
1840
				$rs .= "</data>\n</array>\n";
1841
				break;
1842
			case 1:
1843
				// others
1844
				switch ($typ)
1845
				{
1846
					case $this->xmlrpcBase64:
1847
						$rs .= '<'.$typ.'>'.base64_encode( (string) $val).'</'.$typ.">\n";
1848
						break;
1849
					case $this->xmlrpcBoolean:
1850
						$rs .= '<'.$typ.'>'.( (bool) $val ? '1' : '0').'</'.$typ.">\n";
1851
						break;
1852
					case $this->xmlrpcString:
1853
						$rs .= '<'.$typ.'>'.htmlspecialchars( (string) $val).'</'.$typ.">\n";
1854
						break;
1855
					default:
1856
						$rs .= '<'.$typ.'>'.$val.'</'.$typ.">\n";
1857
						break;
1858
				}
1859
			default:
1860
				break;
1861
		}
1862
1863
		return $rs;
1864
	}
1865
1866
	// --------------------------------------------------------------------
1867
1868
	/**
1869
	 * Serialize class
1870
	 *
1871
	 * @return	string
1872
	 */
1873
	public function serialize_class()
1874
	{
1875
		return $this->serializeval($this);
1876
	}
1877
1878
	// --------------------------------------------------------------------
1879
1880
	/**
1881
	 * Serialize value
1882
	 *
1883
	 * @param	object
1884
	 * @return	string
1885
	 */
1886
	public function serializeval($o)
1887
	{
1888
		$ar = $o->me;
1889
		reset($ar);
1890
1891
		list($typ, $val) = each($ar);
1892
		return "<value>\n".$this->serializedata($typ, $val)."</value>\n";
1893
	}
1894
1895
	// --------------------------------------------------------------------
1896
1897
	/**
1898
	 * Scalar value
1899
	 *
1900
	 * @return	mixed
1901
	 */
1902
	public function scalarval()
1903
	{
1904
		reset($this->me);
1905
		return current($this->me);
1906
	}
1907
1908
	// --------------------------------------------------------------------
1909
1910
	/**
1911
	 * Encode time in ISO-8601 form.
1912
	 * Useful for sending time in XML-RPC
1913
	 *
1914
	 * @param	int	unix timestamp
1915
	 * @param	bool
1916
	 * @return	string
1917
	*/
1918
	public function iso8601_encode($time, $utc = FALSE)
1919
	{
1920
		return ($utc) ? strftime('%Y%m%dT%H:%i:%s', $time) : gmstrftime('%Y%m%dT%H:%i:%s', $time);
1921
	}
1922
1923
} // END XML_RPC_Values Class
1924