# XML-RPC for PHP

version 1.0b9
7th July 2001
Edd
Dumbill
Useful Information Company

    	    edd@usefulinc.com

1999,2000,2001
Edd Dumbill, Useful Information Company

License is granted to use or modify this software ("XML-RPC for PHP") for commercial or non-commercial use provided the copyright of the author is preserved in any distributed or derivative work.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

## Introduction

XML-RPC is a format devised by Userland Software for achieving remote procedure call via XML. XML-RPC has its own web site, www.XmlRpc.com

The most common implementations of XML-RPC available at the moment use HTTP as the transport. A list of implementations for other languages such as Perl and Python can be found on the www.XmlRpc.com.

This collection of PHP classes provides a framework for writing XML-RPC clients and servers in PHP.

The server code works only with versions of PHP3 >= 3.0.12. The code is also known to work with PHP4.

### Acknowledgements

Jim Winstead jimw@php.net

Peter Kocks peter.kocks@baygate.com

Nicolay Mausz mausz@flying-dog.com

Ben Margolin ben@wendy.auctionwatch.com

Dan Libby dan@libby.com

Gaetano Giunta g.giunta@libero.it

Idan Sofer i_sofer@yahoo.com

## Files in the distribution

xmlrpc.inc

  the XML-RPC classes. `include()` this in your PHP files to use the classes.

xmlrpcs.inc

  the XML-RPC server class. `include()` this in addition to xmlrpc.inc to get server functionality

bettydemo.php

  demo which retrieves a state name from a number using Dave Winer's XML-RPC server at betty.userland.com

server.php

  a sample server hosting three functions: a US State lookup tool, a struct sorter and an echo function.

client.php, agesort.php, echotest.php

  client code to exercise the various functions in server.php

base64test.php, stringtest.php

  Tests to verify that encoding and decoding of base 64 and entities is functioning correctly.

vardemo.php

  examples of how to construct xmlrpcval types

demo1.txt, demo2.txt, demo3.txt

  XML-RPC responses captured in a file for testing purposes (you can use these to test the `xmlrpcmsg->parseResponse()` method).

httptest.php

  Testing that HTTP response detection works OK.

test.pl, test.py

  Perl and Python programs to exercise server.php to test that some of the methods work. Make sure you point these at your server, not mine!

workspace.testPhpServer.fttb

  Frontier scripts to exercise the demo server. Thanks to Dave Winer for permission to include these. See Dave's announcement of these.

phpunit.php

  Fred Yankowski's unit test framework for PHP.

testsuite.php

  Start of a unit test suite for this software package. If you do development on this software, please consider submitting tests for this suite.

which.php

  A demo of the `interopEchoTests.whichToolkit` method.

discuss.php, comment.php

  Software used in the PHP chapter of to provide a comment server and allow the attachment of comments to stories from Meerkat's data store.

## Bugs

This is a bare framework. The "nice" bits haven't been put in yet. Specifically, no HTTP response checking is performed, and no type validation or coercion has been put in. PHP being a loosely-typed language, this is going to have to be done explicitly.

dateTime.iso8601 is supported opaquely. It can't be done natively as the XML-RPC specification explictly forbids passing of timezone specifiers in ISO8601 format dates. You can, however, use the and functions to do the encoding and decoding for you.

If alternative character set encoding is sent in HTTP header than it will be ignored for the moment. We speak only UTF-8...

If more than 32k of HTTP headers are encountered (like, why?) then the response parsing code will break.

## Support

### Online Support

XML-RPC for PHP is offered "as-is" without any warranty or commitment to support. However, informal advice and help is available via the XML-RPC for PHP mailing list and XML-RPC.com.

- The PHP XML-RPC interest mailing list is run by the author. More details can be found here.

- For more general XML-RPC questions, there is a Yahoo! Groups XML-RPC mailing list.

- The XML-RPC.com discussion group is a useful place to get help with using XML-RPC. This group is also gatewayed into the Yahoo! Groups mailing list.

### The Jellyfish Book

Together with Simon St.Laurent and Joe Johnston, I wrote a book on XML-RPC for O'Reilly and Associates on XML-RPC. It features a rather fetching jellyfish on the cover.

Complete details of the book are available from O'Reilly's web site.

I'm responsible for the chapter on PHP, which includes a worked example of creating a forum server, and hooking it up the O'Reilly's Meerkat service in order to allow commenting on news stories from around the Web.

If you've benefitted from the effort I've put into writing this software, then please consider buying the book!

## Class documentation

### xmlrpc_client

This is the basic class used to represent a client of an XML-RPC server.

#### Creation

The constructor has the following syntax:

    			$client=new xmlrpc_client
    			$server_path
    			$server_hostname
    			$server_port

Here's an example client set up to query Userland's XML-RPC server at betty.userland.com:

    $client=new xmlrpc_client("/RPC2", "betty.userland.com", 80);

The `server_port` parameter is optional, and if omitted will default to 80.

#### Methods

This class supports the following methods.

##### send

This method takes the form:

    							$response=$client->send
    							$xmlrpc_message
    							$timeout

Where `$xmlrpc_message` is an instance of `xmlrpcmsg` (see ), and `$response` is an instance of `xmlrpcresp` (see ).

The `$timeout` is optional, and will be set to `0` (wait forever) if omitted. This timeout value is passed to `fsockopen()`.

If the value of `$response` is `0` rather than an `xmlrpcresp` object, then this signifies an I/O error has occured. You can find out what the I/O error was from the values `$client->errno` and `$client->errstring`.

In addition to low-level errors, the XML-RPC server you were querying may return an error in the `xmlrpcresp` object. See for details of how to handle these errors.

##### setCredentials

    			  $client->setCredentials
    			  $username
    							$password

This method sets the username and password for authorizing the client to a server. With the default (HTTP) transport, this information is used for HTTP Basic authorization.

##### setDebug

    			  $client->setDebug
    			  $debugOn

`$debugOn` is either `0` or `1` depending on whether you require the client to print debugging information to the browser. The default is not to output this information.

The debugging information includes the raw data returned from the XML-RPC server it was querying, and the PHP value the client attempts to create to represent the value returned by the server. This option can be very useful when debugging servers as it allows you to see exactly what the server returns.

### xmlrpcmsg

This class provides a representation for a request to an XML-RPC server. A client sends an `xmlrpcmsg` to a server, and receives back an `xmlrpcresp` (see ).

#### Creation

The constructor takes the following form:

    			$msg=new xmlrpcmsg
    			$methodName
    			$parameterArray

Where `$methodName` is a string indicating the name of the method you wish to invoke, and `$parameterArray` is a simple `Array` of `xmlrpcval` objects. Here's an example message to the US state name server:

    $msg=new xmlrpcmsg("examples.getStateName",
    		  array(new xmlrpcval(23, "int")));

This example requests the name of state number 23. For more information on `xmlrpcval` objects, see .

#### Methods

##### serialize

    			  $outString=$msg->serialize

Returns the an XML string representing the XML-RPC message.

##### addParam

    			  $msg->addParam
    			  $xmlrpcVal

Adds the `xmlrpcval` `$xmlrpcVal` to the parameter list for this method call.

##### getParam

    			  $xmlrpcVal=$msg->getParam
    			  $n

Gets the `$n`th parameter in the message. Use this method in server implementations. Returns the `undef` value if no such parameter exists.

##### getNumParams

    			  $n=$msg->getNumParams

Returns the number of parameters attached to this message.

##### method

    			  $methName=$msg->method

    			  $msg->method
    			  $methName

Gets or sets the method contained in the XML-RPC message.

##### parseResponse

    			  $response=$msg->parseResponse
    			  $xmlString

Given an incoming XML-RPC server response contained in the string `$xmlString`, this method constructs an `xmlrpcresp` response object and returns it, setting error codes as appropriate (see ).

This method processes any HTTP/MIME headers it finds.

##### parseResponseFile

    			  $response=$msg->parseResponseFile
    			  $fileHandle

Given an incoming XML-RPC server response on the file handle `$fileHandle`, this method reads the data and passes it to `parseResponse`

This method is useful to construct responses from pre-prepared files (see files `demo1.txt, demo2.txt, demo3.txt` in this distribution). It processes any HTTP headers it finds.

### xmlrpcresp

This class is used to contain responses to XML-RPC requests. A server method handler will construct an `xmlrpcresp` and pass it as a return value. This same value will be returned by the result of an invocation of the `send` method of the `xmlrpc_client` class.

#### Creation

    			$resp=new xmlrpcresp

    			$xmlrpcval

    			$resp=new xmlrpcresp
    			0
    			$errcode
    			$errstring

The first instance is used when execution has happened without difficulty: `$xmlrpcval` is an `xmlrpcval` value with the result of the method execution contained in it.

The second type of constructor is used in case of failure. `$errcode` and `$errstring` are used to provide indication of what has gone wrong. See for more information on passing error codes.

#### Methods

##### faultCode

    			  $fn=$resp->faultCode

Returns the integer fault code return from the XML-RPC response `$resp`. A zero value indicates success, any other value indicates a failure response.

##### faultString

    			  $fs=$resp->faultString

Returns the human readable explanation of the fault indicated by `$resp->faultCode`.

##### value

    			  $xmlrpcVal=$resp->value

Returns an `xmlrpcval` object containing the return value sent by the server. If the response's `faultCode` is non-zero then the value returned by this method should not be used (it may not even be an object).

##### serialize

    			  $outString=$resp->serialize

Returns an XML string representation of the response.

### xmlrpcval

This is where a lot of the hard work gets done. This class enables the creation and encapsulation of values for XML-RPC.

Ensure you've read the XML-RPC spec at http://www.xmlrpc.com/stories/storyReader$7 before reading on as it will make things clearer.

The `xmlrpcval` class can store arbitrarily complicated values using the following types: `i4 int boolean string double dateTime.iso8601 base64 array struct`. You should refer to the spec for more information on what each of these types mean.

#### Notes on types

##### int

The type `i4` is accepted as a synonym for `int`. The value parsing code will always convert `i4` to `int`: `int` is regarded by this implementation as the canonical name for this type.

##### base64

Base 64 encoding is performed transparently to the caller when using this type. Therefore you ought to consider it as a "binary" data type, for use when you want to pass none 7-bit clean data. Decoding is also transparent.

##### boolean

The values `true` and `1` map to `true`. All other values (including the empty string) are converted to `false`.

##### string

The characters `< > "` and `&` are converted to their entity equivalents `&lt; &gt; &quot;` and `&amp;` for transport through XML-RPC. The current XML-RPC spec recommends only encoding `< &` but this implementation goes further, for reasons explained by the XML 1.0 recommendation.

TODO: `&apos;` entity not yet supported

#### Creation

The constructor is the normal way to create an `xmlrpcval`. The constructor can take these forms:

    			$myVal=new xmlrpcval

    			$myVal=new xmlrpcval

    			$stringVal

    			$myVal=new xmlrpcval

    			$scalarVal
    			"int" | "boolean" | "string" | "double" | "dateTime.iso8601" | "base64"

    			$myVal=new xmlrpcval

    			$arrayVal
    			"array" | "struct"

The first constructor creates an empty value, which must be altered using the methods `addScalar`, `addArray` or `addStruct` before it can be used.

The second constructor creates a simple string value.

The third constructor is used to create a scalar value. The second parameter must be a name of an XML-RPC type. Examples:

    		  $myInt=new xmlrpcvalue(1267, "int");
    		  $myString=new xmlrpcvalue("Hello, World!", "string");
    		  $myBool=new xmlrpcvalue(1, "boolean");

The fourth constructor form can be used to compose complex XML-RPC values. The first argument is either a simple array in the case of an XML-RPC `array` or an associative array in the case of a `struct`. The elements of the array must be `xmlrpcval` objects themselves. Examples:

    		  $myArray=new xmlrpcval(array(
    		      new xmlrpcval("Tom"), new xmlrpcval("Dick"),
    		      new xmlrpcval("Harry")), "array");

    		  $myStruct=new xmlrpcval(array(
    		      "name" => new xmlrpcval("Tom"),
    		      "age" => new xmlrpcval(34, "int"),
    		      "geek" => new xmlrpcval(1, "boolean")), "struct");

See the file `vardemo.php` in this distribution for more examples.

#### Methods

##### addScalar

    			  $ok=$val->addScalar

    			  $stringVal

    			  $ok=$val->addScalar

    			  $scalarVal
    			  "int" | "boolean" | "string" | "double" | "dateTime.iso8601" | "base64"

If `$val` is an empty `xmlrpcval` this method makes it a scalar value, and sets that value. If `$val` is already a scalar value, then no more scalars can be added and `0` is returned. If all went OK, `1` is returned.

There is a special case if `$val` is an `array`: the scalar value passed is appended to the array.

##### addArray

    			  $ok=$val->addArray
    			  $arrayVal

Turns an empty `xmlrpcval` into an `array` with contents as specified by `$arrayVal`. See the fourth constructor form for more information.

##### addStruct

    			  $ok=$val->addArray
    			  $assocArrayVal

Turns an empty `xmlrpcval` into a `struct` with contents as specified by `$assocArrayVal`. See the fourth constructor form for more information.

##### kindOf

    			  $kind=$val->kindOf

Returns a string containing "struct", "array" or "scalar" describing the base type of the value. If it returns "undef" it means that the value hasn't been initialised.

##### serialize

    			  $outString=$val->serialize

Returns a string containing the XML-RPC representation of this value.

##### scalarval

    			  $scalarVal=$val->scalarval

If `$val->kindOf()=="scalar"`, this method returns the actual PHP-language value of the scalar (base 64 decoding is automatically handled here).

##### scalartyp

    			  $typeName=$val->scalartyp

If `$val->kindOf()=="scalar"`, this method returns a string denoting the type of the scalar. As mentioned before, `i4` is always coerced to `int`.

##### arraymem

    			  $xmlrpcVal=$val->arraymem
    			  $n

Returns the `$n`th element in the array represented by the value `$val`. The value returned is an `xmlrpcval` object.

##### arraysize

    			  $len=$val->arraysize

If `$val` is an `array`, returns the number of elements in that array.

##### structmem

    			  $xmlrpcVal=$val->structmem
    			  $memberName

Returns the element called `$memberName` from the struct represented by the value `$val`. The value returned is an `xmlrpcval` object.

##### structeach

    							list($key,$value)=$val->structeach

Returns the next (key,value) pair from the struct, when `$val` is a struct. See also .

##### structreset

    							$val->structreset

Resets the internal pointer for `structeach()` to the beginning of the struct, where `$val` is a struct.

### xmlrpc_server

The current implementation of this class has been kept as simple as possible. The constructor for the server basically does all the work. Here's a minimal example:

      function foo ($params) {
         ...
      }

      $s=new xmlrpc_server( array("examples.myFunc" =>
    				array("function" => "foo")));

This performs everything you need to do with a server. The single argument is an associative array from method names to function names. The request is parsed and despatched to the relevant function, which is reponsible for returning a `xmlrpcresp` object, which gets serialized back to the caller. See server.php in this distribution for examples of how to do this.

Here is a more detailed look at what the handler function `foo` may do:

      function foo ($params) {
            global $xmlrpcerruser; // import user errcode value

            // $params is an Array of xmlrpcval objects

            if ($err) {
              // this is an error condition
              return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1
               "There's a problem, Captain");
            } else {
              // this is a successful value being returned
              return new xmlrpcresp(new xmlrpcval("All's fine!", "string"));
            }
      }

#### The dispatch map

The first argument to the `xmlrpc_server` constructor is an array, called the dispatch map. In this array is the information the server needs to service the XML-RPC methods you define.

The dispatch map takes the form of an associative array of associative arrays: the outer array has one entry for each method, the key being the method name. The corresponding value is another associative array, which can have the following members:

- `function` - this entry is mandatory. It must be a name of a function in the global scope which services the XML-RPC method.

- `signature` - this entry is an array containg the possible signatures (see ) for the method. If this entry is present then the server will check that the correct number and type of parameters have been sent for this method before dispatching it.

- `docstring` - this entry is a string containing documentation for the method. The documentation may contain HTML markup.

Look at the `server.php` example in the distribution to see what a dispatch map looks like.

#### Method signatures

A signature is a description of a method's return type and its parameter types. A method may have more than one signature.

Within a server's dispatch map, each method has an array of possible signatures. Each signature is an array of types. The first entry is the return type. For instance, the method

    string examples.getStateName(int)

has the signature

    array($xmlrpcString, $xmlrpcInt)

and, assuming that it the only possible signature for the method, might be used like this in server creation:

    $findstate_sig=array(array($xmlrpcString, $xmlrpcInt));

    $findstate_doc='When passed an integer between 1 and 51 returns the
    name of a US state, where the integer is the index of that state name
    in an alphabetic order.';

    $s=new xmlrpc_server( array( "examples.getStateName" =>
    						array("function" => "findstate",
    						"signature" => $findstate_sig,
    						"docstring" => $findstate_doc)));

For convenience the strings representing the XML-RPC types have been encoded as global variables:

    $xmlrpcI4="i4";
    $xmlrpcInt="int";
    $xmlrpcBoolean="boolean";
    $xmlrpcDouble="double";
    $xmlrpcString="string";
    $xmlrpcDateTime="dateTime.iso8601";
    $xmlrpcBase64="base64";
    $xmlrpcArray="array";
    $xmlrpcStruct="struct";

#### Delaying the server response

You may want to construct the server, but for some reason not fulfill the request immediately (security verification, for instance). If you pass the constructor a second argument of `0` this will have the desired effect. You can then use the `service()` method of the server class to service the request. For example:

    $s=new xmlrpc_server($myDispMap, 0);

    // ... some code that does other stuff here

    $s->service();

#### Fault reporting

Fault codes for your servers should start at the value indicated by the global `$xmlrpcerruser` + 1.

Standard errors returned by the server include:

`1` Unknown method

  Returned if the server was asked to dispatch a method it didn't know about

`2` Invalid return payload

  This error is actually generated by the client, not server, code, but signifies that a server returned something it couldn't understand.

`3` Incorrect parameters

  This error is generated when the server has signature(s) defined for a method, and the parameters passed by the client do not match any of signatures.

`4` Can't introspect: method unknown

  This error is generated by the builtin `system.*` methods when any kind of introspection is attempted on a method undefined by the server.

`5` Didn't receive 200 OK from remote server

  This error is generated by the client when a remote server doesn't return HTTP/1.1 200 OK in response to a request. A more detailed error report is added onto the end of the phrase above.

`100-` XML parse errors

  Returns 100 plus the XML parser error code for the fault that occurred. The `faultString` returned explains where the parse error was in the incoming XML stream.

## Helper functions

XML-RPC for PHP contains some helper functions which you can use to make processing of XML-RPC requests easier.

### Date functions

The XML-RPC specification has this to say on dates:

> Don't assume a timezone. It should be specified by the server in its documentation what assumptions it makes about timezones.

Unfortunately, this means that date processing isn't straightforward. Although XML-RPC uses ISO 8601 format dates, it doesn't use the timezone specifier.

We strongly recommend that in every case where you pass dates in XML-RPC calls, you use UTC (GMT) as your timezone. Most computer languages include routines for handling GMT times natively, and you won't have to translate between timezones.

For more information about dates, see ISO 8601: The Right Format for Dates, which has a handy link to a PDF of the ISO 8601 specification. Note that XML-RPC uses exactly one of the available representations: CCYYMMDDTHH:MM:SS.

#### iso8601_encode

    						$isoString=iso8601_encode
    						$time_t$utc=0

Returns an ISO 8601 formatted date generated from the UNIX timestamp `$time_t`, as returned by the PHP function `time()`.

The argument `$utc` can be omitted, in which case it defaults to `0`. If it is set to `1`, then the function corrects the time passed in for UTC. Example: if you're in the GMT-6:00 timezone and set `$utc`, you will receive a date representation six hours ahead of your local time.

The included demo program `vardemo.php` includes a demonstration of this function.

#### iso8601_decode

    						$time_t=iso8601_decode
    						$isoString$utc=0

Returns a UNIX timestamp from an ISO 8601 encoded time and date string passed in. If `$utc` is `1` then `$isoString` is assumed to be in the UTC timezone, and thus the `$time_t` result is also UTC: otherwise, the timezone is assumed to be your local timezone and you receive a local timestamp.

### Easy use with PHP arrays

Dan Libby was kind enough to contribute two helper functions that make it easier to translate to and from PHP arrays. This makes it easier to deal with complex structures. At the moment support is limited to int, double, string, array and struct datatypes; note also that all PHP arrays are encoded as structs due to PHP not being able to tell the difference between a hash and a linear array.

These functions reside in `xmlrpc.inc`.

#### xmlrpc_decode

    						$arr=xmlrpc_decode
    						$xmlrpc_val

Returns a PHP array stuffed with the values found in the xmlrpcval `$xmlrpc_val`, translated into native PHP types.

#### xmlrpc_encode

    						$xmlrpc_val=xmlrpc_encode
    						$phpval

Returns an xmlrpcval populated with the PHP values in `$phpval`. Works recursively on arrays and structs. Note that there's no support for non-base types like base-64 values or date-times.

### Debugging aids

#### xmlrpc_debugmsg

    						xmlrpc_debugmsg
    						$debugstring

Sends the contents of `$debugstring` in XML comments in the server return payload. If a PHP client has debugging turned on, the user will be able to see server debug information.

Use this function in your methods so you can pass back diagnostic information. It is only available from `xmlrpcs.inc`.

## Reserved methods

In order to extend the functionality offered by XML-RPC servers without impacting on the protocol, I've included experimental support in this release for reserved methods.

All methods starting with `system.` are considered reserved by the server. PHP for XML-RPC itself provides three special methods, detailed in this chapter.

### system.listMethods

This method may be used to enumerate the methods implemented by the XML-RPC server.

The `system.listMethods` method requires no parameters. It returns an array of strings, each of which is the name of a method implemented by the server.

### system.methodSignature

This method takes one parameter, the name of a method implemented by the XML-RPC server.

It returns an array of possible signatures for this method. A signature is an array of types. The first of these types is the return type of the method, the rest are parameters.

Multiple signatures (ie. overloading) are permitted: this is the reason that an array of signatures are returned by this method.

Signatures themselves are restricted to the top level parameters expected by a method. For instance if a method expects one array of structs as a parameter, and it returns a string, its signature is simply "string, array". If it expects three integers, its signature is "string, int, int, int".

If no signature is defined for the method, a none-array value is returned. Therefore this is the way to test for a non-signature, if `$resp` below is the response object from a method call to `system.methodSignature`:

    $v=$resp->value();
    if ($v->kindOf()!="array") {
      // then the method did not have a signature defined
    }

See the `introspect.php` demo included in this distribution for an example of using this method.

### system.methodHelp

This method takes one parameter, the name of a method implemented by the XML-RPC server.

It returns a documentation string describing the use of that method. If no such string is available, an empty string is returned.

The documentation string may contain HTML markup.

## Examples

The best examples are to be found in the sample files included with the distribution. Some are included here.

### XML-RPC client: state name query

Code to get the corresponding state name from a number (1-50) from Dave Winer's server

      $f=new xmlrpcmsg('examples.getStateName',
    				   array(new xmlrpcval($HTTP_POST_VARS["stateno"], "int")));
      $c=new xmlrpc_client("/RPC2", "betty.userland.com", 80);
      $r=$c->send($f);
      $v=$r->value();
      if (!$r->faultCode()) {
          print "State number ". $HTTP_POST_VARS["stateno"] . " is " .
          $v->scalarval() . "<BR>";
          print "<HR>I got this value back<BR><PRE>" .
          htmlentities($r->serialize()). "</PRE><HR>\n";
      } else {
          print "Fault: ";
          print "Code: " . $r->faultCode() .
                " Reason '" .$r->faultString()."'<BR>";
      }