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 相关文章推荐
用文本文件制作留言板提示(下)
Oct 09 PHP
php中用文本文件做数据库的实现方法
Mar 27 PHP
PHP PDO函数库详解
Apr 27 PHP
PHP Stream_*系列函数
Aug 01 PHP
浅析php中抽象类和接口的概念以及区别
Jun 27 PHP
php Imagick获取图片RGB颜色值
Jul 28 PHP
php对文件夹进行相关操作(遍历、计算大小)
Nov 04 PHP
php生成Android客户端扫描可登录的二维码
May 13 PHP
浅谈PHP eval()函数定义和用法
Jun 21 PHP
PHP实现深度优先搜索算法(DFS,Depth First Search)详解
Sep 16 PHP
深入研究PHP中的preg_replace和代码执行
Aug 15 PHP
详解PHP设计模式之依赖注入模式
May 25 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数组应该有多大的分析
2009/07/30 PHP
完美解决thinkphp验证码出错无法显示的方法
2014/12/09 PHP
PHP压缩图片功能的介绍
2019/03/21 PHP
关于Javascript 的 prototype问题。
2007/01/03 Javascript
ExtJS Grid使用SimpleStore、多选框的方法
2009/11/20 Javascript
JavaScript 设计模式 富有表现力的Javascript(一)
2010/05/26 Javascript
js自动闭合html标签(自动补全html标记)
2012/10/04 Javascript
jquery配合css简单实现返回顶部效果
2013/09/30 Javascript
利用jquery写的左右轮播图特效
2014/02/12 Javascript
innerHTML在IE中报错解决方案
2014/12/15 Javascript
使用JavaScript的AngularJS库编写hello world的方法
2015/06/23 Javascript
javascript基本语法
2016/05/31 Javascript
node.js cookie-parser 中间件介绍
2016/06/06 Javascript
jQuery Dialog 打开时自动聚焦的解决方法(两种方法)
2016/11/24 Javascript
重新理解JavaScript的六种继承方式
2017/03/24 Javascript
Angular.js组件之input mask对input输入进行格式化详解
2017/07/10 Javascript
前端把html表格生成为excel表格的实例
2017/09/19 Javascript
Angular-UI Bootstrap组件实现警报功能
2018/07/16 Javascript
layui 设置table 行的高度方法
2018/08/17 Javascript
如何优雅的在一台vps(云主机)上面部署vue+mongodb+express项目
2019/01/20 Javascript
jQuery实现当拉动滚动条到底部加载数据的方法分析
2019/01/24 jQuery
antd form表单数据回显操作
2020/11/02 Javascript
使用python开发vim插件及心得分享
2014/11/04 Python
python通过smpt发送邮件的方法
2015/04/30 Python
python爬虫获取小区经纬度以及结构化地址
2018/12/30 Python
把pandas转换int型为str型的方法
2019/01/29 Python
python中time.ctime()实例用法
2021/02/03 Python
基于ccs3的timeline时间线实现方法
2020/04/30 HTML / CSS
The Hut英国:英国领先的豪华在线百货商店
2019/07/26 全球购物
俄罗斯皮肤健康中心:Pharmacosmetica.ru
2020/02/22 全球购物
服装设计行业个人的自我评价
2013/12/20 职场文书
新春文艺演出主持词
2014/03/27 职场文书
物流专业自荐信
2014/05/23 职场文书
中国在我心中演讲稿
2014/09/13 职场文书
2014幼儿园保育员工作总结
2014/11/10 职场文书
python geopandas读取、创建shapefile文件的方法
2021/06/29 Python