#!/usr/bin/perl -w # # A handy little program to get the documentation of the available # methods from an XML-RPC service (via XML-RPC Introspection) and # print it out nicely formatted. # # (I wrote this in Perl because of all the spiffy report-generation # features.) # # You'll need to get Ken MacLeod's Frontier::RPC2 module from CPAN to use # this. # # Eric Kidd # # This script is part of xmlrpc-c, and may be used and distributed under # the same terms as the rest of the package. use strict; # One global variable for use with Perl's format routines, and one for # use inside an 'exec' block. use vars qw/$helptext $method_list/; # Try to load our Perl XML-RPC bindings, but fail gracefully. eval { require Frontier::Client; }; if ($@) { print STDERR <<"EOD"; This script requires Ken MacLeod\'s Frontier::RPC2 module. You can get this from CPAN or from his website at http://bitsko.slc.ut.us/~ken/xml-rpc/ . For installation instructions, see the XML-RPC HOWTO at: http://www.linuxdoc.org/HOWTO/XML-RPC-HOWTO/index.html EOD exit 1; } # Parse our command-line arguments. if (@ARGV != 1 || $ARGV[0] eq "--help") { print STDERR "Usage: xml-rpc-api2txt serverURL\n"; exit 1; } my $server = Frontier::Client->new(url => $ARGV[0]); # Try (very carefully) to get our a list of methods from the server. local $method_list; eval { $method_list = $server->call('system.listMethods'); }; if ($@) { print STDERR <<"EOD"; An error occurred while trying to talk to the XML-RPC server: $@ This may have been caused by several things--the server might not support introspection, it might not be an XML-RPC server, or your network might be down. Try the following: xml-rpc-api2txt http://xmlrpc-c.sourceforge.net/api/sample.php EOD exit 1; } # Enter the methods into a hashtable. my @methods = sort @$method_list; my %method_table; foreach my $method (@methods) { $method_table{$method} = {}; } # Get more information for the hash table. Since we need to make lots and # lots of very small XML-RPC calls, we'd like to use system.multicall to # reduce the latency. if (defined $method_table{'system.multicall'}) { # This is messy but fast. Everybody hates HTTP round-trip lag, right? my @call; foreach my $method (@methods) { push @call, {methodName => 'system.methodSignature', params => [$method]}; push @call, {methodName => 'system.methodHelp', params => [$method]}; } my @result = @{$server->call('system.multicall', \@call)}; for (my $i = 0; $i < @methods; $i++) { my $method = $methods[$i]; $method_table{$method}->{'signatures'} = $result[2*$i]->[0]; $method_table{$method}->{'help'} = $result[2*$i+1]->[0]; } } else { # This is easy but slow (especially over backbone links). foreach my $method (@methods) { my $signature = $server->call('system.methodSignature', $method); my $help = $server->call('system.methodHelp', $method); $method_table{$method}->{'signatures'} = $signature; $method_table{$method}->{'help'} = $help; } } # Now, we need to dump the API. print <<"EOD"; XML-RPC API for $ARGV[0] See http://www.linuxdoc.org/HOWTO/XML-RPC-HOWTO/index.html for instructions on using XML-RPC with Perl, Python, Java, C, C++, PHP, etc. EOD foreach my $method (@methods) { print "\n"; # Print a synopsis of the function. if ($method_table{$method}->{'signatures'} eq 'undef') { # No documentation. Bad server. No biscuit. print "unknown $method (...)\n"; } else { for my $signature (@{$method_table{$method}->{'signatures'}}) { my $return_type = shift @$signature; my $arguments = join(", ", @$signature); print "$return_type $method ($arguments)\n"; } } print "\n"; my $help = $method_table{$method}->{'help'}; if ($help =~ /\n/) { # Text has already been broken into lines by the server, so just # indent it by two spaces and hope for the best. my @lines = split(/\n/, $help); my $help = " " . join("\n ", @lines); print "$help\n"; } else { # Print our help text in a nicely-wrapped fashion using Perl's # formatting routines. $helptext = $method_table{$method}->{'help'}; write; } } format STDOUT = ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~ $helptext .