DEPRECATION WARNING

This documentation is not using the current rendering mechanism and is probably outdated. The extension maintainer should switch to the new system. Details on how to use the rendering mechanism can be found here.

XMLRPC Library

Created:2003-10-10T15:22:51
Changed:2004-05-19T12:46:56
Info 1:raul@bgta.net
Info 2:Raúl Romero
Info 3:
Info 4:

XMLRPC Library

Extension Key: xmlrpc_lib

Copyright 2000-2002, Raúl Romero, <raul@bgta.net>

This document is published under the Open Content License

available from http://www.opencontent.org/opl.shtml

The content of this document is related to TYPO3

- a GNU/GPL CMS/Framework available from www.typo3.com

Table of Contents

1

Introduction 2

What does it do? 2

Keith Devens Open Source License 3

Developer Manual 4

Introduction 4

Include the library in your Extension 4

XMLRPC Manual 5

Instructions 5

Debugging 5

Functions 6

Examples 8

Notes 10

Known problems 11

To-Do list 11

Changelog 11

Introduction

What does it do?

This front end library contains An XML-RPC implementation by Keith Devens(http://www.keithdevens.com/software/xmlrpc/).

Here's a fully compliant XML-RPC client and server written in pure PHP. Only requirements are PHP, and the XML parser you're guaranteed to have if you're using PHP built into Apache (which most people are).

The main benefit of using this XML-RPC library over others is that it uses native PHP datatypes wherever possible and doesn't force you into OO. I'd tried other XML-RPC libraries, and they make you use objects in complex ways just to build your XML-RPC message. With this library, you can build your message using nothing but native PHP datatypes. Since PHP is a high level scripting language, it has most of the type information available to you that you need to build an XML-RPC message. That's called "reflection" :) The library is also fairly small (<500 lines).

This library is Open Source and is distributed under Keith Devens open source license (similar to the Artistic License). You can read the release history here .

Keith Devens Open Source License

This is an example of a search form. The look depends on your template. All labels and options are available in german and english, more languages can be added. In this example we want to search for the author “pratchett”.

The result would look like this:

The code you have is Open Source . You have permission to use or modify the code for your own purposes: commercial, private, or educational. However, the author (Keith Devens) retains ownership over the code - it is not public domain.

The unmodified source may be redistributed with no restrictions, provided that all files in the original distribution are included and unchanged.

The modifiedsource may be redistributed under the following conditions:

Changes to the source must be made available and placed in the public domain or released on the same terms as this license.

You must clearly state in each modified filewhat you have changed. This does not preclude a separate "changes" file from being distributed with the source in additionto the comments you make in the source file. So if you want to give just a short description in the source file, and then supply the location of the changes file containing more detail about the changes, you may do that.

The initial comment header, containing my name, the URL to the homepage for the code, and any other information, must be left intact. You may add other comments below it, of course.

You may use this code within a larger product with no restrictions except those that apply to the source when distributed separately.

Finally, I would appreciate it if you would let me know about any changes you make that you think would be generally useful so I can merge them in with the main source for the benefit of others.

Developer Manual

Introduction

This extension is only a library. It's made for make XMLRPC interfaces for your Typo3 extensions (Server and Client side).

Include the library in your Extension

To include the library, write this:

include_once(t3lib_extMgm::extPath(“xmlrpc_lib”).'/xmlrpc.php');

XMLRPC Manual

Instructions

All functions you need to use have the prefix XMLRPC_

To use the examples.getStateNameexample given in the XML-RPC spec, for instance, all you would need to do is use this function call:

$result = XMLRPC\_request('betty.userland.com', '/RPC2', 'examples.getStateName', array(XMLRPC\_prepare(41)));

This is what gets sent:

<?xml version="1.0" ?>
<methodCall>
        <methodName>examples.getStateName</methodName>
        <params>
                <param>
                        <value>
                                <int>41</int>
                        </value>
                </param>
        </params>
</methodCall>

And the following data structure is what is stored in $result

array(2) {
  [0]=>
  bool(true)
  [1]=>
  string(12) "South Dakota"
}

You always get an array back. The first element of the array is a boolean value indicating success (true) or failure (false). The second element is the return value of the XML_RPC call. If the call failed it will be the error value, and if it succeeded it will be the return value of the call. Because you always get an array of two elements back, you may want to call XMLRPC_requestlike this:

list($success, $response) = XMLRPC\_request('betty.userland.com', '/RPC2', 'examples.getStateName', array(XMLRPC\_prepare(41)));

To be thorough, here's an example of an error. Say I called 'examples.getStateName' like this (notice, I didn't use XMLRPC_prepare):

list($success, $response) = XMLRPC\_request('betty.userland.com', '/RPC2', 'examples.getStateName', array(41));

$successwould contain:

bool(false)

And $responsewould contain:

array(2) {
  ["faultCode"]=>
  int(4)
  ["faultString"]=>
  string(84) "Can't evaluate the array reference because
              the table "table" has no item named "41"."
}

Debugging

New in version 2.2 are facilities for debugging. Basically, if you define the constant XMLRPC_DEBUGusing code like this: define("XMLRPC\_DEBUG", 1); at the beginning of your script, the library will automatically keep track of all data sent or received. Then just call XMLRPC_debug_printto see what's been going on. It'll print out an HTML table with a detailed history of what's been sent and received.

Make sure, however, that you don't leave debugging on while you're in production, especially if you have a long running daemon or anything like that. While the debugging doesn't change the behavior of the script, it uses memory to store the debugging messages, and you'll run out eventually :)

Functions

Note: this library uses the functions documented below. In addition, the actual XML parsing is done in a class named XML. You should be aware of this in case you happen to already have a class named XML.

function XMLRPC\_prepare($data, $type = NULL){

This function takes whatever data you have, and transforms it into the appropriate data structure to be serialized into an XML-RPC message. Because of PHP's reflection, most of the time you don't have to tell it what type you want. If you pass it an array that is either empty or sequentially numbered (specifically, if it has a zero index), it'll assume it's an array and turn it into an XML-RPC array. Similarly, if you pass it an associative array, it will serialize it into an XML-RPC struct. If you pass it a number (not a string that looks like a number, mind you. You may have to do some conversion on your end to make sure that it's an actualnumber.), it'll automatically turn it into an intor a doubleXML-RPC type for you. If you pass it something that looks like a date (you'll have to convert it to ISO8601 format first. See the function below), it'll turn it into an XML-RPC date, if you pass it a boolean, it'll create a boolean, and otherwise it'll just consider it a string. If you want it to be a base64type, you have to do a little something extra which I'll explain at the end.

There was a bug in this function before version 2.2.1 which caused it to not handle empty structs and empty arrays correctly. As of version 2.2.1 it handles empty structs and empty arrays correctly. Normal typing rules apply: it'll consider an empty array to be an arraytype by default, but if you specify a type of "struct" it'll consider it an empty struct.

Examples of creating empty structs:

$array['foo'] = array();
$array['foo type'] = 'struct';
XMLRPC_prepare($array);

#or

XMLRPC_prepare(array(), 'struct');

#you can even force it to consider something
#that would ordinarily be an array to be a struct

$array['foo'] = array(1,1,2,3,5,8);
$array['foo type'] = 'struct';
XMLRPC_prepare($array);

function XMLRPC\_request($site, $location, $methodName, $params = NULL, $user\_agent = NULL){

This function connects to $siteat location $location, calls the method $methodName, and passes it the $paramswith an optional $user_agent. So, the method call above would be translated into the following message:

POST /RPC2 HTTP/1.0
Host: betty.userland.com
Connection: close
Content-Type: text/xml
Content-Length: 192

<?xml version="1.0" ?>
<methodCall>
        <methodName>examples.getStateName</methodName>
        <params>
                <param>
                        <value>
                                <int>41</int>
                        </value>
                </param>
        </params>
</methodCall>

If you want to call a method and pass no parameters, just call XMLRPC_requestwith either NULLor an empty array for the $paramsparameter (or don't pass anything at all).

Finally, if you want to specify a port other than the default of 80, you can pass $sitein the form of "www.keithdevens.com:8080".

function XMLRPC\_response($return\_value, $server = NULL){

XMLRPC_responseallows you to send back an XML-RPC response when your program is acting as a server. It takes one parameter of the return value (as per the XML-RPC spec), but the $return_valuecan of course contain arrays, structs, etc.

Note: Apache doesn't let you override the server header (also see the bottom of this page ), unfortunately. I found this out after I programmed that feature. I expect that other web servers will allow you to override it, so hopefully some will be able to use it.

function XMLRPC\_error($faultCode, $faultString, $server = NULL){

XMLRPC_errorsends an XML-RPC error message.

function XMLRPC\_getMethodName($methodCall){ function XMLRPC\_getParams($methodCall){

The above two functions are to be used when acting as a server. Code example below. XMLRPC_getParamsautomatically puts the result of the method call into native PHP data structures. In fact, with the exception of the base64 type, you can "round trip" between XMLRPC_prepareand XMLRPC_getParams.

function XMLRPC\_convert\_timestamp\_to\_iso8601($timestamp){ function XMLRPC\_convert\_iso8601\_to\_timestamp($iso8601){

Utility functions to convert to and from the ISO8601 formatted time string required by the XML-RPC spec.

function count\_numeric\_items($array){

A utility function that will return the number of numeric indices of an array.

function & XML\_serialize($data){

Takes a data structure, and serializes it into XML. Both XML_serializeand XML_unserializeare not tied to the implementation of XML-RPC, but can be used for any XML format. XML_unserializeis a "full fledged" XML parser in its own right, based on PHP's XML functions, which are based on expat.

function & XML\_unserialize(&$xml){

Turns XML into a native PHP data structure.

Note: While XML_unserializeis a complete XML parser, it only handles "data oriented" XML files correctly, as opposed to "document oriented" XML files. A data oriented XML file is fully nested (like XML-RPC, RSS, SOAP, WDDX, etc.), while XHTML is an example of a type of XML document which is document oriented.

function & XMLRPC\_parse(&$request){

Takes XML and parses it into a PHP data structure. XMLRPC_parseused to be a synonym for XML_unserialize, but as of version 2.5 it does more. For XML-RPC, this function should always be used over XML_unserialize, while XML_unserializecan still be used independently for raw XML if you want.

function & XMLRPC\_adjustValue(&$current\_node){

An internal function that does the heavy lifting in converting an XML- RPC data structure into a native PHP data structure. You should never have to use this separately.

function XMLRPC\_debug($function\_name, $debug\_message){

An internal function that logs debugging messages. Should not be used directly.

function XMLRPC\_debug\_print(){

After you've run through some requests or responses with debugging turned on, you use this function to display a table of debug messages. Once you call this function to display the debugging info, it clears the debugging log so if you make multiple calls to this you won't get the same debugging info repeated. Finally, if you want to write a log file with this debugging information in it, you could always buffer the output of this function, wrap it in some quick HTML (the <html><head><body>, etc.), and write it to a file.

function XMLRPC\_show($data, $func = "print\_r", $return\_str = false){

A utility function I use to log debugging data. This is a direct copy of a function I use all the time on my site for debugging (normally, it's just named show). It'll print out any PHP data for you, automatically escape any HTML, etc. Consider it like a super-powered print_ror var_dump. You can even pass it the name of your own custom written function to use instead of print_r, etc. for outputting your data. You may find this function useful independently of this library.

Examples

First, here's an example of using the client part of the library to ping weblogs.com in both flavors, regular and RSS .

<?phpXMLRPC\_request ( "rpc.weblogs.com" , "/RPC2" , "weblogUpdates.ping" , array( XMLRPC\_prepare ( $name ), XMLRPC\_prepare ( $address ))); XMLRPC\_request ( "rpc.weblogs.com" , "/RPC2" , "rssUpdate" , array( XMLRPC\_prepare ( $name ), XMLRPC\_prepare ( $address ))); ?>

This is how I implement the Blogger API server for my weblog (yes, that's it, besides the individual methods and the function table below):

<?php include( "include\_weblog\_api.php" ); $xmlrpc\_request = XMLRPC\_parse ( $HTTP\_RAW\_POST\_DATA ); $methodName = XMLRPC\_getMethodName ( $xmlrpc\_request ); $params = XMLRPC\_getParams ( $xmlrpc\_request );if(!isset( $xmlrpc\_methods [ $methodName ])){ $xmlrpc\_methods [ 'method\_not\_found' ]( $methodName );}else{ #call the method $xmlrpc\_methods [ $methodName ]( $params );} ?>

And include_weblog_api.phphas this code in it to set up the function translation table:

<?php$xmlrpc\_methods = array(); $xmlrpc\_methods [ 'blogger.getUsersBlogs' ]= 'blogger\_getUsersBlogs' ; $xmlrpc\_methods [ 'blogger.getUserInfo' ]= 'blogger\_getUserInfo' ; $xmlrpc\_methods [ 'blogger.getRecentPosts' ] = 'blogger\_getRecentPosts' ; $xmlrpc\_methods [ 'blogger.newPost' ]= 'blogger\_newPost' ; $xmlrpc\_methods [ 'blogger.editPost' ]= 'blogger\_editPost' ; $xmlrpc\_methods [ 'blogger.getPost' ]= 'blogger\_getPost' ; $xmlrpc\_methods [ 'method\_not\_found' ]= 'XMLRPC\_method\_not\_found' ; ?>

In addition, you can take my implementation of blogger.getRecentPosts as a good example of how you're supposed to use this library: (a little reformatting done to make it fit correctly on a web page :)

<?php function blogger\_getRecentPosts ( $params ){ /\*getRecentPosts(String appkey, String blogid, String username, String password, int numberOfPosts)Returns an array of structs containing the latest n posts to a given blog, newest first.Each post struct includes: dateCreated (when post was made), userid (who made the post), postid, and content.\*/ $username = $params [ 2 ]; $password = $params [ 3 ]; $numposts = $params [ 4 ];if( validateLogin ( $username , $password )){ $conn = init\_db\_connection (); $rs\_id = get\_weblog\_entries ( '1' , $conn , $numposts ); $posts = array();while( $row = mysql\_fetch\_assoc ( $rs\_id )){ $post [ 'userid' ] = '1' ; $post [ 'dateCreated' ] = XMLRPC\_convert\_timestamp\_to\_iso8601 ( convert\_mysql\_datetime ( $row [ 'DateTime\_Entered' ])); $post [ 'content' ] = $row [ 'entry' ]; $post [ 'postid' ] = (string) $row [ 'weblog\_id' ]; $posts [] = $post ;} close\_db\_connection ( $conn ); XMLRPC\_response ( XMLRPC\_prepare ( $posts ), WEBLOG\_XMLRPC\_USERAGENT );}else{ XMLRPC\_error ( "1" , "getRecentPosts() error: Your login ($username, $password) didn't validate." , WEBLOG\_XMLRPC\_USERAGENT );}} ?>

Finally, so you can see XMLRPC_errorin use, I'll show you my implementation of the "method_not_found" method referenced above.

<?php function XMLRPC\_method\_not\_found ( $methodName ){ XMLRPC\_error ( "2" , "The method you requested, '$methodName', was not found." , WEBLOG\_XMLRPC\_USERAGENT );} ?>

Notes

To do base64, you have to include a "type" element along with the data. The way this should work is as follows: If you have a value such as:

$array['binaryData'] = "your data here";

You'll have to include a type element so that it is serialized into an XML-RPC message as a base64instead of a number or a string. The array would now look like:

$array['binaryData'] = "your data here";$array['binaryData type'] = 'base64';

Note that you have to do your own encoding and decoding for base64. Use PHP's base64_encode and base64_decode to do the work for you.

Also, if you're just sending a scalar (where you don't have an array, so "binaryData type" as a key makes no sense), you can say you want a value to be interpreted as a base64 value by saying XMLRPC_prepare($binaryData, 'base64').

Also note that when you use XMLRPC_request, you have to wrap your data in an array, because it's a list of parameters for the methodCall, not just one parameter.

Finally, the way to create boolean types is by casting an integer to a boolean, like so: (bool)1for true and (bool)0for false. Of course you could always use XMLRPC_prepare(1, 'boolean')or $array['saveSettings'] = 1; $array['saveSettings type'] = 'boolean', but that's unnecessary because PHP's built-in types contain all the information you need.

One more thing: if you want the functions you define for use with XML- RPC to take multiple parameters, rather than just one parameter that's an array of the parameters passed in the XML-RPC call, you can call your functions using PHP's call_user_func_array .

Warning:I've gotten a report that when cutting and pasting code from this page in IE 5.2 on a Mac into BBEdit, IE copies some invalid "space" characters which the PHP interpreter then chokes on when you save and try to run the file. You don't notice the space characters unless you turn on "Show Invisibles" in BBEdit. So beware of IE - Microsoft always does bad things with invalid characters.

Note (3/25/2004):I know there's a problem with the code generating call-time pass-by-reference warnings, but there's nothing really that can be done about it under PHP 4. The PHP developers deprecated a feature without making available alternate means of accomplishing the same thing. I even wrote a big rant about it a while ago as I was trying to update the library to make it compatible with that feature. The only way to get around that is to enable call-time pass-by-reference in your PHP configuration. You can do it in your .htaccess file by including the line "php_flag allow_call_time_pass_reference on". Frustratingly, the error messages aren't even E_NOTICE level messages, but are E_WARNING level messages.

Note (3/25/2004):No more changes will be made to this code for PHP version 4 (except bug fixes, if necessary). Once PHP 5 is released I'll work on releasing version 3.0. It should allow XML-RPC calls over SSL, HTTP-Authentication, and I'll probably use PHP 5's SimpleXML feature as well. Oh, and there should be no need to call XMLRPC_prepare ever again. It was a mistake to force the user to call that in the first place. Here's a suggestion box if you'd like to request any other features in version 3.

Known problems

To-Do list

Changelog

img-1 XMLRPC Library - 11