Add a test for registering anonymous functions in the server dispatch map
[plcapi.git] / demo / server / server.php
1 <?php
2 /**
3  * Demo server for xmlrpc library.
4  *
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.
8  *
9  * Please do not copy this file verbatim into your production server.
10  **/
11
12 // give user a chance to see the source for this server instead of running the services
13 if ($_SERVER['REQUEST_METHOD'] != 'POST' && isset($_GET['showSource'])) {
14     highlight_file(__FILE__);
15     die();
16 }
17
18 include_once __DIR__ . "/../../vendor/autoload.php";
19
20 // out-of-band information: let the client manipulate the server operations.
21 // we do this to help the testsuite script: do not reproduce in production!
22 if (isset($_COOKIE['PHPUNIT_SELENIUM_TEST_ID']) && extension_loaded('xdebug')) {
23     $GLOBALS['PHPUNIT_COVERAGE_DATA_DIRECTORY'] = '/tmp/phpxmlrpc_coverage';
24     if (!is_dir($GLOBALS['PHPUNIT_COVERAGE_DATA_DIRECTORY'])) {
25         mkdir($GLOBALS['PHPUNIT_COVERAGE_DATA_DIRECTORY']);
26     }
27
28     include_once __DIR__ . "/../../vendor/phpunit/phpunit-selenium/PHPUnit/Extensions/SeleniumCommon/prepend.php";
29 }
30
31 use PhpXmlRpc\Value;
32
33 /**
34  * Used to test usage of object methods in dispatch maps and in wrapper code.
35  */
36 class xmlrpcServerMethodsContainer
37 {
38     /**
39      * Method used to test logging of php warnings generated by user functions.
40      */
41     public function phpWarningGenerator($req)
42     {
43         $a = $undefinedVariable; // this triggers a warning in E_ALL mode, since $undefinedVariable is undefined
44         return new PhpXmlRpc\Response(new Value(1, 'boolean'));
45     }
46
47     /**
48      * Method used to test catching of exceptions in the server.
49      */
50     public function exceptionGenerator($req)
51     {
52         throw new Exception("it's just a test", 1);
53     }
54
55     /**
56     * A PHP version of the state-number server. Send me an integer and i'll sell you a state
57     * @param integer $num
58     * @return string
59     */
60     public static function findState($num)
61     {
62         return inner_findstate($num);
63     }
64 }
65
66 // a PHP version of the state-number server
67 // send me an integer and i'll sell you a state
68
69 $stateNames = array(
70     "Alabama", "Alaska", "Arizona", "Arkansas", "California",
71     "Colorado", "Columbia", "Connecticut", "Delaware", "Florida",
72     "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas",
73     "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan",
74     "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada",
75     "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina",
76     "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island",
77     "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont",
78     "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming",
79 );
80
81 $findstate_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcInt));
82 $findstate_doc = 'When passed an integer between 1 and 51 returns the
83 name of a US state, where the integer is the index of that state name
84 in an alphabetic order.';
85
86 function findState($req)
87 {
88     global $stateNames;
89
90     $err = "";
91     // get the first param
92     $sno = $req->getParam(0);
93
94     // param must be there and of the correct type: server object does the validation for us
95
96     // extract the value of the state number
97     $snv = $sno->scalarval();
98     // look it up in our array (zero-based)
99     if (isset($stateNames[$snv - 1])) {
100         $stateName = $stateNames[$snv - 1];
101     } else {
102         // not there, so complain
103         $err = "I don't have a state for the index '" . $snv . "'";
104     }
105
106     // if we generated an error, create an error return response
107     if ($err) {
108         return new PhpXmlRpc\Response(0, PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser, $err);
109     } else {
110         // otherwise, we create the right response with the state name
111         return new PhpXmlRpc\Response(new Value($stateName));
112     }
113 }
114
115 /**
116  * Inner code of the state-number server.
117  * Used to test auto-registration of PHP functions as xmlrpc methods.
118  *
119  * @param integer $stateNo the state number
120  *
121  * @return string the name of the state (or error description)
122  */
123 function inner_findstate($stateNo)
124 {
125     global $stateNames;
126
127     if (isset($stateNames[$stateNo - 1])) {
128         return $stateNames[$stateNo - 1];
129     } else {
130         // not, there so complain
131         return "I don't have a state for the index '" . $stateNo . "'";
132     }
133 }
134
135 $findStateClosure = function ($req)
136 {
137     return findState($req);
138 };
139
140 $wrapper = new PhpXmlRpc\Wrapper();
141
142 $findstate2_sig = $wrapper->wrap_php_function('inner_findstate');
143
144 $findstate3_sig = $wrapper->wrap_php_function(array('xmlrpcServerMethodsContainer', 'findState'));
145
146 $findstate5_sig = $wrapper->wrap_php_function('xmlrpcServerMethodsContainer::findState');
147
148 $obj = new xmlrpcServerMethodsContainer();
149 $findstate4_sig = $wrapper->wrap_php_function(array($obj, 'findstate'));
150
151 $addtwo_sig = array(array(Value::$xmlrpcInt, Value::$xmlrpcInt, Value::$xmlrpcInt));
152 $addtwo_doc = 'Add two integers together and return the result';
153 function addTwo($req)
154 {
155     $s = $req->getParam(0);
156     $t = $req->getParam(1);
157
158     return new PhpXmlRpc\Response(new Value($s->scalarval() + $t->scalarval(), "int"));
159 }
160
161 $addtwodouble_sig = array(array(Value::$xmlrpcDouble, Value::$xmlrpcDouble, Value::$xmlrpcDouble));
162 $addtwodouble_doc = 'Add two doubles together and return the result';
163 function addTwoDouble($req)
164 {
165     $s = $req->getParam(0);
166     $t = $req->getParam(1);
167
168     return new PhpXmlRpc\Response(new Value($s->scalarval() + $t->scalarval(), "double"));
169 }
170
171 $stringecho_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcString));
172 $stringecho_doc = 'Accepts a string parameter, returns the string.';
173 function stringEcho($req)
174 {
175     // just sends back a string
176     return new PhpXmlRpc\Response(new Value($req->getParam(0)->scalarval()));
177 }
178
179 $echoback_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcString));
180 $echoback_doc = 'Accepts a string parameter, returns the entire incoming payload';
181 function echoBack($req)
182 {
183     // just sends back a string with what i got sent to me, just escaped, that's all
184     $s = "I got the following message:\n" . $req->serialize();
185
186     return new PhpXmlRpc\Response(new Value($s));
187 }
188
189 $echosixtyfour_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcBase64));
190 $echosixtyfour_doc = 'Accepts a base64 parameter and returns it decoded as a string';
191 function echoSixtyFour($req)
192 {
193     // Accepts an encoded value, but sends it back as a normal string.
194     // This is to test that base64 encoding is working as expected
195     $incoming = $req->getParam(0);
196
197     return new PhpXmlRpc\Response(new Value($incoming->scalarval(), "string"));
198 }
199
200 $bitflipper_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcArray));
201 $bitflipper_doc = 'Accepts an array of booleans, and returns them inverted';
202 function bitFlipper($req)
203 {
204     $v = $req->getParam(0);
205     $sz = $v->arraysize();
206     $rv = new Value(array(), Value::$xmlrpcArray);
207
208     for ($j = 0; $j < $sz; $j++) {
209         $b = $v->arraymem($j);
210         if ($b->scalarval()) {
211             $rv->addScalar(false, "boolean");
212         } else {
213             $rv->addScalar(true, "boolean");
214         }
215     }
216
217     return new PhpXmlRpc\Response($rv);
218 }
219
220 // Sorting demo
221 //
222 // send me an array of structs thus:
223 //
224 // Dave 35
225 // Edd  45
226 // Fred 23
227 // Barney 37
228 //
229 // and I'll return it to you in sorted order
230
231 function agesorter_compare($a, $b)
232 {
233     global $agesorter_arr;
234
235     // don't even ask me _why_ these come padded with hyphens, I couldn't tell you :p
236     $a = str_replace("-", "", $a);
237     $b = str_replace("-", "", $b);
238
239     if ($agesorter_arr[$a] == $agesorter_arr[$b]) {
240         return 0;
241     }
242
243     return ($agesorter_arr[$a] > $agesorter_arr[$b]) ? -1 : 1;
244 }
245
246 $agesorter_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcArray));
247 $agesorter_doc = 'Send this method an array of [string, int] structs, eg:
248 <pre>
249  Dave   35
250  Edd    45
251  Fred   23
252  Barney 37
253 </pre>
254 And the array will be returned with the entries sorted by their numbers.
255 ';
256 function ageSorter($req)
257 {
258     global $agesorter_arr, $s;
259
260     PhpXmlRpc\Server::xmlrpc_debugmsg("Entering 'agesorter'");
261     // get the parameter
262     $sno = $req->getParam(0);
263     // error string for [if|when] things go wrong
264     $err = "";
265     // create the output value
266     $v = new Value();
267     $agar = array();
268
269     $max = $sno->arraysize();
270     PhpXmlRpc\Server::xmlrpc_debugmsg("Found $max array elements");
271     for ($i = 0; $i < $max; $i++) {
272         $rec = $sno->arraymem($i);
273         if ($rec->kindOf() != "struct") {
274             $err = "Found non-struct in array at element $i";
275             break;
276         }
277         // extract name and age from struct
278         $n = $rec->structmem("name");
279         $a = $rec->structmem("age");
280         // $n and $a are xmlrpcvals,
281         // so get the scalarval from them
282         $agar[$n->scalarval()] = $a->scalarval();
283     }
284
285     $agesorter_arr = $agar;
286     // hack, must make global as uksort() won't
287     // allow us to pass any other auxiliary information
288     uksort($agesorter_arr, 'agesorter_compare');
289     $outAr = array();
290     while (list($key, $val) = each($agesorter_arr)) {
291         // recreate each struct element
292         $outAr[] = new Value(array("name" => new Value($key),
293             "age" => new Value($val, "int"),), "struct");
294     }
295     // add this array to the output value
296     $v->addArray($outAr);
297
298     if ($err) {
299         return new PhpXmlRpc\Response(0, PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser, $err);
300     } else {
301         return new PhpXmlRpc\Response($v);
302     }
303 }
304
305 // signature and instructions, place these in the dispatch
306 // map
307 $mailsend_sig = array(array(
308     Value::$xmlrpcBoolean, Value::$xmlrpcString, Value::$xmlrpcString,
309     Value::$xmlrpcString, Value::$xmlrpcString, Value::$xmlrpcString,
310     Value::$xmlrpcString, Value::$xmlrpcString,
311 ));
312 $mailsend_doc = 'mail.send(recipient, subject, text, sender, cc, bcc, mimetype)<br/>
313 recipient, cc, and bcc are strings, comma-separated lists of email addresses, as described above.<br/>
314 subject is a string, the subject of the message.<br/>
315 sender is a string, it\'s the email address of the person sending the message. This string can not be
316 a comma-separated list, it must contain a single email address only.<br/>
317 text is a string, it contains the body of the message.<br/>
318 mimetype, a string, is a standard MIME type, for example, text/plain.
319 ';
320 // WARNING; this functionality depends on the sendmail -t option
321 // it may not work with Windows machines properly; particularly
322 // the Bcc option. Sneak on your friends at your own risk!
323 function mailSend($req)
324 {
325     $err = "";
326
327     $mTo = $req->getParam(0);
328     $mSub = $req->getParam(1);
329     $mBody = $req->getParam(2);
330     $mFrom = $req->getParam(3);
331     $mCc = $req->getParam(4);
332     $mBcc = $req->getParam(5);
333     $mMime = $req->getParam(6);
334
335     if ($mTo->scalarval() == "") {
336         $err = "Error, no 'To' field specified";
337     }
338
339     if ($mFrom->scalarval() == "") {
340         $err = "Error, no 'From' field specified";
341     }
342
343     $msgHdr = "From: " . $mFrom->scalarval() . "\n";
344     $msgHdr .= "To: " . $mTo->scalarval() . "\n";
345
346     if ($mCc->scalarval() != "") {
347         $msgHdr .= "Cc: " . $mCc->scalarval() . "\n";
348     }
349     if ($mBcc->scalarval() != "") {
350         $msgHdr .= "Bcc: " . $mBcc->scalarval() . "\n";
351     }
352     if ($mMime->scalarval() != "") {
353         $msgHdr .= "Content-type: " . $mMime->scalarval() . "\n";
354     }
355     $msgHdr .= "X-Mailer: XML-RPC for PHP mailer 1.0";
356
357     if ($err == "") {
358         if (!mail("",
359             $mSub->scalarval(),
360             $mBody->scalarval(),
361             $msgHdr)
362         ) {
363             $err = "Error, could not send the mail.";
364         }
365     }
366
367     if ($err) {
368         return new PhpXmlRpc\Response(0, PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser, $err);
369     } else {
370         return new PhpXmlRpc\Response(new Value("true", Value::$xmlrpcBoolean));
371     }
372 }
373
374 $getallheaders_sig = array(array(Value::$xmlrpcStruct));
375 $getallheaders_doc = 'Returns a struct containing all the HTTP headers received with the request. Provides limited functionality with IIS';
376 function getAllHeaders_xmlrpc($req)
377 {
378     $encoder = new PhpXmlRpc\Encoder();
379
380     if (function_exists('getallheaders')) {
381         return new PhpXmlRpc\Response($encoder->encode(getallheaders()));
382     } else {
383         $headers = array();
384         // IIS: poor man's version of getallheaders
385         foreach ($_SERVER as $key => $val) {
386             if (strpos($key, 'HTTP_') === 0) {
387                 $key = ucfirst(str_replace('_', '-', strtolower(substr($key, 5))));
388                 $headers[$key] = $val;
389             }
390         }
391
392         return new PhpXmlRpc\Response($encoder->encode($headers));
393     }
394 }
395
396 $setcookies_sig = array(array(Value::$xmlrpcInt, Value::$xmlrpcStruct));
397 $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)';
398 function setCookies($req)
399 {
400     $encoder = new PhpXmlRpc\Encoder();
401     $m = $req->getParam(0);
402     while (list($name, $value) = $m->structeach()) {
403         $cookieDesc = $encoder->decode($value);
404         setcookie($name, @$cookieDesc['value'], @$cookieDesc['expires'], @$cookieDesc['path'], @$cookieDesc['domain'], @$cookieDesc['secure']);
405     }
406
407     return new PhpXmlRpc\Response(new Value(1, 'int'));
408 }
409
410 $getcookies_sig = array(array(Value::$xmlrpcStruct));
411 $getcookies_doc = 'Sends to client a response containing all http cookies as received in the request (as struct)';
412 function getCookies($req)
413 {
414     $encoder = new PhpXmlRpc\Encoder();
415     return new PhpXmlRpc\Response($encoder->encode($_COOKIE));
416 }
417
418 $v1_arrayOfStructs_sig = array(array(Value::$xmlrpcInt, Value::$xmlrpcArray));
419 $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.';
420 function v1_arrayOfStructs($req)
421 {
422     $sno = $req->getParam(0);
423     $numCurly = 0;
424     for ($i = 0; $i < $sno->arraysize(); $i++) {
425         $str = $sno->arraymem($i);
426         $str->structreset();
427         while (list($key, $val) = $str->structeach()) {
428             if ($key == "curly") {
429                 $numCurly += $val->scalarval();
430             }
431         }
432     }
433
434     return new PhpXmlRpc\Response(new Value($numCurly, "int"));
435 }
436
437 $v1_easyStruct_sig = array(array(Value::$xmlrpcInt, Value::$xmlrpcStruct));
438 $v1_easyStruct_doc = 'This handler takes a single parameter, a struct, containing at least three elements named moe, larry and curly, all &lt;i4&gt;s. Your handler must add the three numbers and return the result.';
439 function v1_easyStruct($req)
440 {
441     $sno = $req->getParam(0);
442     $moe = $sno->structmem("moe");
443     $larry = $sno->structmem("larry");
444     $curly = $sno->structmem("curly");
445     $num = $moe->scalarval() + $larry->scalarval() + $curly->scalarval();
446
447     return new PhpXmlRpc\Response(new Value($num, "int"));
448 }
449
450 $v1_echoStruct_sig = array(array(Value::$xmlrpcStruct, Value::$xmlrpcStruct));
451 $v1_echoStruct_doc = 'This handler takes a single parameter, a struct. Your handler must return the struct.';
452 function v1_echoStruct($req)
453 {
454     $sno = $req->getParam(0);
455
456     return new PhpXmlRpc\Response($sno);
457 }
458
459 $v1_manyTypes_sig = array(array(
460     Value::$xmlrpcArray, Value::$xmlrpcInt, Value::$xmlrpcBoolean,
461     Value::$xmlrpcString, Value::$xmlrpcDouble, Value::$xmlrpcDateTime,
462     Value::$xmlrpcBase64,
463 ));
464 $v1_manyTypes_doc = 'This handler takes six parameters, and returns an array containing all the parameters.';
465 function v1_manyTypes($req)
466 {
467     return new PhpXmlRpc\Response(new Value(array(
468         $req->getParam(0),
469         $req->getParam(1),
470         $req->getParam(2),
471         $req->getParam(3),
472         $req->getParam(4),
473         $req->getParam(5),),
474         "array"
475     ));
476 }
477
478 $v1_moderateSizeArrayCheck_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcArray));
479 $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.';
480 function v1_moderateSizeArrayCheck($req)
481 {
482     $ar = $req->getParam(0);
483     $sz = $ar->arraysize();
484     $first = $ar->arraymem(0);
485     $last = $ar->arraymem($sz - 1);
486
487     return new PhpXmlRpc\Response(new Value($first->scalarval() .
488         $last->scalarval(), "string"));
489 }
490
491 $v1_simpleStructReturn_sig = array(array(Value::$xmlrpcStruct, Value::$xmlrpcInt));
492 $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.';
493 function v1_simpleStructReturn($req)
494 {
495     $sno = $req->getParam(0);
496     $v = $sno->scalarval();
497
498     return new PhpXmlRpc\Response(new Value(array(
499         "times10" => new Value($v * 10, "int"),
500         "times100" => new Value($v * 100, "int"),
501         "times1000" => new Value($v * 1000, "int"),),
502         "struct"
503     ));
504 }
505
506 $v1_nestedStruct_sig = array(array(Value::$xmlrpcInt, Value::$xmlrpcStruct));
507 $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 &lt;i4&gt;s. Your handler must add the three numbers and return the result.';
508 function v1_nestedStruct($req)
509 {
510     $sno = $req->getParam(0);
511
512     $twoK = $sno->structmem("2000");
513     $april = $twoK->structmem("04");
514     $fools = $april->structmem("01");
515     $curly = $fools->structmem("curly");
516     $larry = $fools->structmem("larry");
517     $moe = $fools->structmem("moe");
518
519     return new PhpXmlRpc\Response(new Value($curly->scalarval() + $larry->scalarval() + $moe->scalarval(), "int"));
520 }
521
522 $v1_countTheEntities_sig = array(array(Value::$xmlrpcStruct, Value::$xmlrpcString));
523 $v1_countTheEntities_doc = 'This handler takes a single parameter, a string, that contains any number of predefined entities, namely &lt;, &gt;, &amp; \' and ".<BR>Your handler must return a struct that contains five fields, all numbers: ctLeftAngleBrackets, ctRightAngleBrackets, ctAmpersands, ctApostrophes, ctQuotes.';
524 function v1_countTheEntities($req)
525 {
526     $sno = $req->getParam(0);
527     $str = $sno->scalarval();
528     $gt = 0;
529     $lt = 0;
530     $ap = 0;
531     $qu = 0;
532     $amp = 0;
533     for ($i = 0; $i < strlen($str); $i++) {
534         $c = substr($str, $i, 1);
535         switch ($c) {
536             case ">":
537                 $gt++;
538                 break;
539             case "<":
540                 $lt++;
541                 break;
542             case "\"":
543                 $qu++;
544                 break;
545             case "'":
546                 $ap++;
547                 break;
548             case "&":
549                 $amp++;
550                 break;
551             default:
552                 break;
553         }
554     }
555
556     return new PhpXmlRpc\Response(new Value(array(
557         "ctLeftAngleBrackets" => new Value($lt, "int"),
558         "ctRightAngleBrackets" => new Value($gt, "int"),
559         "ctAmpersands" => new Value($amp, "int"),
560         "ctApostrophes" => new Value($ap, "int"),
561         "ctQuotes" => new Value($qu, "int"),),
562         "struct"
563     ));
564 }
565
566 // trivial interop tests
567 // http://www.xmlrpc.com/stories/storyReader$1636
568
569 $i_echoString_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcString));
570 $i_echoString_doc = "Echoes string.";
571
572 $i_echoStringArray_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcArray));
573 $i_echoStringArray_doc = "Echoes string array.";
574
575 $i_echoInteger_sig = array(array(Value::$xmlrpcInt, Value::$xmlrpcInt));
576 $i_echoInteger_doc = "Echoes integer.";
577
578 $i_echoIntegerArray_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcArray));
579 $i_echoIntegerArray_doc = "Echoes integer array.";
580
581 $i_echoFloat_sig = array(array(Value::$xmlrpcDouble, Value::$xmlrpcDouble));
582 $i_echoFloat_doc = "Echoes float.";
583
584 $i_echoFloatArray_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcArray));
585 $i_echoFloatArray_doc = "Echoes float array.";
586
587 $i_echoStruct_sig = array(array(Value::$xmlrpcStruct, Value::$xmlrpcStruct));
588 $i_echoStruct_doc = "Echoes struct.";
589
590 $i_echoStructArray_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcArray));
591 $i_echoStructArray_doc = "Echoes struct array.";
592
593 $i_echoValue_doc = "Echoes any value back.";
594 $i_echoValue_sig = array(array(Value::$xmlrpcValue, Value::$xmlrpcValue));
595
596 $i_echoBase64_sig = array(array(Value::$xmlrpcBase64, Value::$xmlrpcBase64));
597 $i_echoBase64_doc = "Echoes base64.";
598
599 $i_echoDate_sig = array(array(Value::$xmlrpcDateTime, Value::$xmlrpcDateTime));
600 $i_echoDate_doc = "Echoes dateTime.";
601
602 function i_echoParam($req)
603 {
604     $s = $req->getParam(0);
605
606     return new PhpXmlRpc\Response($s);
607 }
608
609 function i_echoString($req)
610 {
611     return i_echoParam($req);
612 }
613
614 function i_echoInteger($req)
615 {
616     return i_echoParam($req);
617 }
618
619 function i_echoFloat($req)
620 {
621     return i_echoParam($req);
622 }
623
624 function i_echoStruct($req)
625 {
626     return i_echoParam($req);
627 }
628
629 function i_echoStringArray($req)
630 {
631     return i_echoParam($req);
632 }
633
634 function i_echoIntegerArray($req)
635 {
636     return i_echoParam($req);
637 }
638
639 function i_echoFloatArray($req)
640 {
641     return i_echoParam($req);
642 }
643
644 function i_echoStructArray($req)
645 {
646     return i_echoParam($req);
647 }
648
649 function i_echoValue($req)
650 {
651     return i_echoParam($req);
652 }
653
654 function i_echoBase64($req)
655 {
656     return i_echoParam($req);
657 }
658
659 function i_echoDate($req)
660 {
661     return i_echoParam($req);
662 }
663
664 $i_whichToolkit_sig = array(array(Value::$xmlrpcStruct));
665 $i_whichToolkit_doc = "Returns a struct containing the following strings: toolkitDocsUrl, toolkitName, toolkitVersion, toolkitOperatingSystem.";
666
667 function i_whichToolkit($req)
668 {
669     global $SERVER_SOFTWARE;
670     $ret = array(
671         "toolkitDocsUrl" => "http://phpxmlrpc.sourceforge.net/",
672         "toolkitName" => PhpXmlRpc\PhpXmlRpc::$xmlrpcName,
673         "toolkitVersion" => PhpXmlRpc\PhpXmlRpc::$xmlrpcVersion,
674         "toolkitOperatingSystem" => isset($SERVER_SOFTWARE) ? $SERVER_SOFTWARE : $_SERVER['SERVER_SOFTWARE'],
675     );
676
677     $encoder = new PhpXmlRpc\Encoder();
678     return new PhpXmlRpc\Response($encoder->encode($ret));
679 }
680
681 $object = new xmlrpcServerMethodsContainer();
682 $signatures = array(
683     "examples.getStateName" => array(
684         "function" => "findState",
685         "signature" => $findstate_sig,
686         "docstring" => $findstate_doc,
687     ),
688     "examples.sortByAge" => array(
689         "function" => "ageSorter",
690         "signature" => $agesorter_sig,
691         "docstring" => $agesorter_doc,
692     ),
693     "examples.addtwo" => array(
694         "function" => "addTwo",
695         "signature" => $addtwo_sig,
696         "docstring" => $addtwo_doc,
697     ),
698     "examples.addtwodouble" => array(
699         "function" => "addTwoDouble",
700         "signature" => $addtwodouble_sig,
701         "docstring" => $addtwodouble_doc,
702     ),
703     "examples.stringecho" => array(
704         "function" => "stringEcho",
705         "signature" => $stringecho_sig,
706         "docstring" => $stringecho_doc,
707     ),
708     "examples.echo" => array(
709         "function" => "echoBack",
710         "signature" => $echoback_sig,
711         "docstring" => $echoback_doc,
712     ),
713     "examples.decode64" => array(
714         "function" => "echoSixtyFour",
715         "signature" => $echosixtyfour_sig,
716         "docstring" => $echosixtyfour_doc,
717     ),
718     "examples.invertBooleans" => array(
719         "function" => "bitFlipper",
720         "signature" => $bitflipper_sig,
721         "docstring" => $bitflipper_doc,
722     ),
723     // signature omitted on purpose
724     "tests.generatePHPWarning" => array(
725         "function" => array($object, "phpWarningGenerator"),
726     ),
727     // signature omitted on purpose
728     "tests.raiseException" => array(
729         "function" => array($object, "exceptionGenerator"),
730     ),
731     // Greek word 'kosme'. NB: NOT a valid ISO8859 string!
732     // NB: we can only register this when setting internal encoding to UTF-8, or it will break system.listMethods
733     "tests.utf8methodname." . 'κόσμε' => array(
734         "function" => "stringEcho",
735         "signature" => $stringecho_sig,
736         "docstring" => $stringecho_doc,
737     ),
738     /*"tests.iso88591methodname." . chr(224) . chr(252) . chr(232) => array(
739         "function" => "stringEcho",
740         "signature" => $stringecho_sig,
741         "docstring" => $stringecho_doc,
742     ),*/
743     "examples.getallheaders" => array(
744         "function" => 'getAllHeaders_xmlrpc',
745         "signature" => $getallheaders_sig,
746         "docstring" => $getallheaders_doc,
747     ),
748     "examples.setcookies" => array(
749         "function" => 'setCookies',
750         "signature" => $setcookies_sig,
751         "docstring" => $setcookies_doc,
752     ),
753     "examples.getcookies" => array(
754         "function" => 'getCookies',
755         "signature" => $getcookies_sig,
756         "docstring" => $getcookies_doc,
757     ),
758     "mail.send" => array(
759         "function" => "mailSend",
760         "signature" => $mailsend_sig,
761         "docstring" => $mailsend_doc,
762     ),
763     "validator1.arrayOfStructsTest" => array(
764         "function" => "v1_arrayOfStructs",
765         "signature" => $v1_arrayOfStructs_sig,
766         "docstring" => $v1_arrayOfStructs_doc,
767     ),
768     "validator1.easyStructTest" => array(
769         "function" => "v1_easyStruct",
770         "signature" => $v1_easyStruct_sig,
771         "docstring" => $v1_easyStruct_doc,
772     ),
773     "validator1.echoStructTest" => array(
774         "function" => "v1_echoStruct",
775         "signature" => $v1_echoStruct_sig,
776         "docstring" => $v1_echoStruct_doc,
777     ),
778     "validator1.manyTypesTest" => array(
779         "function" => "v1_manyTypes",
780         "signature" => $v1_manyTypes_sig,
781         "docstring" => $v1_manyTypes_doc,
782     ),
783     "validator1.moderateSizeArrayCheck" => array(
784         "function" => "v1_moderateSizeArrayCheck",
785         "signature" => $v1_moderateSizeArrayCheck_sig,
786         "docstring" => $v1_moderateSizeArrayCheck_doc,
787     ),
788     "validator1.simpleStructReturnTest" => array(
789         "function" => "v1_simpleStructReturn",
790         "signature" => $v1_simpleStructReturn_sig,
791         "docstring" => $v1_simpleStructReturn_doc,
792     ),
793     "validator1.nestedStructTest" => array(
794         "function" => "v1_nestedStruct",
795         "signature" => $v1_nestedStruct_sig,
796         "docstring" => $v1_nestedStruct_doc,
797     ),
798     "validator1.countTheEntities" => array(
799         "function" => "v1_countTheEntities",
800         "signature" => $v1_countTheEntities_sig,
801         "docstring" => $v1_countTheEntities_doc,
802     ),
803     "interopEchoTests.echoString" => array(
804         "function" => "i_echoString",
805         "signature" => $i_echoString_sig,
806         "docstring" => $i_echoString_doc,
807     ),
808     "interopEchoTests.echoStringArray" => array(
809         "function" => "i_echoStringArray",
810         "signature" => $i_echoStringArray_sig,
811         "docstring" => $i_echoStringArray_doc,
812     ),
813     "interopEchoTests.echoInteger" => array(
814         "function" => "i_echoInteger",
815         "signature" => $i_echoInteger_sig,
816         "docstring" => $i_echoInteger_doc,
817     ),
818     "interopEchoTests.echoIntegerArray" => array(
819         "function" => "i_echoIntegerArray",
820         "signature" => $i_echoIntegerArray_sig,
821         "docstring" => $i_echoIntegerArray_doc,
822     ),
823     "interopEchoTests.echoFloat" => array(
824         "function" => "i_echoFloat",
825         "signature" => $i_echoFloat_sig,
826         "docstring" => $i_echoFloat_doc,
827     ),
828     "interopEchoTests.echoFloatArray" => array(
829         "function" => "i_echoFloatArray",
830         "signature" => $i_echoFloatArray_sig,
831         "docstring" => $i_echoFloatArray_doc,
832     ),
833     "interopEchoTests.echoStruct" => array(
834         "function" => "i_echoStruct",
835         "signature" => $i_echoStruct_sig,
836         "docstring" => $i_echoStruct_doc,
837     ),
838     "interopEchoTests.echoStructArray" => array(
839         "function" => "i_echoStructArray",
840         "signature" => $i_echoStructArray_sig,
841         "docstring" => $i_echoStructArray_doc,
842     ),
843     "interopEchoTests.echoValue" => array(
844         "function" => "i_echoValue",
845         "signature" => $i_echoValue_sig,
846         "docstring" => $i_echoValue_doc,
847     ),
848     "interopEchoTests.echoBase64" => array(
849         "function" => "i_echoBase64",
850         "signature" => $i_echoBase64_sig,
851         "docstring" => $i_echoBase64_doc,
852     ),
853     "interopEchoTests.echoDate" => array(
854         "function" => "i_echoDate",
855         "signature" => $i_echoDate_sig,
856         "docstring" => $i_echoDate_doc,
857     ),
858     "interopEchoTests.whichToolkit" => array(
859         "function" => "i_whichToolkit",
860         "signature" => $i_whichToolkit_sig,
861         "docstring" => $i_whichToolkit_doc,
862     ),
863 );
864
865 if ($findstate2_sig) {
866     $signatures['examples.php.getStateName'] = $findstate2_sig;
867 }
868
869 if ($findstate3_sig) {
870     $signatures['examples.php2.getStateName'] = $findstate3_sig;
871 }
872
873 if ($findstate4_sig) {
874     $signatures['examples.php3.getStateName'] = $findstate4_sig;
875 }
876
877 if ($findstate5_sig) {
878     $signatures['examples.php4.getStateName'] = $findstate5_sig;
879 }
880
881 $signatures['examples.php5.getStateName'] = array(
882     "function" => $findStateClosure,
883     "signature" => $findstate_sig,
884     "docstring" => $findstate_doc,
885 );
886
887 $s = new PhpXmlRpc\Server($signatures, false);
888 $s->setdebug(3);
889 $s->compress_response = true;
890
891 // out-of-band information: let the client manipulate the server operations.
892 // we do this to help the testsuite script: do not reproduce in production!
893 if (isset($_GET['RESPONSE_ENCODING'])) {
894     $s->response_charset_encoding = $_GET['RESPONSE_ENCODING'];
895 }
896 if (isset($_GET['EXCEPTION_HANDLING'])) {
897     $s->exception_handling = $_GET['EXCEPTION_HANDLING'];
898 }
899 $s->service();
900 // that should do all we need!
901
902 // out-of-band information: let the client manipulate the server operations.
903 // we do this to help the testsuite script: do not reproduce in production!
904 if (isset($_COOKIE['PHPUNIT_SELENIUM_TEST_ID']) && extension_loaded('xdebug')) {
905     include_once __DIR__ . "/../../vendor/phpunit/phpunit-selenium/PHPUnit/Extensions/SeleniumCommon/append.php";
906 }