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