";
if(!strstr($key, " attr")){ #if it's not an attribute
if(array_key_exists("$key attr", $data)){
while(list($attr_name, $attr_value) = each($data["$key attr"])){
#echo "Found attribute $attribute_name with value $attribute_value
";
$attr_value = &htmlspecialchars($attr_value, ENT_QUOTES);
$attributes .= " $attr_name=\"$attr_value\"";
}
}
if(is_numeric($key)){
#echo "My current key ($key) is numeric. My parent key is '$prior_key'
";
$key = $prior_key;
}else{
#you can't have numeric keys at two levels in a row, so this is ok
#echo "Checking to see if a numeric key exists in data.";
if(is_array($value) and array_key_exists(0, $value)){
# echo " It does! Calling myself as a result of a numeric array.
";
$numeric_array = true;
$xml_serialized_string .= XML_serialize($value, $level, $key);
}
#echo "
";
}
if(!$numeric_array){
$xml_serialized_string .= str_repeat("\t", $level) . "<$key$attributes>";
if(is_array($value)){
$xml_serialized_string .= "\r\n" . XML_serialize($value, $level+1);
}else{
$inline = true;
$xml_serialized_string .= htmlspecialchars($value);
}
$xml_serialized_string .= (!$inline ? str_repeat("\t", $level) : "") . "$key>\r\n";
}
}else{
#echo "Skipping attribute record for key $key
";
}
}
if($level == 0){
$xml_serialized_string = "\r\n" . $xml_serialized_string;
return $xml_serialized_string;
}else{
return $xml_serialized_string;
}
}
class XML {
var $parser; #a reference to the XML parser
var $document; #the entire XML structure built up so far
var $current; #a pointer to the current item - what is this
var $parent; #a pointer to the current parent - the parent will be an array
var $parents; #an array of the most recent parent at each level
var $last_opened_tag;
function XML($data=null){
$this->parser = xml_parser_create();
xml_parser_set_option ($this->parser, XML_OPTION_CASE_FOLDING, 0);
xml_set_object($this->parser, &$this);
xml_set_element_handler($this->parser, "open", "close");
xml_set_character_data_handler($this->parser, "data");
# register_shutdown_function(array(&$this, 'destruct'));
}
function destruct(){
xml_parser_free($this->parser);
}
function parse($data){
$this->document = array();
$this->parent = &$this->document;
$this->parents = array();
$this->last_opened_tag = NULL;
xml_parse($this->parser, $data);
return $this->document;
}
function open($parser, $tag, $attributes){
#echo "Opening tag $tag
\n";
$this->data = "";
$this->last_opened_tag = $tag; #tag is a string
if(array_key_exists($tag, $this->parent)){
#echo "There's already an instance of '$tag' at the current level ($level)
\n";
if(is_array($this->parent[$tag]) and array_key_exists(0, $this->parent[$tag])){ #if the keys are numeric
#need to make sure they're numeric (account for attributes)
$key = count_numeric_items($this->parent[$tag]);
#echo "There are $key instances: the keys are numeric.
\n";
}else{
#echo "There is only one instance. Shifting everything around
\n";
$temp = &$this->parent[$tag];
unset($this->parent[$tag]);
$this->parent[$tag][0] = &$temp;
if(array_key_exists("$tag attr", $this->parent)){
#shift the attributes around too if they exist
$temp = &$this->parent["$tag attr"];
unset($this->parent["$tag attr"]);
$this->parent[$tag]["0 attr"] = &$temp;
}
$key = 1;
}
$this->parent = &$this->parent[$tag];
}else{
$key = $tag;
}
if($attributes){
$this->parent["$key attr"] = $attributes;
}
$this->parent[$key] = array();
$this->parent = &$this->parent[$key];
array_unshift($this->parents, &$this->parent);
}
function data($parser, $data){
#echo "Data is '", htmlspecialchars($data), "'
\n";
if($this->last_opened_tag != NULL){
$this->data .= $data;
}
}
function close($parser, $tag){
#echo "Close tag $tag
\n";
if($this->last_opened_tag == $tag){
$this->parent = $this->data;
$this->last_opened_tag = NULL;
}
array_shift($this->parents);
$this->parent = &$this->parents[0];
}
}
function & XML_unserialize(&$xml){
$xml_parser = new XML();
$data = &$xml_parser->parse(&$xml);
$xml_parser->destruct();
return $data;
}
function & XMLRPC_parse(&$request){
if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_parse', "
Received the following raw request:
" . XMLRPC_show($request, 'print_r', true)); } $data = &XML_unserialize(&$request); if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ XMLRPC_debug('XMLRPC_parse', "Returning the following parsed request:
" . XMLRPC_show($data, 'print_r', true)); } return $data; } function & XMLRPC_prepare($data, $type = NULL){ if(is_array($data)){ $num_elements = count($data); if((array_key_exists(0, $data) or !$num_elements) and $type != 'struct'){ #it's an array if(!$num_elements){ #if the array is empty $returnvalue = array('array' => array('data' => NULL)); }else{ $returnvalue['array']['data']['value'] = array(); $temp = &$returnvalue['array']['data']['value']; $count = count_numeric_items($data); for($n=0; $n<$count; $n++){ $type = NULL; if(array_key_exists("$n type", $data)){ $type = $data["$n type"]; } $temp[$n] = XMLRPC_prepare(&$data[$n], $type); } } }else{ #it's a struct if(!$num_elements){ #if the struct is empty $returnvalue = array('struct' => NULL); }else{ $returnvalue['struct']['member'] = array(); $temp = &$returnvalue['struct']['member']; while(list($key, $value) = each($data)){ if(substr($key, -5) != ' type'){ #if it's not a type specifier $type = NULL; if(array_key_exists("$key type", $data)){ $type = $data["$key type"]; } $temp[] = array('name' => $key, 'value' => XMLRPC_prepare(&$value, $type)); } } } } }else{ #it's a scalar if(!$type){ if(is_int($data)){ $returnvalue['int'] = $data; return $returnvalue; }elseif(is_float($data)){ $returnvalue['double'] = $data; return $returnvalue; }elseif(is_bool($data)){ $returnvalue['boolean'] = ($data ? 1 : 0); return $returnvalue; }elseif(preg_match('/^\d{8}T\d{2}:\d{2}:\d{2}$/', $data, $matches)){ #it's a date $returnvalue['dateTime.iso8601'] = $data; return $returnvalue; }elseif(is_string($data)){ $returnvalue['string'] = htmlspecialchars($data); return $returnvalue; } }else{ $returnvalue[$type] = htmlspecialchars($data); } } return $returnvalue; } function & XMLRPC_adjustValue(&$current_node){ if(is_array($current_node)){ if(isset($current_node['array'])){ if(!is_array($current_node['array']['data'])){ #If there are no elements, return an empty array return array(); }else{ #echo "Getting rid of array -> data -> valueReceived the following parameter list to send:
" . XMLRPC_show($params, 'print_r', true)); } $conn = fsockopen ($site, $port); #open the connection if(!$conn){ #if the connection was not opened successfully if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ XMLRPC_debug('XMLRPC_request', "Connection failed: Couldn't make the connection to $site.
"); } return array(false, array('faultCode'=>10532, 'faultString'=>"Connection failed: Couldn't make the connection to $site.")); }else{ $headers = "POST $location HTTP/1.0\r\n" . "Host: $site\r\n" . "Connection: close\r\n" . ($user_agent ? "User-Agent: $user_agent\r\n" : '') . "Content-Type: text/xml\r\n" . "Content-Length: " . strlen($data) . "\r\n\r\n"; fputs($conn, "$headers"); fputs($conn, $data); if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ XMLRPC_debug('XMLRPC_request', "Sent the following request:
\n\n" . XMLRPC_show($headers . $data, 'print_r', true)); } #socket_set_blocking ($conn, false); $response = ""; while(!feof($conn)){ $response .= fgets($conn, 1024); } fclose($conn); #strip headers off of response $responsesubstr = substr($response, strpos($response, "\r\n\r\n")+4); $data = XML_unserialize($responsesubstr); if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ XMLRPC_debug('XMLRPC_request', "Received the following response:
\n\n" . XMLRPC_show($response, 'print_r', true) . "Which was serialized into the following data:
\n\n" . XMLRPC_show($data, 'print_r', true)); } if(isset($data['methodResponse']['fault'])){ $return = array(false, XMLRPC_adjustValue(&$data['methodResponse']['fault']['value'])); if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ XMLRPC_debug('XMLRPC_request', "Returning:
\n\n" . XMLRPC_show($return, 'var_dump', true)); } return $return; }else{ $return = array(true, XMLRPC_adjustValue(&$data['methodResponse']['params']['param']['value'])); if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ XMLRPC_debug('XMLRPC_request', "Returning:
\n\n" . XMLRPC_show($return, 'var_dump', true)); } return $return; } } } function XMLRPC_response($return_value, $server = NULL){ $data["methodResponse"]["params"]["param"]["value"] = &$return_value; $return = XML_serialize(&$data); if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ XMLRPC_debug('XMLRPC_response', "Received the following data to return:
\n\n" . XMLRPC_show($return_value, 'print_r', true)); } header("Connection: close"); header("Content-Length: " . strlen($return)); header("Content-Type: text/xml"); header("Date: " . date("r")); if($server){ header("Server: $server"); } if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ XMLRPC_debug('XMLRPC_response', "Sent the following response:
\n\n" . XMLRPC_show($return, 'print_r', true)); } echo $return; } function XMLRPC_error($faultCode, $faultString, $server = NULL){ $array["methodResponse"]["fault"]["value"]["struct"]["member"] = array(); $temp = &$array["methodResponse"]["fault"]["value"]["struct"]["member"]; $temp[0]["name"] = "faultCode"; $temp[0]["value"]["int"] = $faultCode; $temp[1]["name"] = "faultString"; $temp[1]["value"]["string"] = $faultString; $return = XML_serialize($array); header("Connection: close"); header("Content-Length: " . strlen($return)); header("Content-Type: text/xml"); header("Date: " . date("r")); if($server){ header("Server: $server"); } if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ XMLRPC_debug('XMLRPC_error', "Sent the following error response:
\n\n" . XMLRPC_show($return, 'print_r', true)); } echo $return; } function XMLRPC_convert_timestamp_to_iso8601($timestamp){ #takes a unix timestamp and converts it to iso8601 required by XMLRPC #an example iso8601 datetime is "20010822T03:14:33" return date("Ymd\TH:i:s", $timestamp); } function XMLRPC_convert_iso8601_to_timestamp($iso8601){ return strtotime($iso8601); } function count_numeric_items(&$array){ return is_array($array) ? count(array_filter(array_keys($array), 'is_numeric')) : 0; } function XMLRPC_debug($function_name, $debug_message){ $GLOBALS['XMLRPC_DEBUG_INFO'][] = array($function_name, $debug_message); } function XMLRPC_debug_print(){ if($GLOBALS['XMLRPC_DEBUG_INFO']){ echo "$debug[0] | $debug[1] |
---|
No debugging information available yet.
"; } } function XMLRPC_show($data, $func = "print_r", $return_str = false){ ob_start(); $func($data); $output = ob_get_contents(); ob_end_clean(); if($return_str){ return "" . htmlspecialchars($output) . "\n"; }else{ echo "
", htmlspecialchars($output), "\n"; } } ?>