3 * Demo server for xmlrpc library.
5 * Implements a lot of webservices, including a suite of services used for
6 * interoperability testing (validator1 methods), and some whose only purpose
7 * is to be used for unit-testing the library.
9 * Please do not copy this file verbatim into your production server.
12 require_once __DIR__ . "/_bootstrap.php";
14 // out-of-band information: let the client manipulate the server operations.
15 // we do this to help the testsuite script: do not reproduce in production!
16 if (isset($_COOKIE['PHPUNIT_SELENIUM_TEST_ID']) && extension_loaded('xdebug')) {
17 $GLOBALS['PHPUNIT_COVERAGE_DATA_DIRECTORY'] = '/tmp/phpxmlrpc_coverage';
18 if (!is_dir($GLOBALS['PHPUNIT_COVERAGE_DATA_DIRECTORY'])) {
19 mkdir($GLOBALS['PHPUNIT_COVERAGE_DATA_DIRECTORY']);
22 include_once __DIR__ . "/../../vendor/phpunit/phpunit-selenium/PHPUnit/Extensions/SeleniumCommon/prepend.php";
28 * Used to test usage of object methods in dispatch maps and in wrapper code.
30 class xmlrpcServerMethodsContainer
33 * Method used to test logging of php warnings generated by user functions.
34 * @param PhpXmlRpc\Request $req
35 * @return PhpXmlRpc\Response
37 public function phpWarningGenerator($req)
39 $a = $undefinedVariable; // this triggers a warning in E_ALL mode, since $undefinedVariable is undefined
40 return new PhpXmlRpc\Response(new Value(1, Value::$xmlrpcBoolean));
44 * Method used to test catching of exceptions in the server.
45 * @param PhpXmlRpc\Request $req
48 public function exceptionGenerator($req)
50 throw new Exception("it's just a test", 1);
56 public function debugMessageGenerator($msg)
58 PhpXmlRpc\Server::xmlrpc_debugmsg($msg);
62 * A PHP version of the state-number server. Send me an integer and i'll sell you a state.
63 * Used to test wrapping of PHP methods into xmlrpc methods.
69 public static function findState($num)
71 return inner_findstate($num);
75 * Returns an instance of stdClass.
76 * Used to test wrapping of PHP objects with class preservation
78 public function returnObject()
80 $obj = new stdClass();
81 $obj->hello = 'world';
86 // a PHP version of the state-number server
87 // send me an integer and i'll sell you a state
90 "Alabama", "Alaska", "Arizona", "Arkansas", "California",
91 "Colorado", "Columbia", "Connecticut", "Delaware", "Florida",
92 "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas",
93 "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan",
94 "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada",
95 "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina",
96 "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island",
97 "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont",
98 "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming",
101 $findstate_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcInt));
102 $findstate_doc = 'When passed an integer between 1 and 51 returns the
103 name of a US state, where the integer is the index of that state name
104 in an alphabetic order.';
106 function findState($req)
111 // get the first param
112 $sno = $req->getParam(0);
114 // param must be there and of the correct type: server object does the validation for us
116 // extract the value of the state number
117 $snv = $sno->scalarval();
118 // look it up in our array (zero-based)
119 if (isset($stateNames[$snv - 1])) {
120 $stateName = $stateNames[$snv - 1];
122 // not there, so complain
123 $err = "I don't have a state for the index '" . $snv . "'";
126 // if we generated an error, create an error return response
128 return new PhpXmlRpc\Response(0, PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser, $err);
130 // otherwise, we create the right response with the state name
131 return new PhpXmlRpc\Response(new Value($stateName));
136 * Inner code of the state-number server.
137 * Used to test wrapping of PHP functions into xmlrpc methods.
139 * @param integer $stateNo the state number
141 * @return string the name of the state (or error description)
143 * @throws Exception if state is not found
145 function inner_findstate($stateNo)
149 if (isset($stateNames[$stateNo - 1])) {
150 return $stateNames[$stateNo - 1];
152 // not, there so complain
153 throw new Exception("I don't have a state for the index '" . $stateNo . "'", PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser);
157 $wrapper = new PhpXmlRpc\Wrapper();
159 $findstate2_sig = $wrapper->wrapPhpFunction('inner_findstate');
161 $findstate3_sig = $wrapper->wrapPhpFunction(array('xmlrpcServerMethodsContainer', 'findState'));
163 $obj = new xmlrpcServerMethodsContainer();
164 $findstate4_sig = $wrapper->wrapPhpFunction(array($obj, 'findstate'));
166 $findstate5_sig = $wrapper->wrapPhpFunction('xmlrpcServerMethodsContainer::findState', '', array('return_source' => true));
167 eval($findstate5_sig['source']);
169 $findstate6_sig = $wrapper->wrapPhpFunction('inner_findstate', '', array('return_source' => true));
170 eval($findstate6_sig['source']);
172 $findstate7_sig = $wrapper->wrapPhpFunction(array('xmlrpcServerMethodsContainer', 'findState'), '', array('return_source' => true));
173 eval($findstate7_sig['source']);
175 $obj = new xmlrpcServerMethodsContainer();
176 $findstate8_sig = $wrapper->wrapPhpFunction(array($obj, 'findstate'), '', array('return_source' => true));
177 eval($findstate8_sig['source']);
179 $findstate9_sig = $wrapper->wrapPhpFunction('xmlrpcServerMethodsContainer::findState', '', array('return_source' => true));
180 eval($findstate9_sig['source']);
182 $findstate10_sig = array(
183 "function" => function ($req) { return findState($req); },
184 "signature" => $findstate_sig,
185 "docstring" => $findstate_doc,
188 $findstate11_sig = $wrapper->wrapPhpFunction(function ($stateNo) { return inner_findstate($stateNo); });
190 $c = new xmlrpcServerMethodsContainer;
191 $moreSignatures = $wrapper->wrapPhpClass($c, array('prefix' => 'tests.', 'method_type' => 'all'));
193 $returnObj_sig = $wrapper->wrapPhpFunction(array($c, 'returnObject'), '', array('encode_php_objs' => true));
195 // used to test signatures with NULL params
196 $findstate12_sig = array(
197 array(Value::$xmlrpcString, Value::$xmlrpcInt, Value::$xmlrpcNull),
198 array(Value::$xmlrpcString, Value::$xmlrpcNull, Value::$xmlrpcInt),
201 function findStateWithNulls($req)
203 $a = $req->getParam(0);
204 $b = $req->getParam(1);
206 if ($a->scalartyp() == Value::$xmlrpcNull)
207 return new PhpXmlRpc\Response(new Value(inner_findstate($b->scalarval())));
209 return new PhpXmlRpc\Response(new Value(inner_findstate($a->scalarval())));
212 $addtwo_sig = array(array(Value::$xmlrpcInt, Value::$xmlrpcInt, Value::$xmlrpcInt));
213 $addtwo_doc = 'Add two integers together and return the result';
214 function addTwo($req)
216 $s = $req->getParam(0);
217 $t = $req->getParam(1);
219 return new PhpXmlRpc\Response(new Value($s->scalarval() + $t->scalarval(), Value::$xmlrpcInt));
222 $addtwodouble_sig = array(array(Value::$xmlrpcDouble, Value::$xmlrpcDouble, Value::$xmlrpcDouble));
223 $addtwodouble_doc = 'Add two doubles together and return the result';
224 function addTwoDouble($req)
226 $s = $req->getParam(0);
227 $t = $req->getParam(1);
229 return new PhpXmlRpc\Response(new Value($s->scalarval() + $t->scalarval(), Value::$xmlrpcDouble));
232 $stringecho_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcString));
233 $stringecho_doc = 'Accepts a string parameter, returns the string.';
234 function stringEcho($req)
236 // just sends back a string
237 return new PhpXmlRpc\Response(new Value($req->getParam(0)->scalarval()));
240 $echoback_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcString));
241 $echoback_doc = 'Accepts a string parameter, returns the entire incoming payload';
242 function echoBack($req)
244 // just sends back a string with what i got sent to me, just escaped, that's all
245 $s = "I got the following message:\n" . $req->serialize();
247 return new PhpXmlRpc\Response(new Value($s));
250 $echosixtyfour_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcBase64));
251 $echosixtyfour_doc = 'Accepts a base64 parameter and returns it decoded as a string';
252 function echoSixtyFour($req)
254 // Accepts an encoded value, but sends it back as a normal string.
255 // This is to test that base64 encoding is working as expected
256 $incoming = $req->getParam(0);
258 return new PhpXmlRpc\Response(new Value($incoming->scalarval(), Value::$xmlrpcString));
261 $bitflipper_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcArray));
262 $bitflipper_doc = 'Accepts an array of booleans, and returns them inverted';
263 function bitFlipper($req)
265 $v = $req->getParam(0);
266 $rv = new Value(array(), Value::$xmlrpcArray);
269 if ($b->scalarval()) {
270 $rv[] = new Value(false, Value::$xmlrpcBoolean);
272 $rv[] = new Value(true, Value::$xmlrpcBoolean);
276 return new PhpXmlRpc\Response($rv);
281 // send me an array of structs thus:
288 // and I'll return it to you in sorted order
290 function agesorter_compare($a, $b)
292 global $agesorter_arr;
294 // don't even ask me _why_ these come padded with hyphens, I couldn't tell you :p
295 $a = str_replace("-", "", $a);
296 $b = str_replace("-", "", $b);
298 if ($agesorter_arr[$a] == $agesorter_arr[$b]) {
302 return ($agesorter_arr[$a] > $agesorter_arr[$b]) ? -1 : 1;
305 $agesorter_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcArray));
306 $agesorter_doc = 'Send this method an array of [string, int] structs, eg:
313 And the array will be returned with the entries sorted by their numbers.
315 function ageSorter($req)
317 global $agesorter_arr, $s;
319 PhpXmlRpc\Server::xmlrpc_debugmsg("Entering 'agesorter'");
321 $sno = $req->getParam(0);
322 // error string for [if|when] things go wrong
326 $max = $sno->count();
327 PhpXmlRpc\Server::xmlrpc_debugmsg("Found $max array elements");
328 foreach ($sno as $i => $rec) {
329 if ($rec->kindOf() != "struct") {
330 $err = "Found non-struct in array at element $i";
333 // extract name and age from struct
336 // $n and $a are xmlrpcvals,
337 // so get the scalarval from them
338 $agar[$n->scalarval()] = $a->scalarval();
341 // create the output value
342 $v = new Value(array(), Value::$xmlrpcArray);
344 $agesorter_arr = $agar;
345 // hack, must make global as uksort() won't
346 // allow us to pass any other auxiliary information
347 uksort($agesorter_arr, 'agesorter_compare');
348 foreach($agesorter_arr as $key => $val) {
349 // recreate each struct element
352 "name" => new Value($key),
353 "age" => new Value($val, "int")
360 return new PhpXmlRpc\Response(0, PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser, $err);
362 return new PhpXmlRpc\Response($v);
366 // signature and instructions, place these in the dispatch map
367 $mailsend_sig = array(array(
368 Value::$xmlrpcBoolean, Value::$xmlrpcString, Value::$xmlrpcString,
369 Value::$xmlrpcString, Value::$xmlrpcString, Value::$xmlrpcString,
370 Value::$xmlrpcString, Value::$xmlrpcString,
372 $mailsend_doc = 'mail.send(recipient, subject, text, sender, cc, bcc, mimetype)<br/>
373 recipient, cc, and bcc are strings, comma-separated lists of email addresses, as described above.<br/>
374 subject is a string, the subject of the message.<br/>
375 sender is a string, it\'s the email address of the person sending the message. This string can not be
376 a comma-separated list, it must contain a single email address only.<br/>
377 text is a string, it contains the body of the message.<br/>
378 mimetype, a string, is a standard MIME type, for example, text/plain.
380 // WARNING; this functionality depends on the sendmail -t option
381 // it may not work with Windows machines properly; particularly
382 // the Bcc option. Sneak on your friends at your own risk!
383 function mailSend($req)
387 $mTo = $req->getParam(0);
388 $mSub = $req->getParam(1);
389 $mBody = $req->getParam(2);
390 $mFrom = $req->getParam(3);
391 $mCc = $req->getParam(4);
392 $mBcc = $req->getParam(5);
393 $mMime = $req->getParam(6);
395 if ($mTo->scalarval() == "") {
396 $err = "Error, no 'To' field specified";
399 if ($mFrom->scalarval() == "") {
400 $err = "Error, no 'From' field specified";
403 $msgHdr = "From: " . $mFrom->scalarval() . "\n";
404 $msgHdr .= "To: " . $mTo->scalarval() . "\n";
406 if ($mCc->scalarval() != "") {
407 $msgHdr .= "Cc: " . $mCc->scalarval() . "\n";
409 if ($mBcc->scalarval() != "") {
410 $msgHdr .= "Bcc: " . $mBcc->scalarval() . "\n";
412 if ($mMime->scalarval() != "") {
413 $msgHdr .= "Content-type: " . $mMime->scalarval() . "\n";
415 $msgHdr .= "X-Mailer: XML-RPC for PHP mailer 1.0";
423 $err = "Error, could not send the mail.";
428 return new PhpXmlRpc\Response(0, PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser, $err);
430 return new PhpXmlRpc\Response(new Value(true, Value::$xmlrpcBoolean));
434 $getallheaders_sig = array(array(Value::$xmlrpcStruct));
435 $getallheaders_doc = 'Returns a struct containing all the HTTP headers received with the request. Provides limited functionality with IIS';
436 function getAllHeaders_xmlrpc($req)
438 $encoder = new PhpXmlRpc\Encoder();
440 if (function_exists('getallheaders')) {
441 return new PhpXmlRpc\Response($encoder->encode(getallheaders()));
444 // IIS: poor man's version of getallheaders
445 foreach ($_SERVER as $key => $val) {
446 if (strpos($key, 'HTTP_') === 0) {
447 $key = ucfirst(str_replace('_', '-', strtolower(substr($key, 5))));
448 $headers[$key] = $val;
452 return new PhpXmlRpc\Response($encoder->encode($headers));
456 $setcookies_sig = array(array(Value::$xmlrpcInt, Value::$xmlrpcStruct));
457 $setcookies_doc = 'Sends to client a response containing a single \'1\' digit, and sets to it http cookies as received in the request (array of structs describing a cookie)';
458 function setCookies($req)
460 $encoder = new PhpXmlRpc\Encoder();
461 $cookies = $req->getParam(0);
462 foreach ($cookies as $name => $value) {
463 $cookieDesc = $encoder->decode($value);
464 setcookie($name, @$cookieDesc['value'], @$cookieDesc['expires'], @$cookieDesc['path'], @$cookieDesc['domain'], @$cookieDesc['secure']);
467 return new PhpXmlRpc\Response(new Value(1, Value::$xmlrpcInt));
470 $getcookies_sig = array(array(Value::$xmlrpcStruct));
471 $getcookies_doc = 'Sends to client a response containing all http cookies as received in the request (as struct)';
472 function getCookies($req)
474 $encoder = new PhpXmlRpc\Encoder();
475 return new PhpXmlRpc\Response($encoder->encode($_COOKIE));
478 $v1_arrayOfStructs_sig = array(array(Value::$xmlrpcInt, Value::$xmlrpcArray));
479 $v1_arrayOfStructs_doc = 'This handler takes a single parameter, an array of structs, each of which contains at least three elements named moe, larry and curly, all <i4>s. Your handler must add all the struct elements named curly and return the result.';
480 function v1_arrayOfStructs($req)
482 $sno = $req->getParam(0);
484 foreach ($sno as $str) {
485 foreach ($str as $key => $val) {
486 if ($key == "curly") {
487 $numCurly += $val->scalarval();
492 return new PhpXmlRpc\Response(new Value($numCurly, Value::$xmlrpcInt));
495 $v1_easyStruct_sig = array(array(Value::$xmlrpcInt, Value::$xmlrpcStruct));
496 $v1_easyStruct_doc = 'This handler takes a single parameter, a struct, containing at least three elements named moe, larry and curly, all <i4>s. Your handler must add the three numbers and return the result.';
497 function v1_easyStruct($req)
499 $sno = $req->getParam(0);
501 $larry = $sno["larry"];
502 $curly = $sno["curly"];
503 $num = $moe->scalarval() + $larry->scalarval() + $curly->scalarval();
505 return new PhpXmlRpc\Response(new Value($num, Value::$xmlrpcInt));
508 $v1_echoStruct_sig = array(array(Value::$xmlrpcStruct, Value::$xmlrpcStruct));
509 $v1_echoStruct_doc = 'This handler takes a single parameter, a struct. Your handler must return the struct.';
510 function v1_echoStruct($req)
512 $sno = $req->getParam(0);
514 return new PhpXmlRpc\Response($sno);
517 $v1_manyTypes_sig = array(array(
518 Value::$xmlrpcArray, Value::$xmlrpcInt, Value::$xmlrpcBoolean,
519 Value::$xmlrpcString, Value::$xmlrpcDouble, Value::$xmlrpcDateTime,
520 Value::$xmlrpcBase64,
522 $v1_manyTypes_doc = 'This handler takes six parameters, and returns an array containing all the parameters.';
523 function v1_manyTypes($req)
525 return new PhpXmlRpc\Response(new Value(
538 $v1_moderateSizeArrayCheck_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcArray));
539 $v1_moderateSizeArrayCheck_doc = 'This handler takes a single parameter, which is an array containing between 100 and 200 elements. Each of the items is a string, your handler must return a string containing the concatenated text of the first and last elements.';
540 function v1_moderateSizeArrayCheck($req)
542 $ar = $req->getParam(0);
545 $last = $ar[$sz - 1];
547 return new PhpXmlRpc\Response(new Value($first->scalarval() .
548 $last->scalarval(), Value::$xmlrpcString));
551 $v1_simpleStructReturn_sig = array(array(Value::$xmlrpcStruct, Value::$xmlrpcInt));
552 $v1_simpleStructReturn_doc = 'This handler takes one parameter, and returns a struct containing three elements, times10, times100 and times1000, the result of multiplying the number by 10, 100 and 1000.';
553 function v1_simpleStructReturn($req)
555 $sno = $req->getParam(0);
556 $v = $sno->scalarval();
558 return new PhpXmlRpc\Response(new Value(
560 "times10" => new Value($v * 10, Value::$xmlrpcInt),
561 "times100" => new Value($v * 100, Value::$xmlrpcInt),
562 "times1000" => new Value($v * 1000, Value::$xmlrpcInt)
568 $v1_nestedStruct_sig = array(array(Value::$xmlrpcInt, Value::$xmlrpcStruct));
569 $v1_nestedStruct_doc = 'This handler takes a single parameter, a struct, that models a daily calendar. At the top level, there is one struct for each year. Each year is broken down into months, and months into days. Most of the days are empty in the struct you receive, but the entry for April 1, 2000 contains a least three elements named moe, larry and curly, all <i4>s. Your handler must add the three numbers and return the result.';
570 function v1_nestedStruct($req)
572 $sno = $req->getParam(0);
574 $twoK = $sno["2000"];
575 $april = $twoK["04"];
576 $fools = $april["01"];
577 $curly = $fools["curly"];
578 $larry = $fools["larry"];
579 $moe = $fools["moe"];
581 return new PhpXmlRpc\Response(new Value($curly->scalarval() + $larry->scalarval() + $moe->scalarval(), Value::$xmlrpcInt));
584 $v1_countTheEntities_sig = array(array(Value::$xmlrpcStruct, Value::$xmlrpcString));
585 $v1_countTheEntities_doc = 'This handler takes a single parameter, a string, that contains any number of predefined entities, namely <, >, & \' and ".<BR>Your handler must return a struct that contains five fields, all numbers: ctLeftAngleBrackets, ctRightAngleBrackets, ctAmpersands, ctApostrophes, ctQuotes.';
586 function v1_countTheEntities($req)
588 $sno = $req->getParam(0);
589 $str = $sno->scalarval();
595 for ($i = 0; $i < strlen($str); $i++) {
596 $c = substr($str, $i, 1);
618 return new PhpXmlRpc\Response(new Value(
620 "ctLeftAngleBrackets" => new Value($lt, Value::$xmlrpcInt),
621 "ctRightAngleBrackets" => new Value($gt, Value::$xmlrpcInt),
622 "ctAmpersands" => new Value($amp, Value::$xmlrpcInt),
623 "ctApostrophes" => new Value($ap, Value::$xmlrpcInt),
624 "ctQuotes" => new Value($qu, Value::$xmlrpcInt)
630 // trivial interop tests
631 // http://www.xmlrpc.com/stories/storyReader$1636
633 $i_echoString_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcString));
634 $i_echoString_doc = "Echoes string.";
636 $i_echoStringArray_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcArray));
637 $i_echoStringArray_doc = "Echoes string array.";
639 $i_echoInteger_sig = array(array(Value::$xmlrpcInt, Value::$xmlrpcInt));
640 $i_echoInteger_doc = "Echoes integer.";
642 $i_echoIntegerArray_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcArray));
643 $i_echoIntegerArray_doc = "Echoes integer array.";
645 $i_echoFloat_sig = array(array(Value::$xmlrpcDouble, Value::$xmlrpcDouble));
646 $i_echoFloat_doc = "Echoes float.";
648 $i_echoFloatArray_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcArray));
649 $i_echoFloatArray_doc = "Echoes float array.";
651 $i_echoStruct_sig = array(array(Value::$xmlrpcStruct, Value::$xmlrpcStruct));
652 $i_echoStruct_doc = "Echoes struct.";
654 $i_echoStructArray_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcArray));
655 $i_echoStructArray_doc = "Echoes struct array.";
657 $i_echoValue_doc = "Echoes any value back.";
658 $i_echoValue_sig = array(array(Value::$xmlrpcValue, Value::$xmlrpcValue));
660 $i_echoBase64_sig = array(array(Value::$xmlrpcBase64, Value::$xmlrpcBase64));
661 $i_echoBase64_doc = "Echoes base64.";
663 $i_echoDate_sig = array(array(Value::$xmlrpcDateTime, Value::$xmlrpcDateTime));
664 $i_echoDate_doc = "Echoes dateTime.";
666 function i_echoParam($req)
668 $s = $req->getParam(0);
670 return new PhpXmlRpc\Response($s);
673 function i_echoString($req)
675 return i_echoParam($req);
678 function i_echoInteger($req)
680 return i_echoParam($req);
683 function i_echoFloat($req)
685 return i_echoParam($req);
688 function i_echoStruct($req)
690 return i_echoParam($req);
693 function i_echoStringArray($req)
695 return i_echoParam($req);
698 function i_echoIntegerArray($req)
700 return i_echoParam($req);
703 function i_echoFloatArray($req)
705 return i_echoParam($req);
708 function i_echoStructArray($req)
710 return i_echoParam($req);
713 function i_echoValue($req)
715 return i_echoParam($req);
718 function i_echoBase64($req)
720 return i_echoParam($req);
723 function i_echoDate($req)
725 return i_echoParam($req);
728 $i_whichToolkit_sig = array(array(Value::$xmlrpcStruct));
729 $i_whichToolkit_doc = "Returns a struct containing the following strings: toolkitDocsUrl, toolkitName, toolkitVersion, toolkitOperatingSystem.";
731 function i_whichToolkit($req)
733 global $SERVER_SOFTWARE;
735 "toolkitDocsUrl" => "http://phpxmlrpc.sourceforge.net/",
736 "toolkitName" => PhpXmlRpc\PhpXmlRpc::$xmlrpcName,
737 "toolkitVersion" => PhpXmlRpc\PhpXmlRpc::$xmlrpcVersion,
738 "toolkitOperatingSystem" => isset($SERVER_SOFTWARE) ? $SERVER_SOFTWARE : $_SERVER['SERVER_SOFTWARE'],
741 $encoder = new PhpXmlRpc\Encoder();
742 return new PhpXmlRpc\Response($encoder->encode($ret));
745 $object = new xmlrpcServerMethodsContainer();
747 "examples.getStateName" => array(
748 "function" => "findState",
749 "signature" => $findstate_sig,
750 "docstring" => $findstate_doc,
752 "examples.sortByAge" => array(
753 "function" => "ageSorter",
754 "signature" => $agesorter_sig,
755 "docstring" => $agesorter_doc,
757 "examples.addtwo" => array(
758 "function" => "addTwo",
759 "signature" => $addtwo_sig,
760 "docstring" => $addtwo_doc,
762 "examples.addtwodouble" => array(
763 "function" => "addTwoDouble",
764 "signature" => $addtwodouble_sig,
765 "docstring" => $addtwodouble_doc,
767 "examples.stringecho" => array(
768 "function" => "stringEcho",
769 "signature" => $stringecho_sig,
770 "docstring" => $stringecho_doc,
772 "examples.echo" => array(
773 "function" => "echoBack",
774 "signature" => $echoback_sig,
775 "docstring" => $echoback_doc,
777 "examples.decode64" => array(
778 "function" => "echoSixtyFour",
779 "signature" => $echosixtyfour_sig,
780 "docstring" => $echosixtyfour_doc,
782 "examples.invertBooleans" => array(
783 "function" => "bitFlipper",
784 "signature" => $bitflipper_sig,
785 "docstring" => $bitflipper_doc,
787 // signature omitted on purpose
788 "tests.generatePHPWarning" => array(
789 "function" => array($object, "phpWarningGenerator"),
791 // signature omitted on purpose
792 "tests.raiseException" => array(
793 "function" => array($object, "exceptionGenerator"),
795 // Greek word 'kosme'. NB: NOT a valid ISO8859 string!
796 // NB: we can only register this when setting internal encoding to UTF-8, or it will break system.listMethods
797 "tests.utf8methodname." . 'κόσμε' => array(
798 "function" => "stringEcho",
799 "signature" => $stringecho_sig,
800 "docstring" => $stringecho_doc,
802 /*"tests.iso88591methodname." . chr(224) . chr(252) . chr(232) => array(
803 "function" => "stringEcho",
804 "signature" => $stringecho_sig,
805 "docstring" => $stringecho_doc,
807 "examples.getallheaders" => array(
808 "function" => 'getAllHeaders_xmlrpc',
809 "signature" => $getallheaders_sig,
810 "docstring" => $getallheaders_doc,
812 "examples.setcookies" => array(
813 "function" => 'setCookies',
814 "signature" => $setcookies_sig,
815 "docstring" => $setcookies_doc,
817 "examples.getcookies" => array(
818 "function" => 'getCookies',
819 "signature" => $getcookies_sig,
820 "docstring" => $getcookies_doc,
822 "mail.send" => array(
823 "function" => "mailSend",
824 "signature" => $mailsend_sig,
825 "docstring" => $mailsend_doc,
827 "validator1.arrayOfStructsTest" => array(
828 "function" => "v1_arrayOfStructs",
829 "signature" => $v1_arrayOfStructs_sig,
830 "docstring" => $v1_arrayOfStructs_doc,
832 "validator1.easyStructTest" => array(
833 "function" => "v1_easyStruct",
834 "signature" => $v1_easyStruct_sig,
835 "docstring" => $v1_easyStruct_doc,
837 "validator1.echoStructTest" => array(
838 "function" => "v1_echoStruct",
839 "signature" => $v1_echoStruct_sig,
840 "docstring" => $v1_echoStruct_doc,
842 "validator1.manyTypesTest" => array(
843 "function" => "v1_manyTypes",
844 "signature" => $v1_manyTypes_sig,
845 "docstring" => $v1_manyTypes_doc,
847 "validator1.moderateSizeArrayCheck" => array(
848 "function" => "v1_moderateSizeArrayCheck",
849 "signature" => $v1_moderateSizeArrayCheck_sig,
850 "docstring" => $v1_moderateSizeArrayCheck_doc,
852 "validator1.simpleStructReturnTest" => array(
853 "function" => "v1_simpleStructReturn",
854 "signature" => $v1_simpleStructReturn_sig,
855 "docstring" => $v1_simpleStructReturn_doc,
857 "validator1.nestedStructTest" => array(
858 "function" => "v1_nestedStruct",
859 "signature" => $v1_nestedStruct_sig,
860 "docstring" => $v1_nestedStruct_doc,
862 "validator1.countTheEntities" => array(
863 "function" => "v1_countTheEntities",
864 "signature" => $v1_countTheEntities_sig,
865 "docstring" => $v1_countTheEntities_doc,
867 "interopEchoTests.echoString" => array(
868 "function" => "i_echoString",
869 "signature" => $i_echoString_sig,
870 "docstring" => $i_echoString_doc,
872 "interopEchoTests.echoStringArray" => array(
873 "function" => "i_echoStringArray",
874 "signature" => $i_echoStringArray_sig,
875 "docstring" => $i_echoStringArray_doc,
877 "interopEchoTests.echoInteger" => array(
878 "function" => "i_echoInteger",
879 "signature" => $i_echoInteger_sig,
880 "docstring" => $i_echoInteger_doc,
882 "interopEchoTests.echoIntegerArray" => array(
883 "function" => "i_echoIntegerArray",
884 "signature" => $i_echoIntegerArray_sig,
885 "docstring" => $i_echoIntegerArray_doc,
887 "interopEchoTests.echoFloat" => array(
888 "function" => "i_echoFloat",
889 "signature" => $i_echoFloat_sig,
890 "docstring" => $i_echoFloat_doc,
892 "interopEchoTests.echoFloatArray" => array(
893 "function" => "i_echoFloatArray",
894 "signature" => $i_echoFloatArray_sig,
895 "docstring" => $i_echoFloatArray_doc,
897 "interopEchoTests.echoStruct" => array(
898 "function" => "i_echoStruct",
899 "signature" => $i_echoStruct_sig,
900 "docstring" => $i_echoStruct_doc,
902 "interopEchoTests.echoStructArray" => array(
903 "function" => "i_echoStructArray",
904 "signature" => $i_echoStructArray_sig,
905 "docstring" => $i_echoStructArray_doc,
907 "interopEchoTests.echoValue" => array(
908 "function" => "i_echoValue",
909 "signature" => $i_echoValue_sig,
910 "docstring" => $i_echoValue_doc,
912 "interopEchoTests.echoBase64" => array(
913 "function" => "i_echoBase64",
914 "signature" => $i_echoBase64_sig,
915 "docstring" => $i_echoBase64_doc,
917 "interopEchoTests.echoDate" => array(
918 "function" => "i_echoDate",
919 "signature" => $i_echoDate_sig,
920 "docstring" => $i_echoDate_doc,
922 "interopEchoTests.whichToolkit" => array(
923 "function" => "i_whichToolkit",
924 "signature" => $i_whichToolkit_sig,
925 "docstring" => $i_whichToolkit_doc,
928 'tests.getStateName.2' => $findstate2_sig,
929 'tests.getStateName.3' => $findstate3_sig,
930 'tests.getStateName.4' => $findstate4_sig,
931 'tests.getStateName.5' => $findstate5_sig,
932 'tests.getStateName.6' => $findstate6_sig,
933 'tests.getStateName.7' => $findstate7_sig,
934 'tests.getStateName.8' => $findstate8_sig,
935 'tests.getStateName.9' => $findstate9_sig,
936 'tests.getStateName.10' => $findstate10_sig,
937 'tests.getStateName.11' => $findstate11_sig,
939 'tests.getStateName.12' => array(
940 "function" => "findStateWithNulls",
941 "signature" => $findstate12_sig,
942 "docstring" => $findstate_doc,
945 'tests.returnPhpObject' => $returnObj_sig,
948 $signatures = array_merge($signatures, $moreSignatures);
950 // Enable support for the NULL extension
951 PhpXmlRpc\PhpXmlRpc::$xmlrpc_null_extension = true;
953 $s = new PhpXmlRpc\Server($signatures, false);
955 $s->compress_response = true;
957 // Out-of-band information: let the client manipulate the server operations.
958 // We do this to help the testsuite script: do not reproduce in production!
959 if (isset($_GET['RESPONSE_ENCODING'])) {
960 $s->response_charset_encoding = $_GET['RESPONSE_ENCODING'];
962 if (isset($_GET['DETECT_ENCODINGS'])) {
963 PhpXmlRpc\PhpXmlRpc::$xmlrpc_detectencodings = $_GET['DETECT_ENCODINGS'];
965 if (isset($_GET['EXCEPTION_HANDLING'])) {
966 $s->exception_handling = $_GET['EXCEPTION_HANDLING'];
968 if (isset($_GET['FORCE_AUTH'])) {
969 // We implement both Basic and Digest auth in php to avoid having to set it up in a vhost.
970 // Code taken from php.net
971 // NB: we do NOT check for valid credentials!
972 if ($_GET['FORCE_AUTH'] == 'Basic') {
973 if (!isset($_SERVER['PHP_AUTH_USER']) && !isset($_SERVER['REMOTE_USER']) && !isset($_SERVER['REDIRECT_REMOTE_USER'])) {
974 header('HTTP/1.0 401 Unauthorized');
975 header('WWW-Authenticate: Basic realm="Phpxmlrpc Basic Realm"');
976 die('Text visible if user hits Cancel button');
978 } elseif ($_GET['FORCE_AUTH'] == 'Digest') {
979 if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
980 header('HTTP/1.1 401 Unauthorized');
981 header('WWW-Authenticate: Digest realm="Phpxmlrpc Digest Realm",qop="auth",nonce="'.uniqid().'",opaque="'.md5('Phpxmlrpc Digest Realm').'"');
982 die('Text visible if user hits Cancel button');
988 // That should do all we need!
990 // Out-of-band information: let the client manipulate the server operations.
991 // We do this to help the testsuite script: do not reproduce in production!
992 if (isset($_COOKIE['PHPUNIT_SELENIUM_TEST_ID']) && extension_loaded('xdebug')) {
993 include_once __DIR__ . "/../../vendor/phpunit/phpunit-selenium/PHPUnit/Extensions/SeleniumCommon/append.php";