php xml-rpc远程调用


Posted in PHP onDecember 19, 2008
<?php 
/* 
从网上找来的XML-RPC库,对于开发小型的外部通讯接口很有用 
*/ function & XML_serialize($data, $level = 0, $prior_key = NULL){ 
#assumes a hash, keys are the variable names 
$xml_serialized_string = ""; 
while(list($key, $value) = each($data)){ 
$inline = false; 
$numeric_array = false; 
$attributes = ""; 
#echo "My current key is '$key', called with prior key '$prior_key'<br>"; 
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<br>"; 
$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'<br>"; 
$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.<br>"; 
$numeric_array = true; 
$xml_serialized_string .= XML_serialize($value, $level, $key); 
} 
#echo "<br>"; 
} 
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<bR>"; 
} 
} 
if($level == 0){ 
$xml_serialized_string = "<?xml version=\"1.0\" ?>\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<br>\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)<br>\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.<br>\n"; 
}else{ 
#echo "There is only one instance. Shifting everything around<br>\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), "'<br>\n"; 
if($this->last_opened_tag != NULL){ 
$this->data .= $data; 
} 
} 
function close($parser, $tag){ 
#echo "Close tag $tag<br>\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', "<p>Received the following raw request:</p>" . XMLRPC_show($request, 'print_r', true)); 
} 
$data = &XML_unserialize($request); 
if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ 
XMLRPC_debug('XMLRPC_parse', "<p>Returning the following parsed request:</p>" . 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 emptyempty 
$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 emptyempty 
$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 emptyempty array 
return array(); 
}else{ 
#echo "Getting rid of array -> data -> value<br>\n"; 
$temp = $current_node['array']['data']['value']; 
if(is_array($temp) and array_key_exists(0, $temp)){ 
$count = count($temp); 
for($n=0;$n<$count;$n++){ 
$temp2[$n] = &XMLRPC_adjustValue($temp[$n]); 
} 
$temp = $temp2; 
}else{ 
$temp2 = &XMLRPC_adjustValue($temp); 
$temp = array($temp2); 
#I do the temp assignment because it avoids copying, 
# since I can put a reference in the array 
#PHP's reference model is a bit silly, and I can't just say: 
# $temp = array(&XMLRPC_adjustValue($temp)); 
} 
} 
}elseif(isset($current_node['struct'])){ 
if(!is_array($current_node['struct'])){ 
#If there are no members, return an emptyempty array 
return array(); 
}else{ 
#echo "Getting rid of struct -> member<br>\n"; 
$temp = $current_node['struct']['member']; 
if(is_array($temp) and array_key_exists(0, $temp)){ 
$count = count($temp); 
for($n=0;$n<$count;$n++){ 
#echo "Passing name {$temp[$n][name]}. Value is: " . show($temp[$n][value], var_dump, true) . "<br>\n"; 
$temp2[$temp[$n]['name']] = &XMLRPC_adjustValue($temp[$n]['value']); 
#echo "adjustValue(): After assigning, the value is " . show($temp2[$temp[$n]['name']], var_dump, true) . "<br>\n"; 
} 
}else{ 
#echo "Passing name $temp[name]<br>\n"; 
$temp2[$temp['name']] = &XMLRPC_adjustValue($temp['value']); 
} 
$temp = $temp2; 
} 
}else{ 
$types = array('string', 'int', 'i4', 'double', 'dateTime.iso8601', 'base64', 'boolean'); 
$fell_through = true; 
foreach($types as $type){ 
if(array_key_exists($type, $current_node)){ 
#echo "Getting rid of '$type'<br>\n"; 
$temp = $current_node[$type]; 
#echo "adjustValue(): The current node is set with a type of $type<br>\n"; 
$fell_through = false; 
break; 
} 
} 
if($fell_through){ 
$type = 'string'; 
#echo "Fell through! Type is $type<br>\n"; 
} 
switch ($type){ 
case 'int': case 'i4': $temp = (int)$temp; break; 
case 'string': $temp = (string)$temp; break; 
case 'double': $temp = (double)$temp; break; 
case 'boolean': $temp = (bool)$temp; break; 
} 
} 
}else{ 
$temp = (string)$current_node; 
} 
return $temp; 
} 
function XMLRPC_getParams($request){ 
if(!is_array($request['methodCall']['params'])){ 
#If there are no parameters, return an emptyempty array 
return array(); 
}else{ 
#echo "Getting rid of methodCall -> params -> param<br>\n"; 
$temp = $request['methodCall']['params']['param']; 
if(is_array($temp) and array_key_exists(0, $temp)){ 
$count = count($temp); 
for($n = 0; $n < $count; $n++){ 
#echo "Serializing parameter $n<br>"; 
$temp2[$n] = &XMLRPC_adjustValue($temp[$n]['value']); 
} 
}else{ 
$temp2[0] = &XMLRPC_adjustValue($temp['value']); 
} 
$temp = $temp2; 
return $temp; 
} 
} 
function XMLRPC_getMethodName($methodCall){ 
#returns the method name 
return $methodCall['methodCall']['methodName']; 
} 
function XMLRPC_request($site, $location, $methodName, $params = NULL, $user_agent = NULL){ 
$site = explode(':', $site); 
if(isset($site[1]) and is_numeric($site[1])){ 
$port = $site[1]; 
}else{ 
$port = 80; 
} 
$site = $site[0]; 
$data["methodCall"]["methodName"] = $methodName; 
$param_count = count($params); 
if(!$param_count){ 
$data["methodCall"]["params"] = NULL; 
}else{ 
for($n = 0; $n<$param_count; $n++){ 
$data["methodCall"]["params"]["param"][$n]["value"] = $params[$n]; 
} 
} 
$data = XML_serialize($data); 
if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ 
XMLRPC_debug('XMLRPC_request', "<p>Received the following parameter list to send:</p>" . 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', "<p>Connection failed: Couldn't make the connection to $site.</p>"); 
} 
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', "<p>Sent the following request:</p>\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 
$data = XML_unserialize(substr($response, strpos($response, "\r\n\r\n")+4)); 
if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ 
XMLRPC_debug('XMLRPC_request', "<p>Received the following response:</p>\n\n" . XMLRPC_show($response, 'print_r', true) . "<p>Which was serialized into the following data:</p>\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', "<p>Returning:</p>\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', "<p>Returning:</p>\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', "<p>Received the following data to return:</p>\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', "<p>Sent the following response:</p>\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', "<p>Sent the following error response:</p>\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 "<table border=\"1\" width=\"100%\">\n"; 
foreach($GLOBALS['XMLRPC_DEBUG_INFO'] as $debug){ 
echo "<tr><th style=\"vertical-align: top\">$debug[0]</th><td>$debug[1]</td></tr>\n"; 
} 
echo "</table>\n"; 
unset($GLOBALS['XMLRPC_DEBUG_INFO']); 
}else{ 
echo "<p>No debugging information available yet.</p>"; 
} 
} 
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 "<pre>" . htmlspecialchars($output) . "</pre>\n"; 
}else{ 
echo "<pre>", htmlspecialchars($output), "</pre>\n"; 
} 
} 
?>

服务端程序例子,server.php
<? 
include 'xml-rpc.inc.php'; 
//定义可被远程调用的方法 
$xmlrpc_methods=array(); 
$xmlrpc_methods['insertRecords']='insertRecords'; //获得用户传入的方法名和参数 
$xmlrpc_request = XMLRPC_parse($HTTP_RAW_POST_DATA); 
$methodName = XMLRPC_getMethodName($xmlrpc_request); 
$params = XMLRPC_getParams($xmlrpc_request); 
if (!isset($xmlrpc_methods[$methodName])){ 
XMLRPC_error('1',"你所调用的方法不存在"); 
}else { 
$xmlrpc_methods[$methodName]($params); 
} 
function insertRecords($params){ 
if (emptyempty($params)){ 
XMLRPC_error('2',"参数出错"); 
} 
XMLRPC_response(XMLRPC_prepare('http://www.emtit.com')); 
} 
?>

PHP客户端调用服务端方法例子
<?php 
include_once 'xml-rpc.inc'; 
$params=array(2,3); 
$result=XMLRPC_request("127.0.0.1","/services/server.php","insertRecords",$params);//服务端文件放在services文件夹下 
print_r($result); 
?>

结果会显示www.emtiit.com
PHP 相关文章推荐
PHP初学者头疼问题总结
Jul 08 PHP
php获得当前的脚本网址
Dec 10 PHP
php获取地址栏信息的代码
Oct 08 PHP
php中jQuery插件autocomplate的简单使用笔记
Jun 14 PHP
记录mysql性能查询过程的使用方法
May 02 PHP
在PHP中设置、使用、删除Cookie的解决方法
May 06 PHP
php防止sql注入示例分析和几种常见攻击正则表达式
Jan 12 PHP
Linux下PHP安装mcrypt扩展模块笔记
Sep 10 PHP
php常用的安全过滤函数集锦
Oct 09 PHP
php自动加载方式集合
Apr 04 PHP
php mysql实现mysql_select_db选择数据库
Dec 30 PHP
AJAX的使用方法详解
Apr 29 PHP
php 设计模式之 工厂模式
Dec 19 #PHP
php 设计模式之 单例模式
Dec 19 #PHP
PHP 采集程序 常用函数
Dec 18 #PHP
php IP及IP段进行访问限制的代码
Dec 17 #PHP
php mssql 数据库分页SQL语句
Dec 16 #PHP
linux下 C语言对 php 扩展
Dec 14 #PHP
php 文件状态缓存带来的问题
Dec 14 #PHP
You might like
PHP中的正规表达式(二)
2006/10/09 PHP
php检测网页是否被百度收录的函数代码
2013/10/09 PHP
Laravel中的Blade模板引擎示例详解
2017/10/10 PHP
php微信开发之图片回复功能
2018/06/14 PHP
PHP反射学习入门示例
2019/06/14 PHP
Javascript下的keyCode键码值表
2007/04/10 Javascript
javascript addBookmark 加入收藏 多浏览器兼容
2009/08/15 Javascript
表单序列化与jq中的serialize使用示例
2014/02/21 Javascript
JQuery 图片滚动轮播示例代码
2014/03/24 Javascript
再探JavaScript作用域
2014/09/24 Javascript
js正则表达式验证邮件地址
2015/11/12 Javascript
利用require.js与angular搭建spa应用的方法实例
2017/07/19 Javascript
带你了解session和cookie作用原理区别和用法
2017/08/14 Javascript
vue.js在标签属性中插入变量参数的方法
2018/03/06 Javascript
基于jQuery实现的设置文本区域的光标位置
2018/06/15 jQuery
默认浏览器设置及vue自动打开页面的方法
2018/09/21 Javascript
解决vue更新路由router-view复用组件内容不刷新的问题
2019/11/04 Javascript
python网络编程之TCP通信实例和socketserver框架使用例子
2014/04/25 Python
解决pycharm无法调用pip安装的包问题
2018/05/18 Python
Python 实现Windows开机运行某软件的方法
2018/10/14 Python
python实现随机漫步方法和原理
2019/06/10 Python
Django Admin中增加导出CSV功能过程解析
2019/09/04 Python
Python实现打印实心和空心菱形
2019/11/23 Python
Python GUI库PyQt5图形和特效样式QSS介绍
2020/02/25 Python
python对文件的操作方法汇总
2020/02/28 Python
详解Pycharm出现out of memory的终极解决方法
2020/03/03 Python
浅谈Python中range与Numpy中arange的比较
2020/03/11 Python
Django mysqlclient安装和使用详解
2020/09/17 Python
Boda Skins皮衣官网:奢侈皮夹克,全球配送
2016/12/15 全球购物
新加坡网上化妆品店:Best Buy World
2018/05/18 全球购物
英国电子产品购物网站:Tech in the basket
2019/11/08 全球购物
元旦晚会上单位领导演讲稿
2014/01/05 职场文书
财务会计人员求职的自我评价
2014/01/13 职场文书
调查研究项目计划书
2014/04/29 职场文书
幼儿园小班教学反思
2016/03/03 职场文书
Spring Boot 使用 Spring-Retry 进行重试框架
2022/04/24 Java/Android