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