| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920 | <?php/** * CodeIgniter * * An open source application development framework for PHP * * This content is released under the MIT License (MIT) * * Copyright (c) 2014 - 2017, British Columbia Institute of Technology * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * @package	CodeIgniter * @author	EllisLab Dev Team * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/) * @copyright	Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/) * @license	http://opensource.org/licenses/MIT	MIT License * @link	https://codeigniter.com * @since	Version 1.0.0 * @filesource */defined('BASEPATH') OR exit('No direct script access allowed');if ( ! function_exists('xml_parser_create')){	show_error('Your PHP installation does not support XML');}// ------------------------------------------------------------------------/** * XML-RPC request handler class * * @package		CodeIgniter * @subpackage	Libraries * @category	XML-RPC * @author		EllisLab Dev Team * @link		https://codeigniter.com/user_guide/libraries/xmlrpc.html */class CI_Xmlrpc {	/**	 * Debug flag	 *	 * @var	bool	 */	public $debug		= FALSE;	/**	 * I4 data type	 *	 * @var	string	 */	public $xmlrpcI4	= 'i4';	/**	 * Integer data type	 *	 * @var	string	 */	public $xmlrpcInt	= 'int';	/**	 * Boolean data type	 *	 * @var	string	 */	public $xmlrpcBoolean	= 'boolean';	/**	 * Double data type	 *	 * @var	string	 */	public $xmlrpcDouble	= 'double';	/**	 * String data type	 *	 * @var	string	 */	public $xmlrpcString	= 'string';	/**	 * DateTime format	 *	 * @var	string	 */	public $xmlrpcDateTime	= 'dateTime.iso8601';	/**	 * Base64 data type	 *	 * @var	string	 */	public $xmlrpcBase64	= 'base64';	/**	 * Array data type	 *	 * @var	string	 */	public $xmlrpcArray	= 'array';	/**	 * Struct data type	 *	 * @var	string	 */	public $xmlrpcStruct	= 'struct';	/**	 * Data types list	 *	 * @var	array	 */	public $xmlrpcTypes	= array();	/**	 * Valid parents list	 *	 * @var	array	 */	public $valid_parents	= array();	/**	 * Response error numbers list	 *	 * @var	array	 */	public $xmlrpcerr		= array();	/**	 * Response error messages list	 *	 * @var	string[]	 */	public $xmlrpcstr		= array();	/**	 * Encoding charset	 *	 * @var	string	 */	public $xmlrpc_defencoding	= 'UTF-8';	/**	 * XML-RPC client name	 *	 * @var	string	 */	public $xmlrpcName		= 'XML-RPC for CodeIgniter';	/**	 * XML-RPC version	 *	 * @var	string	 */	public $xmlrpcVersion		= '1.1';	/**	 * Start of user errors	 *	 * @var	int	 */	public $xmlrpcerruser		= 800;	/**	 * Start of XML parse errors	 *	 * @var	int	 */	public $xmlrpcerrxml		= 100;	/**	 * Backslash replacement value	 *	 * @var	string	 */	public $xmlrpc_backslash	= '';	/**	 * XML-RPC Client object	 *	 * @var	object	 */	public $client;	/**	 * XML-RPC Method name	 *	 * @var	string	 */	public $method;	/**	 * XML-RPC Data	 *	 * @var	array	 */	public $data;	/**	 * XML-RPC Message	 *	 * @var	string	 */	public $message			= '';	/**	 * Request error message	 *	 * @var	string	 */	public $error			= '';	/**	 * XML-RPC result object	 *	 * @var	object	 */	public $result;	/**	 * XML-RPC Response	 *	 * @var	array	 */	public $response		= array(); // Response from remote server	/**	 * XSS Filter flag	 *	 * @var	bool	 */	public $xss_clean		= TRUE;	// --------------------------------------------------------------------	/**	 * Constructor	 *	 * Initializes property default values	 *	 * @param	array	$config	 * @return	void	 */	public function __construct($config = array())	{		$this->xmlrpc_backslash = chr(92).chr(92);		// Types for info sent back and forth		$this->xmlrpcTypes = array(			$this->xmlrpcI4	 		=> '1',			$this->xmlrpcInt		=> '1',			$this->xmlrpcBoolean	=> '1',			$this->xmlrpcString		=> '1',			$this->xmlrpcDouble		=> '1',			$this->xmlrpcDateTime	=> '1',			$this->xmlrpcBase64		=> '1',			$this->xmlrpcArray		=> '2',			$this->xmlrpcStruct		=> '3'		);		// Array of Valid Parents for Various XML-RPC elements		$this->valid_parents = array('BOOLEAN' => array('VALUE'),			'I4'				=> array('VALUE'),			'INT'				=> array('VALUE'),			'STRING'			=> array('VALUE'),			'DOUBLE'			=> array('VALUE'),			'DATETIME.ISO8601'	=> array('VALUE'),			'BASE64'			=> array('VALUE'),			'ARRAY'			=> array('VALUE'),			'STRUCT'			=> array('VALUE'),			'PARAM'			=> array('PARAMS'),			'METHODNAME'		=> array('METHODCALL'),			'PARAMS'			=> array('METHODCALL', 'METHODRESPONSE'),			'MEMBER'			=> array('STRUCT'),			'NAME'				=> array('MEMBER'),			'DATA'				=> array('ARRAY'),			'FAULT'			=> array('METHODRESPONSE'),			'VALUE'			=> array('MEMBER', 'DATA', 'PARAM', 'FAULT')		);		// XML-RPC Responses		$this->xmlrpcerr['unknown_method'] = '1';		$this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server';		$this->xmlrpcerr['invalid_return'] = '2';		$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.';		$this->xmlrpcerr['incorrect_params'] = '3';		$this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method';		$this->xmlrpcerr['introspect_unknown'] = '4';		$this->xmlrpcstr['introspect_unknown'] = 'Cannot inspect signature for request: method unknown';		$this->xmlrpcerr['http_error'] = '5';		$this->xmlrpcstr['http_error'] = "Did not receive a '200 OK' response from remote server.";		$this->xmlrpcerr['no_data'] = '6';		$this->xmlrpcstr['no_data'] = 'No data received from server.';		$this->initialize($config);		log_message('info', 'XML-RPC Class Initialized');	}	// --------------------------------------------------------------------	/**	 * Initialize	 *	 * @param	array	$config	 * @return	void	 */	public function initialize($config = array())	{		if (count($config) > 0)		{			foreach ($config as $key => $val)			{				if (isset($this->$key))				{					$this->$key = $val;				}			}		}	}	// --------------------------------------------------------------------	/**	 * Parse server URL	 *	 * @param	string	$url	 * @param	int	$port	 * @param	string	$proxy	 * @param	int	$proxy_port	 * @return	void	 */	public function server($url, $port = 80, $proxy = FALSE, $proxy_port = 8080)	{		if (stripos($url, 'http') !== 0)		{			$url = 'http://'.$url;		}		$parts = parse_url($url);		if (isset($parts['user'], $parts['pass']))		{			$parts['host'] = $parts['user'].':'.$parts['pass'].'@'.$parts['host'];		}		$path = isset($parts['path']) ? $parts['path'] : '/';		if ( ! empty($parts['query']))		{			$path .= '?'.$parts['query'];		}		$this->client = new XML_RPC_Client($path, $parts['host'], $port, $proxy, $proxy_port);	}	// --------------------------------------------------------------------	/**	 * Set Timeout	 *	 * @param	int	$seconds	 * @return	void	 */	public function timeout($seconds = 5)	{		if ($this->client !== NULL && is_int($seconds))		{			$this->client->timeout = $seconds;		}	}	// --------------------------------------------------------------------	/**	 * Set Methods	 *	 * @param	string	$function	Method name	 * @return	void	 */	public function method($function)	{		$this->method = $function;	}	// --------------------------------------------------------------------	/**	 * Take Array of Data and Create Objects	 *	 * @param	array	$incoming	 * @return	void	 */	public function request($incoming)	{		if ( ! is_array($incoming))		{			// Send Error			return;		}		$this->data = array();		foreach ($incoming as $key => $value)		{			$this->data[$key] = $this->values_parsing($value);		}	}	// --------------------------------------------------------------------	/**	 * Set Debug	 *	 * @param	bool	$flag	 * @return	void	 */	public function set_debug($flag = TRUE)	{		$this->debug = ($flag === TRUE);	}	// --------------------------------------------------------------------	/**	 * Values Parsing	 *	 * @param	mixed	$value	 * @return	object	 */	public function values_parsing($value)	{		if (is_array($value) && array_key_exists(0, $value))		{			if ( ! isset($value[1], $this->xmlrpcTypes[$value[1]]))			{				$temp = new XML_RPC_Values($value[0], (is_array($value[0]) ? 'array' : 'string'));			}			else			{				if (is_array($value[0]) && ($value[1] === 'struct' OR $value[1] === 'array'))				{					foreach (array_keys($value[0]) as $k)					{						$value[0][$k] = $this->values_parsing($value[0][$k]);					}				}				$temp = new XML_RPC_Values($value[0], $value[1]);			}		}		else		{			$temp = new XML_RPC_Values($value, 'string');		}		return $temp;	}	// --------------------------------------------------------------------	/**	 * Sends XML-RPC Request	 *	 * @return	bool	 */	public function send_request()	{		$this->message = new XML_RPC_Message($this->method, $this->data);		$this->message->debug = $this->debug;		if ( ! $this->result = $this->client->send($this->message) OR ! is_object($this->result->val))		{			$this->error = $this->result->errstr;			return FALSE;		}		$this->response = $this->result->decode();		return TRUE;	}	// --------------------------------------------------------------------	/**	 * Returns Error	 *	 * @return	string	 */	public function display_error()	{		return $this->error;	}	// --------------------------------------------------------------------	/**	 * Returns Remote Server Response	 *	 * @return	string	 */	public function display_response()	{		return $this->response;	}	// --------------------------------------------------------------------	/**	 * Sends an Error Message for Server Request	 *	 * @param	int	$number	 * @param	string	$message	 * @return	object	 */	public function send_error_message($number, $message)	{		return new XML_RPC_Response(0, $number, $message);	}	// --------------------------------------------------------------------	/**	 * Send Response for Server Request	 *	 * @param	array	$response	 * @return	object	 */	public function send_response($response)	{		// $response should be array of values, which will be parsed		// based on their data and type into a valid group of XML-RPC values		return new XML_RPC_Response($this->values_parsing($response));	}} // END XML_RPC Class/** * XML-RPC Client class * * @category	XML-RPC * @author		EllisLab Dev Team * @link		https://codeigniter.com/user_guide/libraries/xmlrpc.html */class XML_RPC_Client extends CI_Xmlrpc{	/**	 * Path	 *	 * @var	string	 */	public $path			= '';	/**	 * Server hostname	 *	 * @var	string	 */	public $server			= '';	/**	 * Server port	 *	 * @var	int	 */	public $port			= 80;	/**	 *	 * Server username	 *	 * @var	string	 */	public $username;	/**	 * Server password	 *	 * @var	string	 */	public $password;	/**	 * Proxy hostname	 *	 * @var	string	 */	public $proxy			= FALSE;	/**	 * Proxy port	 *	 * @var	int	 */	public $proxy_port		= 8080;	/**	 * Error number	 *	 * @var	string	 */	public $errno			= '';	/**	 * Error message	 *	 * @var	string	 */	public $errstring		= '';	/**	 * Timeout in seconds	 *	 * @var	int	 */	public $timeout		= 5;	/**	 * No Multicall flag	 *	 * @var	bool	 */	public $no_multicall	= FALSE;	// --------------------------------------------------------------------	/**	 * Constructor	 *	 * @param	string	$path	 * @param	object	$server	 * @param	int	$port	 * @param	string	$proxy	 * @param	int	$proxy_port	 * @return	void	 */	public function __construct($path, $server, $port = 80, $proxy = FALSE, $proxy_port = 8080)	{		parent::__construct();		$url = parse_url('http://'.$server);		if (isset($url['user'], $url['pass']))		{			$this->username = $url['user'];			$this->password = $url['pass'];		}		$this->port = $port;		$this->server = $url['host'];		$this->path = $path;		$this->proxy = $proxy;		$this->proxy_port = $proxy_port;	}	// --------------------------------------------------------------------	/**	 * Send message	 *	 * @param	mixed	$msg	 * @return	object	 */	public function send($msg)	{		if (is_array($msg))		{			// Multi-call disabled			return new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'], $this->xmlrpcstr['multicall_recursion']);		}		return $this->sendPayload($msg);	}	// --------------------------------------------------------------------	/**	 * Send payload	 *	 * @param	object	$msg	 * @return	object	 */	public function sendPayload($msg)	{		if ($this->proxy === FALSE)		{			$server = $this->server;			$port = $this->port;		}		else		{			$server = $this->proxy;			$port = $this->proxy_port;		}		$fp = @fsockopen($server, $port, $this->errno, $this->errstring, $this->timeout);		if ( ! is_resource($fp))		{			error_log($this->xmlrpcstr['http_error']);			return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);		}		if (empty($msg->payload))		{			// $msg = XML_RPC_Messages			$msg->createPayload();		}		$r = "\r\n";		$op = 'POST '.$this->path.' HTTP/1.0'.$r			.'Host: '.$this->server.$r			.'Content-Type: text/xml'.$r			.(isset($this->username, $this->password) ? 'Authorization: Basic '.base64_encode($this->username.':'.$this->password).$r : '')			.'User-Agent: '.$this->xmlrpcName.$r			.'Content-Length: '.strlen($msg->payload).$r.$r			.$msg->payload;		stream_set_timeout($fp, $this->timeout); // set timeout for subsequent operations		for ($written = $timestamp = 0, $length = strlen($op); $written < $length; $written += $result)		{			if (($result = fwrite($fp, substr($op, $written))) === FALSE)			{				break;			}			// See https://bugs.php.net/bug.php?id=39598 and http://php.net/manual/en/function.fwrite.php#96951			elseif ($result === 0)			{				if ($timestamp === 0)				{					$timestamp = time();				}				elseif ($timestamp < (time() - $this->timeout))				{					$result = FALSE;					break;				}			}			else			{				$timestamp = 0;			}		}		if ($result === FALSE)		{			error_log($this->xmlrpcstr['http_error']);			return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);		}		$resp = $msg->parseResponse($fp);		fclose($fp);		return $resp;	}} // END XML_RPC_Client Class/** * XML-RPC Response class * * @category	XML-RPC * @author		EllisLab Dev Team * @link		https://codeigniter.com/user_guide/libraries/xmlrpc.html */class XML_RPC_Response{	/**	 * Value	 *	 * @var	mixed	 */	public $val		= 0;	/**	 * Error number	 *	 * @var	int	 */	public $errno		= 0;	/**	 * Error message	 *	 * @var	string	 */	public $errstr		= '';	/**	 * Headers list	 *	 * @var	array	 */	public $headers		= array();	/**	 * XSS Filter flag	 *	 * @var	bool	 */	public $xss_clean	= TRUE;	// --------------------------------------------------------------------	/**	 * Constructor	 *	 * @param	mixed	$val	 * @param	int	$code	 * @param	string	$fstr	 * @return	void	 */	public function __construct($val, $code = 0, $fstr = '')	{		if ($code !== 0)		{			// error			$this->errno = $code;			$this->errstr = htmlspecialchars($fstr,							(is_php('5.4') ? ENT_XML1 | ENT_NOQUOTES : ENT_NOQUOTES),							'UTF-8');		}		elseif ( ! is_object($val))		{			// programmer error, not an object			error_log("Invalid type '".gettype($val)."' (value: ".$val.') passed to XML_RPC_Response. Defaulting to empty value.');			$this->val = new XML_RPC_Values();		}		else		{			$this->val = $val;		}	}	// --------------------------------------------------------------------	/**	 * Fault code	 *	 * @return	int	 */	public function faultCode()	{		return $this->errno;	}	// --------------------------------------------------------------------	/**	 * Fault string	 *	 * @return	string	 */	public function faultString()	{		return $this->errstr;	}	// --------------------------------------------------------------------	/**	 * Value	 *	 * @return	mixed	 */	public function value()	{		return $this->val;	}	// --------------------------------------------------------------------	/**	 * Prepare response	 *	 * @return	string	xml	 */	public function prepare_response()	{		return "<methodResponse>\n"			.($this->errno				? '<fault>	<value>		<struct>			<member>				<name>faultCode</name>				<value><int>'.$this->errno.'</int></value>			</member>			<member>				<name>faultString</name>				<value><string>'.$this->errstr.'</string></value>			</member>		</struct>	</value></fault>'				: "<params>\n<param>\n".$this->val->serialize_class()."</param>\n</params>")			."\n</methodResponse>";	}	// --------------------------------------------------------------------	/**	 * Decode	 *	 * @param	mixed	$array	 * @return	array	 */	public function decode($array = NULL)	{		$CI =& get_instance();		if (is_array($array))		{			foreach ($array as $key => &$value)			{				if (is_array($value))				{					$array[$key] = $this->decode($value);				}				elseif ($this->xss_clean)				{					$array[$key] = $CI->security->xss_clean($value);				}			}			return $array;		}		$result = $this->xmlrpc_decoder($this->val);		if (is_array($result))		{			$result = $this->decode($result);		}		elseif ($this->xss_clean)		{			$result = $CI->security->xss_clean($result);		}		return $result;	}	// --------------------------------------------------------------------	/**	 * XML-RPC Object to PHP Types	 *	 * @param	object	 * @return	array	 */	public function xmlrpc_decoder($xmlrpc_val)	{		$kind = $xmlrpc_val->kindOf();		if ($kind === 'scalar')		{			return $xmlrpc_val->scalarval();		}		elseif ($kind === 'array')		{			reset($xmlrpc_val->me);			$b = current($xmlrpc_val->me);			$arr = array();			for ($i = 0, $size = count($b); $i < $size; $i++)			{				$arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);			}			return $arr;		}		elseif ($kind === 'struct')		{			reset($xmlrpc_val->me['struct']);			$arr = array();			foreach ($xmlrpc_val->me['struct'] as $key => &$value)			{				$arr[$key] = $this->xmlrpc_decoder($value);			}			return $arr;		}	}	// --------------------------------------------------------------------	/**	 * ISO-8601 time to server or UTC time	 *	 * @param	string	 * @param	bool	 * @return	int	unix timestamp	 */	public function iso8601_decode($time, $utc = FALSE)	{		// Return a time in the localtime, or UTC		$t = 0;		if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))		{			$fnc = ($utc === TRUE) ? 'gmmktime' : 'mktime';			$t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);		}		return $t;	}} // END XML_RPC_Response Class/** * XML-RPC Message class * * @category	XML-RPC * @author		EllisLab Dev Team * @link		https://codeigniter.com/user_guide/libraries/xmlrpc.html */class XML_RPC_Message extends CI_Xmlrpc{	/**	 * Payload	 *	 * @var	string	 */	public $payload;	/**	 * Method name	 *	 * @var	string	 */	public $method_name;	/**	 * Parameter list	 *	 * @var	array	 */	public $params		= array();	/**	 * XH?	 *	 * @var	array	 */	public $xh		= array();	// --------------------------------------------------------------------	/**	 * Constructor	 *	 * @param	string	$method	 * @param	array	$pars	 * @return	void	 */	public function __construct($method, $pars = FALSE)	{		parent::__construct();		$this->method_name = $method;		if (is_array($pars) && count($pars) > 0)		{			for ($i = 0, $c = count($pars); $i < $c; $i++)			{				// $pars[$i] = XML_RPC_Values				$this->params[] = $pars[$i];			}		}	}	// --------------------------------------------------------------------	/**	 * Create Payload to Send	 *	 * @return	void	 */	public function createPayload()	{		$this->payload = '<?xml version="1.0"?'.">\r\n<methodCall>\r\n"				.'<methodName>'.$this->method_name."</methodName>\r\n"				."<params>\r\n";		for ($i = 0, $c = count($this->params); $i < $c; $i++)		{			// $p = XML_RPC_Values			$p = $this->params[$i];			$this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n";		}		$this->payload .= "</params>\r\n</methodCall>\r\n";	}	// --------------------------------------------------------------------	/**	 * Parse External XML-RPC Server's Response	 *	 * @param	resource	 * @return	object	 */	public function parseResponse($fp)	{		$data = '';		while ($datum = fread($fp, 4096))		{			$data .= $datum;		}		// Display HTTP content for debugging		if ($this->debug === TRUE)		{			echo "<pre>---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n</pre>";		}		// Check for data		if ($data === '')		{			error_log($this->xmlrpcstr['no_data']);			return new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);		}		// Check for HTTP 200 Response		if (strpos($data, 'HTTP') === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))		{			$errstr = substr($data, 0, strpos($data, "\n")-1);			return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');		}		//-------------------------------------		// Create and Set Up XML Parser		//-------------------------------------		$parser = xml_parser_create($this->xmlrpc_defencoding);		$pname = (string) $parser;		$this->xh[$pname] = array(			'isf'		=> 0,			'ac'		=> '',			'headers'	=> array(),			'stack'		=> array(),			'valuestack'	=> array(),			'isf_reason'	=> 0		);		xml_set_object($parser, $this);		xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);		xml_set_element_handler($parser, 'open_tag', 'closing_tag');		xml_set_character_data_handler($parser, 'character_data');		//xml_set_default_handler($parser, 'default_handler');		// Get headers		$lines = explode("\r\n", $data);		while (($line = array_shift($lines)))		{			if (strlen($line) < 1)			{				break;			}			$this->xh[$pname]['headers'][] = $line;		}		$data = implode("\r\n", $lines);		// Parse XML data		if ( ! xml_parse($parser, $data, count($data)))		{			$errstr = sprintf('XML error: %s at line %d',						xml_error_string(xml_get_error_code($parser)),						xml_get_current_line_number($parser));			$r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);			xml_parser_free($parser);			return $r;		}		xml_parser_free($parser);		// Got ourselves some badness, it seems		if ($this->xh[$pname]['isf'] > 1)		{			if ($this->debug === TRUE)			{				echo "---Invalid Return---\n".$this->xh[$pname]['isf_reason']."---Invalid Return---\n\n";			}			return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['isf_reason']);		}		elseif ( ! is_object($this->xh[$pname]['value']))		{			return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['isf_reason']);		}		// Display XML content for debugging		if ($this->debug === TRUE)		{			echo '<pre>';			if (count($this->xh[$pname]['headers'] > 0))			{				echo "---HEADERS---\n";				foreach ($this->xh[$pname]['headers'] as $header)				{					echo $header."\n";				}				echo "---END HEADERS---\n\n";			}			echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n---PARSED---\n";			var_dump($this->xh[$pname]['value']);			echo "\n---END PARSED---</pre>";		}		// Send response		$v = $this->xh[$pname]['value'];		if ($this->xh[$pname]['isf'])		{			$errno_v = $v->me['struct']['faultCode'];			$errstr_v = $v->me['struct']['faultString'];			$errno = $errno_v->scalarval();			if ($errno === 0)			{				// FAULT returned, errno needs to reflect that				$errno = -1;			}			$r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());		}		else		{			$r = new XML_RPC_Response($v);		}		$r->headers = $this->xh[$pname]['headers'];		return $r;	}	// --------------------------------------------------------------------	// ------------------------------------	//  Begin Return Message Parsing section	// ------------------------------------	// quick explanation of components:	//   ac - used to accumulate values	//   isf - used to indicate a fault	//   lv - used to indicate "looking for a value": implements	//		the logic to allow values with no types to be strings	//   params - used to store parameters in method calls	//   method - used to store method name	//	 stack - array with parent tree of the xml element,	//			 used to validate the nesting of elements	// --------------------------------------------------------------------	/**	 * Start Element Handler	 *	 * @param	string	 * @param	string	 * @return	void	 */	public function open_tag($the_parser, $name)	{		$the_parser = (string) $the_parser;		// If invalid nesting, then return		if ($this->xh[$the_parser]['isf'] > 1) return;		// Evaluate and check for correct nesting of XML elements		if (count($this->xh[$the_parser]['stack']) === 0)		{			if ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')			{				$this->xh[$the_parser]['isf'] = 2;				$this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';				return;			}		}		// not top level element: see if parent is OK		elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))		{			$this->xh[$the_parser]['isf'] = 2;			$this->xh[$the_parser]['isf_reason'] = 'XML-RPC element '.$name.' cannot be child of '.$this->xh[$the_parser]['stack'][0];			return;		}		switch ($name)		{			case 'STRUCT':			case 'ARRAY':				// Creates array for child elements				$cur_val = array('value' => array(), 'type' => $name);				array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);				break;			case 'METHODNAME':			case 'NAME':				$this->xh[$the_parser]['ac'] = '';				break;			case 'FAULT':				$this->xh[$the_parser]['isf'] = 1;				break;			case 'PARAM':				$this->xh[$the_parser]['value'] = NULL;				break;			case 'VALUE':				$this->xh[$the_parser]['vt'] = 'value';				$this->xh[$the_parser]['ac'] = '';				$this->xh[$the_parser]['lv'] = 1;				break;			case 'I4':			case 'INT':			case 'STRING':			case 'BOOLEAN':			case 'DOUBLE':			case 'DATETIME.ISO8601':			case 'BASE64':				if ($this->xh[$the_parser]['vt'] !== 'value')				{					//two data elements inside a value: an error occurred!					$this->xh[$the_parser]['isf'] = 2;					$this->xh[$the_parser]['isf_reason'] = 'There is a '.$name.' element following a '										.$this->xh[$the_parser]['vt'].' element inside a single value';					return;				}				$this->xh[$the_parser]['ac'] = '';				break;			case 'MEMBER':				// Set name of <member> to nothing to prevent errors later if no <name> is found				$this->xh[$the_parser]['valuestack'][0]['name'] = '';				// Set NULL value to check to see if value passed for this param/member				$this->xh[$the_parser]['value'] = NULL;				break;			case 'DATA':			case 'METHODCALL':			case 'METHODRESPONSE':			case 'PARAMS':				// valid elements that add little to processing				break;			default:				/// An Invalid Element is Found, so we have trouble				$this->xh[$the_parser]['isf'] = 2;				$this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;				break;		}		// Add current element name to stack, to allow validation of nesting		array_unshift($this->xh[$the_parser]['stack'], $name);		$name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;	}	// --------------------------------------------------------------------	/**	 * End Element Handler	 *	 * @param	string	 * @param	string	 * @return	void	 */	public function closing_tag($the_parser, $name)	{		$the_parser = (string) $the_parser;		if ($this->xh[$the_parser]['isf'] > 1) return;		// Remove current element from stack and set variable		// NOTE: If the XML validates, then we do not have to worry about		// the opening and closing of elements. Nesting is checked on the opening		// tag so we be safe there as well.		$curr_elem = array_shift($this->xh[$the_parser]['stack']);		switch ($name)		{			case 'STRUCT':			case 'ARRAY':				$cur_val = array_shift($this->xh[$the_parser]['valuestack']);				$this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();				$this->xh[$the_parser]['vt']	= strtolower($name);				break;			case 'NAME':				$this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];				break;			case 'BOOLEAN':			case 'I4':			case 'INT':			case 'STRING':			case 'DOUBLE':			case 'DATETIME.ISO8601':			case 'BASE64':				$this->xh[$the_parser]['vt'] = strtolower($name);				if ($name === 'STRING')				{					$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];				}				elseif ($name === 'DATETIME.ISO8601')				{					$this->xh[$the_parser]['vt']	= $this->xmlrpcDateTime;					$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];				}				elseif ($name === 'BASE64')				{					$this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);				}				elseif ($name === 'BOOLEAN')				{					// Translated BOOLEAN values to TRUE AND FALSE					$this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];				}				elseif ($name=='DOUBLE')				{					// we have a DOUBLE					// we must check that only 0123456789-.<space> are characters here					$this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])										? (float) $this->xh[$the_parser]['ac']										: 'ERROR_NON_NUMERIC_FOUND';				}				else				{					// we have an I4/INT					// we must check that only 0123456789-<space> are characters here					$this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])										? (int) $this->xh[$the_parser]['ac']										: 'ERROR_NON_NUMERIC_FOUND';				}				$this->xh[$the_parser]['ac'] = '';				$this->xh[$the_parser]['lv'] = 3; // indicate we've found a value				break;			case 'VALUE':				// This if() detects if no scalar was inside <VALUE></VALUE>				if ($this->xh[$the_parser]['vt'] == 'value')				{					$this->xh[$the_parser]['value']	= $this->xh[$the_parser]['ac'];					$this->xh[$the_parser]['vt']	= $this->xmlrpcString;				}				// build the XML-RPC value out of the data received, and substitute it				$temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);				if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')				{					// Array					$this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;				}				else				{					// Struct					$this->xh[$the_parser]['value'] = $temp;				}				break;			case 'MEMBER':				$this->xh[$the_parser]['ac'] = '';				// If value add to array in the stack for the last element built				if ($this->xh[$the_parser]['value'])				{					$this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];				}				break;			case 'DATA':				$this->xh[$the_parser]['ac'] = '';				break;			case 'PARAM':				if ($this->xh[$the_parser]['value'])				{					$this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];				}				break;			case 'METHODNAME':				$this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);				break;			case 'PARAMS':			case 'FAULT':			case 'METHODCALL':			case 'METHORESPONSE':				// We're all good kids with nuthin' to do				break;			default:				// End of an Invalid Element. Taken care of during the opening tag though				break;		}	}	// --------------------------------------------------------------------	/**	 * Parse character data	 *	 * @param	string	 * @param	string	 * @return	void	 */	public function character_data($the_parser, $data)	{		$the_parser = (string) $the_parser;		if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already		// If a value has not been found		if ($this->xh[$the_parser]['lv'] !== 3)		{			if ($this->xh[$the_parser]['lv'] === 1)			{				$this->xh[$the_parser]['lv'] = 2; // Found a value			}			if ( ! isset($this->xh[$the_parser]['ac']))			{				$this->xh[$the_parser]['ac'] = '';			}			$this->xh[$the_parser]['ac'] .= $data;		}	}	// --------------------------------------------------------------------	/**	 * Add parameter	 *	 * @param	mixed	 * @return	void	 */	public function addParam($par)	{		$this->params[] = $par;	}	// --------------------------------------------------------------------	/**	 * Output parameters	 *	 * @param	array	$array	 * @return	array	 */	public function output_parameters(array $array = array())	{		$CI =& get_instance();		if ( ! empty($array))		{			foreach ($array as $key => &$value)			{				if (is_array($value))				{					$array[$key] = $this->output_parameters($value);				}				elseif ($key !== 'bits' && $this->xss_clean)				{					// 'bits' is for the MetaWeblog API image bits					// @todo - this needs to be made more general purpose					$array[$key] = $CI->security->xss_clean($value);				}			}			return $array;		}		$parameters = array();		for ($i = 0, $c = count($this->params); $i < $c; $i++)		{			$a_param = $this->decode_message($this->params[$i]);			if (is_array($a_param))			{				$parameters[] = $this->output_parameters($a_param);			}			else			{				$parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;			}		}		return $parameters;	}	// --------------------------------------------------------------------	/**	 * Decode message	 *	 * @param	object	 * @return	mixed	 */	public function decode_message($param)	{		$kind = $param->kindOf();		if ($kind === 'scalar')		{			return $param->scalarval();		}		elseif ($kind === 'array')		{			reset($param->me);			$b = current($param->me);			$arr = array();			for ($i = 0, $c = count($b); $i < $c; $i++)			{				$arr[] = $this->decode_message($param->me['array'][$i]);			}			return $arr;		}		elseif ($kind === 'struct')		{			reset($param->me['struct']);			$arr = array();			foreach ($param->me['struct'] as $key => &$value)			{				$arr[$key] = $this->decode_message($value);			}			return $arr;		}	}} // END XML_RPC_Message Class/** * XML-RPC Values class * * @category	XML-RPC * @author		EllisLab Dev Team * @link		https://codeigniter.com/user_guide/libraries/xmlrpc.html */class XML_RPC_Values extends CI_Xmlrpc{	/**	 * Value data	 *	 * @var	array	 */	public $me	= array();	/**	 * Value type	 *	 * @var	int	 */	public $mytype	= 0;	// --------------------------------------------------------------------	/**	 * Constructor	 *	 * @param	mixed	$val	 * @param	string	$type	 * @return	void	 */	public function __construct($val = -1, $type = '')	{		parent::__construct();		if ($val !== -1 OR $type !== '')		{			$type = $type === '' ? 'string' : $type;			if ($this->xmlrpcTypes[$type] == 1)			{				$this->addScalar($val, $type);			}			elseif ($this->xmlrpcTypes[$type] == 2)			{				$this->addArray($val);			}			elseif ($this->xmlrpcTypes[$type] == 3)			{				$this->addStruct($val);			}		}	}	// --------------------------------------------------------------------	/**	 * Add scalar value	 *	 * @param	scalar	 * @param	string	 * @return	int	 */	public function addScalar($val, $type = 'string')	{		$typeof = $this->xmlrpcTypes[$type];		if ($this->mytype === 1)		{			echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';			return 0;		}		if ($typeof != 1)		{			echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';			return 0;		}		if ($type === $this->xmlrpcBoolean)		{			$val = (int) (strcasecmp($val, 'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));		}		if ($this->mytype === 2)		{			// adding to an array here			$ar = $this->me['array'];			$ar[] = new XML_RPC_Values($val, $type);			$this->me['array'] = $ar;		}		else		{			// a scalar, so set the value and remember we're scalar			$this->me[$type] = $val;			$this->mytype = $typeof;		}		return 1;	}	// --------------------------------------------------------------------	/**	 * Add array value	 *	 * @param	array	 * @return	int	 */	public function addArray($vals)	{		if ($this->mytype !== 0)		{			echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';			return 0;		}		$this->mytype = $this->xmlrpcTypes['array'];		$this->me['array'] = $vals;		return 1;	}	// --------------------------------------------------------------------	/**	 * Add struct value	 *	 * @param	object	 * @return	int	 */	public function addStruct($vals)	{		if ($this->mytype !== 0)		{			echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';			return 0;		}		$this->mytype = $this->xmlrpcTypes['struct'];		$this->me['struct'] = $vals;		return 1;	}	// --------------------------------------------------------------------	/**	 * Get value type	 *	 * @return	string	 */	public function kindOf()	{		switch ($this->mytype)		{			case 3: return 'struct';			case 2: return 'array';			case 1: return 'scalar';			default: return 'undef';		}	}	// --------------------------------------------------------------------	/**	 * Serialize data	 *	 * @param	string	 * @param	mixed	 * @return	string	 */	public function serializedata($typ, $val)	{		$rs = '';		switch ($this->xmlrpcTypes[$typ])		{			case 3:				// struct				$rs .= "<struct>\n";				reset($val);				foreach ($val as $key2 => &$val2)				{					$rs .= "<member>\n<name>{$key2}</name>\n".$this->serializeval($val2)."</member>\n";				}				$rs .= '</struct>';				break;			case 2:				// array				$rs .= "<array>\n<data>\n";				for ($i = 0, $c = count($val); $i < $c; $i++)				{					$rs .= $this->serializeval($val[$i]);				}				$rs .= "</data>\n</array>\n";				break;			case 1:				// others				switch ($typ)				{					case $this->xmlrpcBase64:						$rs .= '<'.$typ.'>'.base64_encode( (string) $val).'</'.$typ.">\n";						break;					case $this->xmlrpcBoolean:						$rs .= '<'.$typ.'>'.( (bool) $val ? '1' : '0').'</'.$typ.">\n";						break;					case $this->xmlrpcString:						$rs .= '<'.$typ.'>'.htmlspecialchars( (string) $val).'</'.$typ.">\n";						break;					default:						$rs .= '<'.$typ.'>'.$val.'</'.$typ.">\n";						break;				}			default:				break;		}		return $rs;	}	// --------------------------------------------------------------------	/**	 * Serialize class	 *	 * @return	string	 */	public function serialize_class()	{		return $this->serializeval($this);	}	// --------------------------------------------------------------------	/**	 * Serialize value	 *	 * @param	object	 * @return	string	 */	public function serializeval($o)	{		$array = $o->me;		list($value, $type) = array(reset($array), key($array));		return "<value>\n".$this->serializedata($type, $value)."</value>\n";	}	// --------------------------------------------------------------------	/**	 * Scalar value	 *	 * @return	mixed	 */	public function scalarval()	{		return reset($this->me);	}	// --------------------------------------------------------------------	/**	 * Encode time in ISO-8601 form.	 * Useful for sending time in XML-RPC	 *	 * @param	int	unix timestamp	 * @param	bool	 * @return	string	*/	public function iso8601_encode($time, $utc = FALSE)	{		return ($utc) ? strftime('%Y%m%dT%H:%i:%s', $time) : gmstrftime('%Y%m%dT%H:%i:%s', $time);	}} // END XML_RPC_Values Class
 |