3 * @author Gaetano Giunta
4 * @copyright (C) 2005-2015 G. Giunta
5 * @license code licensed under the BSD License: see file license.txt
7 * @todo switch params for http compression from 0,1,2 to values to be used directly
8 * @todo use ob_start to catch debug info and echo it AFTER method call results?
9 * @todo be smarter in creating client stub for proxy/auth cases: only set appropriate property of client obj
12 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
13 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
14 <html xmlns="http://www.w3.org/1999/xhtml">
16 <title>XMLRPC Debugger</title>
17 <meta name="robots" content="index,nofollow"/>
18 <style type="text/css">
21 border-top: 1px solid gray;
23 font-family: Verdana, Arial, Helvetica;
37 background-color: #EEEEEE;
38 border: 1px dashed silver;
39 font-family: monospace;
45 background-color: #DDDDDD;
46 border: 1px solid gray;
48 font-family: monospace;
57 background-color: navy;
64 font-family: monospace;
72 background-color: #EEEEEE;
80 background-color: #EEEEEE;
91 include __DIR__ . '/common.php';
94 include_once __DIR__ . "/../src/Autoloader.php";
95 PhpXmlRpc\Autoloader::register();
97 // make sure the script waits long enough for the call to complete...
99 set_time_limit($timeout + 10);
103 @include 'jsonrpc.inc';
104 if (!class_exists('jsonrpc_client')) {
105 die('Error: to debug the jsonrpc protocol the jsonrpc.inc file is needed');
107 $clientClass = 'PhpJsRpc\client';
108 $requestClass = 'PhpJsRpc\request';
109 $protoName = 'JSONRPC';
111 $clientClass = 'PhpXmlRpc\client';
112 $requestClass = 'PhpXmlRpc\Request';
113 $protoName = 'XMLRPC';
117 $client = new $clientClass($path, $host, $port);
118 $server = "$host:$port$path";
120 $client = new $clientClass($path, $host);
121 $server = "$host$path";
123 if ($protocol == 2) {
124 $server = 'https://' . $server;
126 $server = 'http://' . $server;
129 $pproxy = explode(':', $proxy);
130 if (count($pproxy) > 1) {
135 $client->setProxy($pproxy[0], $pport, $proxyuser, $proxypwd);
138 if ($protocol == 2) {
139 $client->setSSLVerifyPeer($verifypeer);
140 $client->setSSLVerifyHost($verifyhost);
142 $client->setCaCertificate($cainfo);
144 $httpprotocol = 'https';
145 } elseif ($protocol == 1) {
146 $httpprotocol = 'http11';
148 $httpprotocol = 'http';
152 $client->setCredentials($username, $password, $authtype);
155 $client->setDebug($debug);
157 switch ($requestcompression) {
159 $client->request_compression = '';
162 $client->request_compression = 'gzip';
165 $client->request_compression = 'deflate';
169 switch ($responsecompression) {
171 $client->accepted_compression = '';
174 $client->accepted_compression = array('gzip');
177 $client->accepted_compression = array('deflate');
180 $client->accepted_compression = array('gzip', 'deflate');
184 $cookies = explode(',', $clientcookies);
185 foreach ($cookies as $cookie) {
186 if (strpos($cookie, '=')) {
187 $cookie = explode('=', $cookie);
188 $client->setCookie(trim($cookie[0]), trim(@$cookie[1]));
194 // fall thru intentionally
197 $msg[0] = new $requestClass('system.methodHelp', array(), $id);
198 $msg[0]->addparam(new PhpXmlRpc\Value($method));
199 $msg[1] = new $requestClass('system.methodSignature', array(), $id + 1);
200 $msg[1]->addparam(new PhpXmlRpc\Value($method));
201 $actionname = 'Description of method "' . $method . '"';
204 $msg[0] = new $requestClass('system.listMethods', array(), $id);
205 $actionname = 'List of available methods';
208 if (!payload_is_safe($payload)) {
209 die("Tsk tsk tsk, please stop it or I will have to call in the cops!");
211 $msg[0] = new $requestClass($method, array(), $id);
212 // hack! build xml payload by hand
214 $msg[0]->payload = "{\n" .
215 '"method": "' . $method . "\",\n\"params\": [" .
218 // fix: if user gave an empty string, use NULL, or we'll break json syntax
220 $msg[0]->payload .= "null\n}";
222 if (is_numeric($id) || $id == 'false' || $id == 'true' || $id == 'null') {
223 $msg[0]->payload .= "$id\n}";
225 $msg[0]->payload .= "\"$id\"\n}";
229 $msg[0]->payload = $msg[0]->xml_header() .
230 '<methodName>' . $method . "</methodName>\n<params>" .
232 "</params>\n" . $msg[0]->xml_footer();
234 $actionname = 'Execution of method ' . $method;
236 default: // give a warning
237 $actionname = '[ERROR: unknown action] "' . $action . '"';
240 // Before calling execute, echo out brief description of action taken + date and time ???
241 // this gives good user feedback for long-running methods...
242 echo '<h2>' . htmlspecialchars($actionname) . ' on server ' . htmlspecialchars($server) . " ...</h2>\n";
248 echo '<div class="dbginfo"><h2>Debug info:</h2>';
249 } /// @todo use ob_start instead
251 $mtime = explode(' ', microtime());
252 $time = (float)$mtime[0] + (float)$mtime[1];
253 foreach ($msg as $message) {
254 // catch errors: for older xmlrpc libs, send does not return by ref
255 @$response = $client->send($message, $timeout, $httpprotocol);
257 if (!$response || $response->faultCode()) {
261 $mtime = explode(' ', microtime());
262 $time = (float)$mtime[0] + (float)$mtime[1] - $time;
268 if ($response->faultCode()) {
269 // call failed! echo out error msg!
270 //echo '<h2>'.htmlspecialchars($actionname).' on server '.htmlspecialchars($server).'</h2>';
271 echo "<h3>$protoName call FAILED!</h3>\n";
272 echo "<p>Fault code: [" . htmlspecialchars($response->faultCode()) .
273 "] Reason: '" . htmlspecialchars($response->faultString()) . "'</p>\n";
274 echo(strftime("%d/%b/%Y:%H:%M:%S\n"));
276 // call succeeded: parse results
277 //echo '<h2>'.htmlspecialchars($actionname).' on server '.htmlspecialchars($server).'</h2>';
278 printf("<h3>%s call(s) OK (%.2f secs.)</h3>\n", $protoName, $time);
279 echo(strftime("%d/%b/%Y:%H:%M:%S\n"));
284 $v = $response->value();
285 if ($v->kindOf() == "array") {
286 $max = $v->arraysize();
287 echo "<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n";
288 echo "<thead>\n<tr><th>Method</th><th>Description</th></tr>\n</thead>\n<tbody>\n";
289 for ($i = 0; $i < $max; $i++) {
290 $rec = $v->arraymem($i);
292 $class = ' class="oddrow"';
294 $class = ' class="evenrow"';
296 echo("<tr><td$class>" . htmlspecialchars($rec->scalarval()) . "</td><td$class><form action=\"controller.php\" method=\"get\" target=\"frmcontroller\">" .
297 "<input type=\"hidden\" name=\"host\" value=\"" . htmlspecialchars($host) . "\" />" .
298 "<input type=\"hidden\" name=\"port\" value=\"" . htmlspecialchars($port) . "\" />" .
299 "<input type=\"hidden\" name=\"path\" value=\"" . htmlspecialchars($path) . "\" />" .
300 "<input type=\"hidden\" name=\"id\" value=\"" . htmlspecialchars($id) . "\" />" .
301 "<input type=\"hidden\" name=\"debug\" value=\"$debug\" />" .
302 "<input type=\"hidden\" name=\"username\" value=\"" . htmlspecialchars($username) . "\" />" .
303 "<input type=\"hidden\" name=\"password\" value=\"" . htmlspecialchars($password) . "\" />" .
304 "<input type=\"hidden\" name=\"authtype\" value=\"$authtype\" />" .
305 "<input type=\"hidden\" name=\"verifyhost\" value=\"$verifyhost\" />" .
306 "<input type=\"hidden\" name=\"verifypeer\" value=\"$verifypeer\" />" .
307 "<input type=\"hidden\" name=\"cainfo\" value=\"" . htmlspecialchars($cainfo) . "\" />" .
308 "<input type=\"hidden\" name=\"proxy\" value=\"" . htmlspecialchars($proxy) . "\" />" .
309 "<input type=\"hidden\" name=\"proxyuser\" value=\"" . htmlspecialchars($proxyuser) . "\" />" .
310 "<input type=\"hidden\" name=\"proxypwd\" value=\"" . htmlspecialchars($proxypwd) . "\" />" .
311 "<input type=\"hidden\" name=\"responsecompression\" value=\"$responsecompression\" />" .
312 "<input type=\"hidden\" name=\"requestcompression\" value=\"$requestcompression\" />" .
313 "<input type=\"hidden\" name=\"clientcookies\" value=\"" . htmlspecialchars($clientcookies) . "\" />" .
314 "<input type=\"hidden\" name=\"protocol\" value=\"$protocol\" />" .
315 "<input type=\"hidden\" name=\"timeout\" value=\"" . htmlspecialchars($timeout) . "\" />" .
316 "<input type=\"hidden\" name=\"method\" value=\"" . $rec->scalarval() . "\" />" .
317 "<input type=\"hidden\" name=\"wstype\" value=\"$wstype\" />" .
318 "<input type=\"hidden\" name=\"action\" value=\"describe\" />" .
319 "<input type=\"hidden\" name=\"run\" value=\"now\" />" .
320 "<input type=\"submit\" value=\"Describe\" /></form></td>");
323 // generate the skeleton for method payload per possible tests
324 //$methodpayload="<methodCall>\n<methodName>".$rec->scalarval()."</methodName>\n<params>\n<param><value></value></param>\n</params>\n</methodCall>";
326 /*echo ("<form action=\"{$_SERVER['PHP_SELF']}\" method=\"get\"><td>".
327 "<input type=\"hidden\" name=\"host\" value=\"$host\" />".
328 "<input type=\"hidden\" name=\"port\" value=\"$port\" />".
329 "<input type=\"hidden\" name=\"path\" value=\"$path\" />".
330 "<input type=\"hidden\" name=\"method\" value=\"".$rec->scalarval()."\" />".
331 "<input type=\"hidden\" name=\"methodpayload\" value=\"$payload\" />".
332 "<input type=\"hidden\" name=\"action\" value=\"execute\" />".
333 "<input type=\"submit\" value=\"Test\" /></td></form>");*/
336 echo "</tbody>\n</table>";
342 $r1 = $resp[0]->value();
343 $r2 = $resp[1]->value();
345 echo "<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n";
346 echo "<thead>\n<tr><th>Method</th><th>" . htmlspecialchars($method) . "</th><th> </th><th> </th></tr>\n</thead>\n<tbody>\n";
347 $desc = htmlspecialchars($r1->scalarval());
351 echo "<tr><td class=\"evenrow\">Description</td><td colspan=\"3\" class=\"evenrow\">$desc</td></tr>\n";
354 if ($r2->kindOf() != "array") {
355 echo "<tr><td class=\"oddrow\">Signature</td><td class=\"oddrow\">Unknown</td><td class=\"oddrow\"> </td></tr>\n";
357 for ($i = 0; $i < $r2->arraysize(); $i++) {
359 $class = ' class="oddrow"';
361 $class = ' class="evenrow"';
363 echo "<tr><td$class>Signature " . ($i + 1) . "</td><td$class>";
364 $x = $r2->arraymem($i);
365 if ($x->kindOf() == "array") {
366 $ret = $x->arraymem(0);
367 echo "<code>OUT: " . htmlspecialchars($ret->scalarval()) . "<br />IN: (";
368 if ($x->arraysize() > 1) {
369 for ($k = 1; $k < $x->arraysize(); $k++) {
370 $y = $x->arraymem($k);
371 echo $y->scalarval();
373 $payload = $payload . '<param><value><' . htmlspecialchars($y->scalarval()) . '></' . htmlspecialchars($y->scalarval()) . "></value></param>\n";
375 $alt_payload .= $y->scalarval();
376 if ($k < $x->arraysize() - 1) {
387 // button to test this method
388 //$payload="<methodCall>\n<methodName>$method</methodName>\n<params>\n$payload</params>\n</methodCall>";
389 echo "<td$class><form action=\"controller.php\" target=\"frmcontroller\" method=\"get\">" .
390 "<input type=\"hidden\" name=\"host\" value=\"" . htmlspecialchars($host) . "\" />" .
391 "<input type=\"hidden\" name=\"port\" value=\"" . htmlspecialchars($port) . "\" />" .
392 "<input type=\"hidden\" name=\"path\" value=\"" . htmlspecialchars($path) . "\" />" .
393 "<input type=\"hidden\" name=\"id\" value=\"" . htmlspecialchars($id) . "\" />" .
394 "<input type=\"hidden\" name=\"debug\" value=\"$debug\" />" .
395 "<input type=\"hidden\" name=\"username\" value=\"" . htmlspecialchars($username) . "\" />" .
396 "<input type=\"hidden\" name=\"password\" value=\"" . htmlspecialchars($password) . "\" />" .
397 "<input type=\"hidden\" name=\"authtype\" value=\"$authtype\" />" .
398 "<input type=\"hidden\" name=\"verifyhost\" value=\"$verifyhost\" />" .
399 "<input type=\"hidden\" name=\"verifypeer\" value=\"$verifypeer\" />" .
400 "<input type=\"hidden\" name=\"cainfo\" value=\"" . htmlspecialchars($cainfo) . "\" />" .
401 "<input type=\"hidden\" name=\"proxy\" value=\"" . htmlspecialchars($proxy) . "\" />" .
402 "<input type=\"hidden\" name=\"proxyuser\" value=\"" . htmlspecialchars($proxyuser) . "\" />" .
403 "<input type=\"hidden\" name=\"proxypwd\" value=\"" . htmlspecialchars($proxypwd) . "\" />" .
404 "<input type=\"hidden\" name=\"responsecompression\" value=\"$responsecompression\" />" .
405 "<input type=\"hidden\" name=\"requestcompression\" value=\"$requestcompression\" />" .
406 "<input type=\"hidden\" name=\"clientcookies\" value=\"" . htmlspecialchars($clientcookies) . "\" />" .
407 "<input type=\"hidden\" name=\"protocol\" value=\"$protocol\" />" .
408 "<input type=\"hidden\" name=\"timeout\" value=\"" . htmlspecialchars($timeout) . "\" />" .
409 "<input type=\"hidden\" name=\"method\" value=\"" . htmlspecialchars($method) . "\" />" .
410 "<input type=\"hidden\" name=\"methodpayload\" value=\"" . htmlspecialchars($payload) . "\" />" .
411 "<input type=\"hidden\" name=\"altmethodpayload\" value=\"" . htmlspecialchars($alt_payload) . "\" />" .
412 "<input type=\"hidden\" name=\"wstype\" value=\"$wstype\" />" .
413 "<input type=\"hidden\" name=\"action\" value=\"execute\" />";
415 echo "<input type=\"submit\" value=\"Load method synopsis\" />";
417 echo "</form></td>\n";
419 echo "<td$class><form action=\"controller.php\" target=\"frmcontroller\" method=\"get\">" .
420 "<input type=\"hidden\" name=\"host\" value=\"" . htmlspecialchars($host) . "\" />" .
421 "<input type=\"hidden\" name=\"port\" value=\"" . htmlspecialchars($port) . "\" />" .
422 "<input type=\"hidden\" name=\"path\" value=\"" . htmlspecialchars($path) . "\" />" .
423 "<input type=\"hidden\" name=\"id\" value=\"" . htmlspecialchars($id) . "\" />" .
424 "<input type=\"hidden\" name=\"debug\" value=\"$debug\" />" .
425 "<input type=\"hidden\" name=\"username\" value=\"" . htmlspecialchars($username) . "\" />" .
426 "<input type=\"hidden\" name=\"password\" value=\"" . htmlspecialchars($password) . "\" />" .
427 "<input type=\"hidden\" name=\"authtype\" value=\"$authtype\" />" .
428 "<input type=\"hidden\" name=\"verifyhost\" value=\"$verifyhost\" />" .
429 "<input type=\"hidden\" name=\"verifypeer\" value=\"$verifypeer\" />" .
430 "<input type=\"hidden\" name=\"cainfo\" value=\"" . htmlspecialchars($cainfo) . "\" />" .
431 "<input type=\"hidden\" name=\"proxy\" value=\"" . htmlspecialchars($proxy) . "\" />" .
432 "<input type=\"hidden\" name=\"proxyuser\" value=\"" . htmlspecialchars($proxyuser) . "\" />" .
433 "<input type=\"hidden\" name=\"proxypwd\" value=\"" . htmlspecialchars($proxypwd) . "\" />" .
434 "<input type=\"hidden\" name=\"responsecompression\" value=\"$responsecompression\" />" .
435 "<input type=\"hidden\" name=\"requestcompression\" value=\"$requestcompression\" />" .
436 "<input type=\"hidden\" name=\"clientcookies\" value=\"" . htmlspecialchars($clientcookies) . "\" />" .
437 "<input type=\"hidden\" name=\"protocol\" value=\"$protocol\" />" .
438 "<input type=\"hidden\" name=\"timeout\" value=\"" . htmlspecialchars($timeout) . "\" />" .
439 "<input type=\"hidden\" name=\"method\" value=\"" . htmlspecialchars($method) . "\" />" .
440 "<input type=\"hidden\" name=\"methodsig\" value=\"" . $i . "\" />" .
441 "<input type=\"hidden\" name=\"methodpayload\" value=\"" . htmlspecialchars($payload) . "\" />" .
442 "<input type=\"hidden\" name=\"altmethodpayload\" value=\"" . htmlspecialchars($alt_payload) . "\" />" .
443 "<input type=\"hidden\" name=\"wstype\" value=\"$wstype\" />" .
444 "<input type=\"hidden\" name=\"run\" value=\"now\" />" .
445 "<input type=\"hidden\" name=\"action\" value=\"wrap\" />" .
446 "<input type=\"submit\" value=\"Generate method call stub code\" />";
447 echo "</form></td></tr>\n";
450 echo "</tbody>\n</table>";
455 $r1 = $resp[0]->value();
456 $r2 = $resp[1]->value();
457 if ($r2->kindOf() != "array" || $r2->arraysize() <= $methodsig) {
458 echo "Error: signature unknown\n";
460 $mdesc = $r1->scalarval();
461 $encoder = new PhpXmlRpc\Encoder();
462 $msig = $encoder->decode($r2);
463 $msig = $msig[$methodsig];
464 $proto = $protocol == 2 ? 'https' : $protocol == 1 ? 'http11' : '';
465 if ($proxy == '' && $username == '' && !$requestcompression && !$responsecompression &&
468 $opts = 0; // simple client copy in stub code
470 $opts = 1; // complete client copy in stub code
477 //$code = wrap_xmlrpc_method($client, $method, $methodsig, 0, $proto, '', $opts);
478 $wrapper = new PhpXmlRpc\Wrapper();
479 $code = $wrapper->build_remote_method_wrapper_code($client, $method, str_replace('.', '_', $prefix . '_' . $method), $msig, $mdesc, $timeout, $proto, $opts, $prefix);
482 echo "<div id=\"phpcode\">\n";
483 highlight_string("<?php\n" . $code['docstring'] . $code['source'] . '?>');
488 // echo 'Error while building php code stub...';
494 echo '<div id="response"><h2>Response:</h2>' . htmlspecialchars($response->serialize()) . '</div>';
497 default: // give a warning
499 } // if !$response->faultCode()
502 // no action taken yet: give some instructions on debugger usage
505 <h3>Instructions on usage of the debugger</h3>
507 <li>Run a 'list available methods' action against desired server</li>
508 <li>If list of methods appears, click on 'describe method' for desired method</li>
509 <li>To run method: click on 'load method synopsis' for desired method. This will load a skeleton for method call
510 parameters in the form above. Complete all xmlrpc values with appropriate data and click 'Execute'
514 if (!extension_loaded('curl')) {
515 echo "<p class=\"evidence\">You will need to enable the CURL extension to use the HTTPS and HTTP 1.1 transports</p>\n";
521 Server Address: phpxmlrpc.sourceforge.net<br/>
526 <p>all usernames and passwords entered on the above form will be written to the web server logs of this server. Use
531 <li>2007-02-20: add visual editor for method payload; allow strings, bools as jsonrpc msg id</li>
532 <li>2006-06-26: support building php code stub for calling remote methods</li>
533 <li>2006-05-25: better support for long running queries; check for no-curl installs</li>
534 <li>2006-05-02: added support for JSON-RPC. Note that many interesting json-rpc features are not implemented
535 yet, such as notifications or multicall.
537 <li>2006-04-22: added option for setting custom CA certs to verify peer with in SSLmode</li>
538 <li>2006-03-05: added option for setting Basic/Digest/NTLM auth type</li>
539 <li>2006-01-18: added option echoing to screen xmlrpc request before sending it ('More' debug)</li>
540 <li>2005-10-01: added option for setting cookies to be sent to server</li>
541 <li>2005-08-07: added switches for compression of requests and responses and http 1.1</li>
542 <li>2005-06-27: fixed possible security breach in parsing malformed xml</li>
543 <li>2005-06-24: fixed error with calling methods having parameters...</li>