You probably know by know that I’ve been playing with PEAR and XML-RPC a lot lately. Well when reading an excellent book called Advanced PHP Programming
I came across a small section on XML-RPC autodiscovery. This seemed like an interesting thing to me (no, really it did), so I decided to have a play.
Now my only problem with this book is that most of the stuff is written for PHP5. This wouldn’t be so bad (PHP 5 looks to have to great improvements), except for the fact that most of the web servers I have to work on all run PHP 4.
So, for the benefit of the human race, I’ve re-written the script so that it will work in PHP4:
require_once('XML/RPC.php');
$url = parse_url('http://www.oreillynet.com/meerkat/xml-rpc/server.php');
$cli = new XML_RPC_Client($url['path'], $url['host']);
$msg = new XML_RPC_Message('system.listMethods');
$resp = $cli->send($msg);
if($resp->faultCode())
{
echo "** ERROR **n";
echo 'Fault Code: ' . $result->faultCode() . "n";
echo 'Fault Reason: ' . $result->faultString() . "n";
exit;
}
$methods = XML_RPC_decode($resp->value());
foreach($methods as $method)
{
print "Method $method:n";
$oDoc = $cli->send(
new XML_RPC_Message('system.methodHelp',
array( new XML_RPC_Value($method) ))
);
$doc = XML_RPC_decode( $oDoc->value() );
if($doc)
{
print "$docn";
}
else
{
print "No Docstringn";
}
$msg = new XML_RPC_Message('system.methodSignature',
array(new XML_RPC_Value($method)));
$oResp = $cli->send($msg);
$resp = $oResp->value();
if($resp->kindOf() == 'array')
{
$sigs = XML_RPC_decode($resp);
for($i = 0; $i < count($sigs); $i++)
{
$return = array_shift($sigs[$i]);
$params = implode(", ", $sigs[$i]);
print "Signature #$i: $return $method($params)n";
}
}
else
{
print "No Signaturen";
}
print "n";
}
Save this file as something like rpc-test.php and you can run this from the command line like this:
php -f rpc-test.php
Depending on the server you point it at, you will get output like the following (in this case from Meerkat, O’Reilly Network’s Open Wire Service):
Method meerkat.getChannels:
Returns an array of structs of available RSS channels each with its associated channel Id.
Signature #0: array meerkat.getChannels()
Method meerkat.getCategories:
Returns an array of structs of available Meerkat categories each with its associated category Id.
Signature #0: array meerkat.getCategories()
Method meerkat.getCategoriesBySubstring:
Returns an array of structs of available Meerkat categories each with its associated category Id given a substring to match (case-insensitively).
Signature #0: array meerkat.getCategoriesBySubstring(string)
Method meerkat.getChannelsByCategory:
Returns an array of structs of RSS channels in a particular category (specified by integer category id) each with its associated channel Id.
Signature #0: array meerkat.getChannelsByCategory(int)
Method meerkat.getChannelsBySubstring:
Returns an array of structs of RSS channels in a particular category each with its associated channel Id givena substring to match (case-insensitively).
Signature #0: array meerkat.getChannelsBySubstring(string)
Method meerkat.getItems:
Returns an array of structs of RSS items given a recipe struct.
Search Criteria:
channel (int) - a channel's numeric id
category (int) - a category's numeric id
item (int) - a particular item's numeric id
search (string) - /a MySQL regular expression/
time_period (string) - travel back in time; format: #(MINUTE|HOUR|DAY)
profile (int) - a particular profile's numeric id
mob (int) - a particular mob's numeric id
url (string) - a particular url
Display Recipes:
ids (int) - Return story ids (0=off, 1=on)
descriptions (int) - Return item descriptions (0=off, 1=full, >1=length)
categories (int) - Return categories with which items are associated (0=off, 1=on)
channels (int) - Return channels in which items appeared (0=off, 1=on)
dates (int) - Return the dates items were picked up by Meerkat (0=off, 1=on)
num_items (int) - The number of items to be returned (0 < n <=50)
Example:
$ f = new xmlrpcmsg("meerkat.getItems",
array(
new xmlrpcval(
array(
"channel" => new xmlrpcval(724, "int"),
"search" => new xmlrpcval("/xml|[Jj]ava/", "string"),
"time_period" => new xmlrpcval("3DAY", "string"),
"ids" => new xmlrpcval(0, "int"),
"descriptions" => new xmlrpcval(200, "int"),
"categories" => new xmlrpcval(0, "int"),
"channels" => new xmlrpcval(0, "int"),
"dates" => new xmlrpcval(0, "int"),
"num_items" => new xmlrpcval(5, "int"),
),
"struct"
)
)
);
Signature #0: array meerkat.getItems(struct)
Method system.listMethods:
This method lists all the methods that the XML-RPC server knows how to dispatch
Signature #0: array system.listMethods(string)
Signature #1: array system.listMethods()
Method system.methodHelp:
Returns help text if defined for the method passed, otherwise returns an empty string
Signature #0: string system.methodHelp(string)
Method system.methodSignature:
Returns an array of known signatures (an array of arrays) for the method name passed. If no signatures are known, returns a none-array (test for type != array to detect missing signature)
Signature #0: array system.methodSignature(string)
Caveat
You may run into some problems when running this script: not all servers make the system methods available to them (like system.listMethods, system.methodHelp, and system.methodSignature
Anyway, I hope someone finds this useful/interesting…