From: gggeek Date: Sun, 8 Jan 2023 12:23:45 +0000 (+0000) Subject: improve client demos: demo more lib features; add use clauses X-Git-Tag: 4.9.5~31 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=acf656ce8faebfc32b00eae5491e71379986a298;p=plcapi.git improve client demos: demo more lib features; add use clauses --- diff --git a/demo/client/agesort.php b/demo/client/agesort.php index e6b863e6..7ab2b959 100644 --- a/demo/client/agesort.php +++ b/demo/client/agesort.php @@ -6,60 +6,59 @@ output('

Agesort demo

Send an array of "name" => "age" pairs to the server that will send it back sorted.

-

The source code demonstrates basic lib usage, including manual creation of xml-rpc arrays and structs

-

Have a look at getstatename.php for automatic encoding and decoding, and at - vardemo.php for more examples of manual encoding and decoding

+

The code demonstrates usage of automatic encoding/decoding of php variables into xmlrpc values such as arrays and structs

+

Have a look at vardemo.php for more examples of manual encoding and decoding

You can see the source to this page here: agesort.php

'); -$inAr = array("Dave" => 24, "Edd" => 45, "Joe" => 37, "Fred" => 27); +use PhpXmlRpc\Client; +use PhpXmlRpc\Encoder; +use PhpXmlRpc\Request; -output("This is the input data:
");
-foreach ($inAr as $key => $val) {
-    output($key . ", " . $val . "\n");
-}
-output("
"); +$inAr = array( + array('name' => 'Dave', 'age' => 24), + array('name' => 'Edd', 'age' => 45), + array('name' => 'Joe', 'age' => 37), + array('name' => 'Fred', 'age' => 27), +); -// Create parameters from the input array: an xmlrpc array of xmlrpc structs -$p = array(); -foreach ($inAr as $key => $val) { - $p[] = new PhpXmlRpc\Value( - array( - "name" => new PhpXmlRpc\Value($key), - "age" => new PhpXmlRpc\Value($val, "int") - ), - "struct" - ); +output('This is the input data:
');
+foreach ($inAr as $val) {
+    output($val['name'] . ", " . $val['age'] . "\n");
 }
-$v = new PhpXmlRpc\Value($p, "array");
+output('
'); + +// Create xml-rpc parameters from the input array: an array of structs +$encoder = new Encoder(); +$v = $encoder->encode($inAr); output("Encoded into xmlrpc format it looks like this:
\n" . htmlentities($v->serialize()) . "
\n"); -// create client and message objects -$req = new PhpXmlRpc\Request('examples.sortByAge', array($v)); -$client = new PhpXmlRpc\Client(XMLRPCSERVER); +// create client and request objects +$req = new Request('examples.sortByAge', array($v)); +$client = new Client(XMLRPCSERVER); // set maximum debug level, to have the complete communication printed to screen $client->setDebug(2); // send request -output("Now sending request (detailed debug info follows)"); +output('Now sending the request... (very detailed debug info follows. Scroll to the bottom of the page for results!)
'); $resp = $client->send($req); +output('
'); // check response for errors, and take appropriate action if (!$resp->faultCode()) { - output("The server gave me these results:
");
+    output('The server gave me these results:
');
     $value = $resp->value();
-    foreach ($value as $struct) {
-        $name = $struct["name"];
-        $age = $struct["age"];
-        output(htmlspecialchars($name->scalarval()) . ", " . htmlspecialchars($age->scalarval()) . "\n");
+    foreach ($encoder->decode($value) as $struct) {
+        // note: here we are trusting the server's response to have the expected format
+        output(htmlspecialchars($struct['name']) . ", " . htmlspecialchars($struct['age']) . "\n");
     }
 
-    output("
For nerds: I got this value back
" .
+    output('

For nerds: I got this value back
' .
         htmlentities($resp->serialize()) . "

\n"); } else { - output("An error occurred:
");
-    output("Code: " . htmlspecialchars($resp->faultCode()) .
+    output('An error occurred:
');
+    output('Code: ' . htmlspecialchars($resp->faultCode()) .
         "\nReason: '" . htmlspecialchars($resp->faultString()) . "'

"); } diff --git a/demo/client/getstatename.php b/demo/client/getstatename.php index 2f7df378..ee838b56 100644 --- a/demo/client/getstatename.php +++ b/demo/client/getstatename.php @@ -6,35 +6,43 @@ output('

Getstatename demo

Send a U.S. state number to the server and get back the state name

-

The code demonstrates usage of automatic encoding/decoding of php variables into xmlrpc values

+

The source code demonstrates basic lib usage, including manual creation and decoding of of xml-rpc values

You can see the source to this page here: getstatename.php

'); -if (isset($_POST["stateno"]) && $_POST["stateno"] != "") { - $stateNo = (integer)$_POST["stateno"]; - $encoder = new PhpXmlRpc\Encoder(); - $req = new PhpXmlRpc\Request('examples.getStateName', - array($encoder->encode($stateNo)) +use PhpXmlRpc\Client; +use PhpXmlRpc\Request; +use PhpXmlRpc\Value; + +$stateNo = ""; + +if (isset($_POST['stateno']) && $_POST['stateno'] != "") { + $stateNo = (integer)$_POST['stateno']; + $method = 'examples.getStateName'; + $arguments = array( + new Value($stateNo, Value::$xmlrpcInt), ); - output("Sending the following request:
\n\n" . htmlentities($req->serialize()) . "\n\n
Debug info of server data follows...\n\n"); - $client = new PhpXmlRpc\Client(XMLRPCSERVER); + $req = new Request($method, $arguments); + output("Sending the following request:
\n\n" . htmlentities($req->serialize()) .
+        "\n\n
Debug info of server data follows...\n\n"); + $client = new Client(XMLRPCSERVER); $client->setDebug(1); - $r = $client->send($req); - if (!$r->faultCode()) { - $v = $r->value(); - output("
State number " . $stateNo . " is " - . htmlspecialchars($encoder->decode($v)) . "

"); + $resp = $client->send($req); + if (!$resp->faultCode()) { + $val = $resp->value(); + // NB: we are _assuming_ that the server did return a scalar xml-rpc value here. + // If the server is not trusted, we might check that via `$val->kindOf() == 'scalar'` + output('
State number ' . $stateNo . ' is ' + . htmlspecialchars($val->scalarval()) . '

'); } else { - output("An error occurred: "); - output("Code: " . htmlspecialchars($r->faultCode()) - . " Reason: '" . htmlspecialchars($r->faultString()) . "'

"); + output('An error occurred: '); + output('
Code: ' . htmlspecialchars($resp->faultCode())
+            . " Reason: '" . htmlspecialchars($resp->faultString()) . "'
"); } -} else { - $stateNo = ""; } output("
- +

Enter a state number to query its name

"); diff --git a/demo/client/introspect.php b/demo/client/introspect.php index 565e1c4a..30a0a62e 100644 --- a/demo/client/introspect.php +++ b/demo/client/introspect.php @@ -5,22 +5,28 @@ output(' xmlrpc - Introspect demo

Introspect demo

-

Query server for available methods and their description

-

The code demonstrates usage of multicall and introspection methods

+

Query server for available methods, their description and their signatures

+

The code demonstrates usage of multicall, introspection methods `system.listMethods` and co., and `$client->return_type`

You can see the source to this page here: introspect.php

'); +use PhpXmlRpc\Client; +use PhpXmlRpc\Helper\XMLParser; +use PhpXmlRpc\Request; + function display_error($r) { output("An error occurred: "); output("Code: " . $r->faultCode() . " Reason: '" . $r->faultString() . "'
"); } -$client = new PhpXmlRpc\Client(XMLRPCSERVER); +$client = new Client(XMLRPCSERVER); +// tell the client we want back plain php values +$client->return_type = XMLParser::RETURN_PHP; // First off, let's retrieve the list of methods available on the remote server output("

methods available at http://" . $client->server . $client->path . "

\n"); -$req = new PhpXmlRpc\Request('system.listMethods'); +$req = new Request('system.listMethods'); $resp = $client->send($req); if ($resp->faultCode()) { @@ -28,46 +34,61 @@ if ($resp->faultCode()) { } else { $v = $resp->value(); + // check if the server supports 'system.multicall', and configure the client accordingly + $avoidMulticall = true; + foreach ($v as $methodName) { + if ($methodName == 'system.multicall') { + $avoidMulticall = false; + break; + } + } + + $client->no_multicall = $avoidMulticall; + // Then, retrieve the signature and help text of each available method foreach ($v as $methodName) { - output("

" . htmlspecialchars($methodName->scalarval()) . "

\n"); - // build messages first, add params later - $m1 = new PhpXmlRpc\Request('system.methodHelp'); - $m2 = new PhpXmlRpc\Request('system.methodSignature'); - $val = new PhpXmlRpc\Value($methodName->scalarval(), "string"); - $m1->addParam($val); - $m2->addParam($val); - // Send multiple requests in one http call. - // If server does not support multicall, client will automatically fall back to 2 separate calls - $ms = array($m1, $m2); - $rs = $client->send($ms); - if ($rs[0]->faultCode()) { - display_error($rs[0]); + output("

" . htmlspecialchars($methodName) . "

\n"); + // build requests first, add params later + $r1 = new PhpXmlRpc\Request('system.methodHelp'); + $r2 = new PhpXmlRpc\Request('system.methodSignature'); + $val = new PhpXmlRpc\Value($methodName, "string"); + $r1->addParam($val); + $r2->addParam($val); + // Send multiple requests in one/many http calls. + $reqs = array($r1, $r2); + $resps = $client->send($reqs); + if ($resps[0]->faultCode()) { + display_error($resps[0]); } else { - $val = $rs[0]->value(); - $txt = $val->scalarval(); + output("
Documentation

\n"); + $txt = $resps[0]->value(); if ($txt != "") { - output("

Documentation

{$txt}

\n"); + // NB: we explicitly avoid escaping the received data because the spec says that html _can be_ in methodHelp. + // That is not a very good practice nevertheless! + output("

$txt

\n"); } else { output("

No documentation available.

\n"); } } - if ($rs[1]->faultCode()) { - display_error($rs[1]); + if ($resps[1]->faultCode()) { + display_error($resps[1]); } else { - output("

Signature

\n"); - // note: using PhpXmlRpc\Encoder::decode() here would lead to cleaner code - $val = $rs[1]->value(); - if ($val->kindOf() == "array") { - foreach ($val as $x) { - $ret = $x[0]; - output("" . htmlspecialchars($ret->scalarval()) . " " - . htmlspecialchars($methodName->scalarval()) . "("); - if ($x->count() > 1) { - for ($k = 1; $k < $x->count(); $k++) { - $y = $x[$k]; - output(htmlspecialchars($y->scalarval())); - if ($k < $x->count() - 1) { + output("

Signature(s)

\n"); + $sigs = $resps[1]->value(); + if (is_array($sigs)) { + foreach ($sigs as $sn => $sig) { + // can we trust the server to be fully compliant with the spec? + if (!is_array($sig)) { + output("Signature $sn: unknown\n"); + continue; + } + $ret = $sig[0]; + output("" . htmlspecialchars($ret) . " " + . htmlspecialchars($methodName) . "("); + if (count($sig) > 1) { + for ($k = 1; $k < count($sig); $k++) { + output(htmlspecialchars($sig[$k])); + if ($k < count($sig) - 1) { output(", "); } } diff --git a/demo/client/mail.php b/demo/client/mail.php deleted file mode 100644 index 06f1db89..00000000 --- a/demo/client/mail.php +++ /dev/null @@ -1,58 +0,0 @@ - -xmlrpc - Mail demo - -

Mail demo

-

This form enables you to send mail via an XML-RPC server. - When you press Send this page will reload, showing you the XML-RPC request sent to the host server, the - XML-RPC response received and the internal evaluation done by the PHP implementation.

-

You can see the source to this page here: mail.php
- And the source to a functionally identical mail-by-XML-RPC server in the file server.php included with the library (look for the "mail_send" - method)

-'); - -if (isset($_POST["mailto"]) && $_POST["mailto"]) { - $server = XMLRPCSERVER; - $req = new PhpXmlRpc\Request('mail.send', array( - new PhpXmlRpc\Value($_POST["mailto"]), - new PhpXmlRpc\Value($_POST["mailsub"]), - new PhpXmlRpc\Value($_POST["mailmsg"]), - new PhpXmlRpc\Value($_POST["mailfrom"]), - new PhpXmlRpc\Value($_POST["mailcc"]), - new PhpXmlRpc\Value($_POST["mailbcc"]), - new PhpXmlRpc\Value("text/plain") - )); - - $client = new PhpXmlRpc\Client($server); - $client->setDebug(2); - $resp = $client->send($req); - if (!$resp->faultCode()) { - output("Mail sent OK
\n"); - } else { - output(""); - output("Mail send failed
\n"); - output("Fault: "); - output("Code: " . htmlspecialchars($resp->faultCode()) . - " Reason: '" . htmlspecialchars($resp->faultString()) . "'
"); - output("

"); - } -} -output(' -
- From
-
- To
- Cc
- Bcc
-
- Subject -
- Body
- -
- - -'); diff --git a/demo/client/proxy.php b/demo/client/proxy.php index 2108e602..20bd8a0c 100644 --- a/demo/client/proxy.php +++ b/demo/client/proxy.php @@ -10,45 +10,55 @@ output('

You can see the source to this page here: proxy.php

'); -class PhpXmlRpcProxy +class XmlRpcProxy { protected $client; protected $prefix; + protected $encoder; protected $encodingOptions = array(); + /** + * We rely on injecting a fully-formed Client, so that all the necessary http/debugging options can be set into it + * without the need for this class to reimplement support for that configuration. + */ public function __construct(PhpXmlRpc\Client $client, $prefix = 'examples.', $encodingOptions = array()) { $this->client = $client; $this->prefix = $prefix; $this->encodingOptions = $encodingOptions; + $this->encoder = new PhpXmlRpc\Encoder(); } /** - * Translates any method call to an xml-rpc call. + * Translates any php method call to an xml-rpc call. + * Note that the server might expose methods which can not be called directly this way, because their name includes + * characters which are not allowed in a php method. That's why we implement as well method `call` * * @author Toth Istvan * * @param string $name remote function name. Will be prefixed - * @param array $arguments + * @param array $arguments any php value will do. For xml-rpc base64 values, wrap them in a Value object * @return mixed * * @throws Exception */ public function __call($name, $arguments) { - $encoder = new PhpXmlRpc\Encoder(); - $valueArray = array(); + $arguments = array(); foreach ($arguments as $parameter) { - $valueArray[] = $encoder->encode($parameter, $this->encodingOptions); + $arguments[] = $this->encoder->encode($parameter, $this->encodingOptions); } // just in case this was set to something else + $originalReturnType = $this->client->return_type; $this->client->return_type = 'phpvals'; - $resp = $this->client->send(new PhpXmlRpc\Request($this->prefix.$name, $valueArray)); + $resp = $this->client->send(new PhpXmlRpc\Request($this->prefix.$name, $arguments)); + + $this->client->return_type = $originalReturnType; if ($resp->faultCode()) { - throw new Exception($resp->faultString(), $resp->faultCode()); + throw new \Exception($resp->faultString(), $resp->faultCode()); } else { return $resp->value(); } @@ -58,7 +68,7 @@ class PhpXmlRpcProxy * In case the remote method name has characters which are not valid as php method names, use this. * * @param string $name remote function name. Will be prefixed - * @param array $arguments + * @param array $arguments any php value will do. For xml-rpc base64 values, wrap them in a Value object * @return mixed * * @throws Exception @@ -69,7 +79,7 @@ class PhpXmlRpcProxy } } -$proxy = new PhpXmlRpcProxy(new PhpXmlRpc\Client(XMLRPCSERVER)); +$proxy = new XmlRpcProxy(new PhpXmlRpc\Client(XMLRPCSERVER)); $stateNo = rand(1, 51); // sadly, no IDE will be able to assist with autocompletion for this method, unless you manually add an equivalent phpdoc comment... diff --git a/demo/client/which.php b/demo/client/which.php index 888c751d..1de3207f 100644 --- a/demo/client/which.php +++ b/demo/client/which.php @@ -6,16 +6,45 @@ output('

Which toolkit demo

Query server for toolkit information

-

The code demonstrates usage of the PhpXmlRpc\Encoder class

+

The code demonstrates support for http redirects, the `interopEchoTests.whichToolkit` xml-rpc methods and use of pre-built xml

You can see the source to this page here: which.php

'); -$client = new PhpXmlRpc\Client(XMLRPCSERVER); -$req = new PhpXmlRpc\Request('interopEchoTests.whichToolkit', array()); -$resp = $client->send($req); +use PhpXmlRpc\Client; +use PhpXmlRpc\Encoder; + +$client = new Client(XMLRPCSERVER); + +// to support http redirects we have to force usage of cURL even for http 1.0 requests +$client->setUseCurl(Client::USE_CURL_ALWAYS); +$client->setCurlOptions(array(CURLOPT_FOLLOWLOCATION => true, CURLOPT_POSTREDIR => 3)); + +// use a pre-built request payload +$payload = ' + + interopEchoTests.whichToolkit + +'; +// and ask the client to give us back xml +$client->return_type = 'xml'; + +output("XML custom request:
" . htmlspecialchars($payload) . "
\n"); + +$resp = $client->send($payload); + if (!$resp->faultCode()) { - $encoder = new PhpXmlRpc\Encoder(); - $value = $encoder->decode($resp->value()); + + $xml = $resp->value(); + output("XML response:
" . htmlspecialchars($xml) . "
\n"); + + $encoder = new Encoder(); + // from xml to xml-rpc Response + $response = $encoder->decodeXml($xml); + // from Response to Value + $value = $response->value(); + // from value to php + $value = $encoder->decode($value); + output("Toolkit info:
\n"); output("
");
     output("name: " . htmlspecialchars($value["toolkitName"]) . "\n");
diff --git a/demo/server/methodProviders/interop.php b/demo/server/methodProviders/interop.php
index 691a7ec6..b911cb62 100644
--- a/demo/server/methodProviders/interop.php
+++ b/demo/server/methodProviders/interop.php
@@ -114,7 +114,7 @@ function i_whichToolkit($req)
 {
     global $SERVER_SOFTWARE;
     $ret = array(
-        "toolkitDocsUrl" => "http://phpxmlrpc.sourceforge.net/",
+        "toolkitDocsUrl" => "https://gggeek.github.io/phpxmlrpc/",
         "toolkitName" => PhpXmlRpc\PhpXmlRpc::$xmlrpcName,
         "toolkitVersion" => PhpXmlRpc\PhpXmlRpc::$xmlrpcVersion,
         "toolkitOperatingSystem" => isset($SERVER_SOFTWARE) ? $SERVER_SOFTWARE : $_SERVER['SERVER_SOFTWARE'],