XML-RPC library from the Internet, for the development of small external communication interface is very useful, save this code as a xml-rpc.inc.php
The code is as follows:
/*
XML-RPC library from the Internet, very useful for developing small external communication interfaces
*/
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'
";
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 ):"")." \ 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, 'destoct '));
}
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 und
\ 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 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
\ 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
\ 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 )."
\ 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 )."
\ N ";
}
} Else {
# Echo "Passing name $ temp [name]
\ 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'
\ N ";
$ Temp = $ current_node [$ type];
# Echo "adjustValue (): The current node is set with a type of $ type
\ N ";
$ Fell_through = false;
Break;
}
}
If ($ fell_through ){
$ Type = 'string ';
# Echo "Fell through! Type is $ type
\ 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
\ 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
";
$ 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 ',"
Specified ed 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 ";
Fputs ($ conn, "$ headers ");
Fputs ($ conn, $ data );
If (defined ('xmlrpc _ debug') and XMLRPC_DEBUG ){
XMLRPC_debug ('xmlrpc _ request ',"
Sent the following request:
\ 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") + 4 ));
If (defined ('xmlrpc _ debug') and XMLRPC_DEBUG ){
XMLRPC_debug ('xmlrpc _ request ',"
Stored ed the following response:
\ N ". XMLRPC_show ($ response, 'print _ R', true )."
Which was serialized into the following data:
\ N ". XMLRPC_show ($ data, 'print _ R', true ));
}
If (isset ($ data ['methodresponse'] ['faresult']) {
$ Return = array (false, XMLRPC_adjustValue ($ data ['methodresponse'] ['result'] ['value']);
If (defined ('xmlrpc _ debug') and XMLRPC_DEBUG ){
XMLRPC_debug ('xmlrpc _ request ',"
Returning:
\ 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 ". 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 ',"
Stored ed the following data to return:
\ 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 ". 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 ". 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 "20034722t03: 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"
\ N ";Foreach ($ GLOBALS ['xmlrpc _ DEBUG_INFO '] as $ debug ){Echo"
$ Debug [0] |
$ Debug [1] |
\ N ";}Echo"
\ N ";
Unset ($ GLOBALS ['xmlrpc _ DEBUG_INFO ']);
} Else {
Echo"
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 ";
}
}
?>
Server Program example, server. php
The code is as follows:
Include 'XML-rpc. inc. php ';
// Define a method that can be called Remotely
$ Xmlrpc_methods = array ();
$ Xmlrpc_methods ['insertrecords '] = 'insertrecords ';
// Obtain the method name and parameter passed in by the user
$ 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', "the method you are calling does not exist ");
} Else {
$ Xmlrpc_methods [$ methodName] ($ params );
}
Function insertRecords ($ params ){
If (emptyempty ($ params )){
XMLRPC_error ('2', "Parameter error ");
}
XMLRPC_response (XMLRPC_prepare ('http: // www.emtit.com '));
}
?>
Example of a PHP client calling a server method
The code is as follows:
Include_once 'XML-rpc. Inc ';
$ Params = array (2, 3 );
$ Result = XMLRPC_request ("127.0.0.1", "/services/server. php", "insertRecords", $ params); // put the server file in the services folder
Print_r ($ result );
?>
The result is www.emtiit.com.