Fix (hopefully) the Travis tests using https for localhost
[plcapi.git] / tests / 1ParsingBugsTest.php
1 <?php
2 /**
3  * NB: do not let your IDE fool you. The correct encoding for this file is NOT UTF8.
4  */
5 include_once __DIR__ . '/../lib/xmlrpc.inc';
6 include_once __DIR__ . '/../lib/xmlrpcs.inc';
7
8 class ParsingBugsTests extends PHPUnit_Framework_TestCase
9 {
10     public function testMinusOneString()
11     {
12         $v = new xmlrpcval('-1');
13         $u = new xmlrpcval('-1', 'string');
14         $this->assertEquals($u->scalarval(), $v->scalarval());
15     }
16
17     public function testUnicodeInMemberName()
18     {
19         $str = "G" . chr(252) . "nter, El" . chr(232) . "ne";
20         $v = array($str => new xmlrpcval(1));
21         $r = new xmlrpcresp(new xmlrpcval($v, 'struct'));
22         $r = $r->serialize();
23         $m = new xmlrpcmsg('dummy');
24         $r = $m->parseResponse($r);
25         $v = $r->value();
26         $this->assertEquals($v->structmemexists($str), true);
27     }
28
29     public function testUnicodeInErrorString()
30     {
31         $response = utf8_encode(
32             '<?xml version="1.0"?>
33 <!-- $Id -->
34 <!-- found by G. giunta, covers what happens when lib receives
35   UTF8 chars in response text and comments -->
36 <!-- ' . chr(224) . chr(252) . chr(232) . '&#224;&#252;&#232; -->
37 <methodResponse>
38 <fault>
39 <value>
40 <struct>
41 <member>
42 <name>faultCode</name>
43 <value><int>888</int></value>
44 </member>
45 <member>
46 <name>faultString</name>
47 <value><string>' . chr(224) . chr(252) . chr(232) . '&#224;&#252;&#232;</string></value>
48 </member>
49 </struct>
50 </value>
51 </fault>
52 </methodResponse>');
53         $m = new xmlrpcmsg('dummy');
54         $r = $m->parseResponse($response);
55         $v = $r->faultString();
56         $this->assertEquals(chr(224) . chr(252) . chr(232) . chr(224) . chr(252) . chr(232), $v);
57     }
58
59     public function testValidNumbers()
60     {
61         $m = new xmlrpcmsg('dummy');
62         $fp =
63             '<?xml version="1.0"?>
64 <methodResponse>
65 <params>
66 <param>
67 <value>
68 <struct>
69 <member>
70 <name>integer1</name>
71 <value><int>01</int></value>
72 </member>
73 <member>
74 <name>float1</name>
75 <value><double>01.10</double></value>
76 </member>
77 <member>
78 <name>integer2</name>
79 <value><int>+1</int></value>
80 </member>
81 <member>
82 <name>float2</name>
83 <value><double>+1.10</double></value>
84 </member>
85 <member>
86 <name>float3</name>
87 <value><double>-1.10e2</double></value>
88 </member>
89 </struct>
90 </value>
91 </param>
92 </params>
93 </methodResponse>';
94         $r = $m->parseResponse($fp);
95         $v = $r->value();
96         $s = $v->structmem('integer1');
97         $t = $v->structmem('float1');
98         $u = $v->structmem('integer2');
99         $w = $v->structmem('float2');
100         $x = $v->structmem('float3');
101         $this->assertEquals(1, $s->scalarval());
102         $this->assertEquals(1.1, $t->scalarval());
103         $this->assertEquals(1, $u->scalarval());
104         $this->assertEquals(1.1, $w->scalarval());
105         $this->assertEquals(-110.0, $x->scalarval());
106     }
107
108     public function testAddScalarToStruct()
109     {
110         $v = new xmlrpcval(array('a' => 'b'), 'struct');
111         // use @ operator in case error_log gets on screen
112         $r = @$v->addscalar('c');
113         $this->assertEquals(0, $r);
114     }
115
116     public function testAddStructToStruct()
117     {
118         $v = new xmlrpcval(array('a' => new xmlrpcval('b')), 'struct');
119         $r = $v->addstruct(array('b' => new xmlrpcval('c')));
120         $this->assertEquals(2, $v->structsize());
121         $this->assertEquals(1, $r);
122         $r = $v->addstruct(array('b' => new xmlrpcval('b')));
123         $this->assertEquals(2, $v->structsize());
124     }
125
126     public function testAddArrayToArray()
127     {
128         $v = new xmlrpcval(array(new xmlrpcval('a'), new xmlrpcval('b')), 'array');
129         $r = $v->addarray(array(new xmlrpcval('b'), new xmlrpcval('c')));
130         $this->assertEquals(4, $v->arraysize());
131         $this->assertEquals(1, $r);
132     }
133
134     public function testEncodeArray()
135     {
136         $r = range(1, 100);
137         $v = php_xmlrpc_encode($r);
138         $this->assertEquals('array', $v->kindof());
139     }
140
141     public function testEncodeRecursive()
142     {
143         $v = php_xmlrpc_encode(php_xmlrpc_encode('a simple string'));
144         $this->assertEquals('scalar', $v->kindof());
145     }
146
147     public function testBrokenRequests()
148     {
149         $s = new xmlrpc_server();
150         // omitting the 'params' tag: not tolerated by the lib anymore
151         $f = '<?xml version="1.0"?>
152 <methodCall>
153 <methodName>system.methodHelp</methodName>
154 <param>
155 <value><string>system.methodHelp</string></value>
156 </param>
157 </methodCall>';
158         $r = $s->parserequest($f);
159         $this->assertEquals(15, $r->faultCode());
160         // omitting a 'param' tag
161         $f = '<?xml version="1.0"?>
162 <methodCall>
163 <methodName>system.methodHelp</methodName>
164 <params>
165 <value><string>system.methodHelp</string></value>
166 </params>
167 </methodCall>';
168         $r = $s->parserequest($f);
169         $this->assertEquals(15, $r->faultCode());
170         // omitting a 'value' tag
171         $f = '<?xml version="1.0"?>
172 <methodCall>
173 <methodName>system.methodHelp</methodName>
174 <params>
175 <param><string>system.methodHelp</string></param>
176 </params>
177 </methodCall>';
178         $r = $s->parserequest($f);
179         $this->assertEquals(15, $r->faultCode());
180     }
181
182     public function testBrokenResponses()
183     {
184         $m = new xmlrpcmsg('dummy');
185         //$m->debug = 1;
186         // omitting the 'params' tag: no more tolerated by the lib...
187         $f = '<?xml version="1.0"?>
188 <methodResponse>
189 <param>
190 <value><string>system.methodHelp</string></value>
191 </param>
192 </methodResponse>';
193         $r = $m->parseResponse($f);
194         $this->assertEquals(2, $r->faultCode());
195         // omitting the 'param' tag: no more tolerated by the lib...
196         $f = '<?xml version="1.0"?>
197 <methodResponse>
198 <params>
199 <value><string>system.methodHelp</string></value>
200 </params>
201 </methodResponse>';
202         $r = $m->parseResponse($f);
203         $this->assertEquals(2, $r->faultCode());
204         // omitting a 'value' tag: KO
205         $f = '<?xml version="1.0"?>
206 <methodResponse>
207 <params>
208 <param><string>system.methodHelp</string></param>
209 </params>
210 </methodResponse>';
211         $r = $m->parseResponse($f);
212         $this->assertEquals(2, $r->faultCode());
213     }
214
215     public function testBuggyHttp()
216     {
217         $s = new xmlrpcmsg('dummy');
218         $f = 'HTTP/1.1 100 Welcome to the jungle
219
220 HTTP/1.0 200 OK
221 X-Content-Marx-Brothers: Harpo
222         Chico and Groucho
223 Content-Length: who knows?
224
225
226
227 <?xml version="1.0"?>
228 <!-- First of all, let\'s check out if the lib properly handles a commented </methodResponse> tag... -->
229 <methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
230 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
231
232
233 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
234 <script type="text\javascript">document.write(\'Hello, my name is added nag, I\\\'m happy to serve your content for free\');</script>
235  ';
236         $r = $s->parseResponse($f);
237         $v = $r->value();
238         $s = $v->structmem('content');
239         $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s->scalarval());
240     }
241
242     public function testStringBug()
243     {
244         $s = new xmlrpcmsg('dummy');
245         $f = '<?xml version="1.0"?>
246 <!-- $Id -->
247 <!-- found by 2z69xks7bpy001@sneakemail.com, amongst others
248  covers what happens when there\'s character data after </string>
249  and before </value> -->
250 <methodResponse>
251 <params>
252 <param>
253 <value>
254 <struct>
255 <member>
256 <name>success</name>
257 <value>
258 <boolean>1</boolean>
259 </value>
260 </member>
261 <member>
262 <name>sessionID</name>
263 <value>
264 <string>S300510007I</string>
265 </value>
266 </member>
267 </struct>
268 </value>
269 </param>
270 </params>
271 </methodResponse> ';
272         $r = $s->parseResponse($f);
273         $v = $r->value();
274         $s = $v->structmem('sessionID');
275         $this->assertEquals('S300510007I', $s->scalarval());
276     }
277
278     public function testWhiteSpace()
279     {
280         $s = new xmlrpcmsg('dummy');
281         $f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
282 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
283
284
285 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
286 ';
287         $r = $s->parseResponse($f);
288         $v = $r->value();
289         $s = $v->structmem('content');
290         $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s->scalarval());
291     }
292
293     public function testDoubleDataInArrayTag()
294     {
295         $s = new xmlrpcmsg('dummy');
296         $f = '<?xml version="1.0"?><methodResponse><params><param><value><array>
297 <data></data>
298 <data></data>
299 </array></value></param></params></methodResponse>
300 ';
301         $r = $s->parseResponse($f);
302         $v = $r->faultCode();
303         $this->assertEquals(2, $v);
304         $f = '<?xml version="1.0"?><methodResponse><params><param><value><array>
305 <data><value>Hello world</value></data>
306 <data></data>
307 </array></value></param></params></methodResponse>
308 ';
309         $r = $s->parseResponse($f);
310         $v = $r->faultCode();
311         $this->assertEquals(2, $v);
312     }
313
314     public function testDoubleStuffInValueTag()
315     {
316         $s = new xmlrpcmsg('dummy');
317         $f = '<?xml version="1.0"?><methodResponse><params><param><value>
318 <string>hello world</string>
319 <array><data></data></array>
320 </value></param></params></methodResponse>
321 ';
322         $r = $s->parseResponse($f);
323         $v = $r->faultCode();
324         $this->assertEquals(2, $v);
325         $f = '<?xml version="1.0"?><methodResponse><params><param><value>
326 <string>hello</string>
327 <string>world</string>
328 </value></param></params></methodResponse>
329 ';
330         $r = $s->parseResponse($f);
331         $v = $r->faultCode();
332         $this->assertEquals(2, $v);
333         $f = '<?xml version="1.0"?><methodResponse><params><param><value>
334 <string>hello</string>
335 <struct><member><name>hello><value>world</value></member></struct>
336 </value></param></params></methodResponse>
337 ';
338         $r = $s->parseResponse($f);
339         $v = $r->faultCode();
340         $this->assertEquals(2, $v);
341     }
342
343     public function testAutodecodeResponse()
344     {
345         $s = new xmlrpcmsg('dummy');
346         $f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
347 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
348
349
350 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
351 ';
352         $r = $s->parseResponse($f, true, 'phpvals');
353         $v = $r->value();
354         $s = $v['content'];
355         $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s);
356     }
357
358     public function testNoDecodeResponse()
359     {
360         $s = new xmlrpcmsg('dummy');
361         $f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
362 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
363
364
365 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>';
366         $r = $s->parseResponse($f, true, 'xml');
367         $v = $r->value();
368         $this->assertEquals($f, $v);
369     }
370
371     public function testAutoCoDec()
372     {
373         $data1 = array(1, 1.0, 'hello world', true, '20051021T23:43:00', -1, 11.0, '~!@#$%^&*()_+|', false, '20051021T23:43:00');
374         $data2 = array('zero' => $data1, 'one' => $data1, 'two' => $data1, 'three' => $data1, 'four' => $data1, 'five' => $data1, 'six' => $data1, 'seven' => $data1, 'eight' => $data1, 'nine' => $data1);
375         $data = array($data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2);
376         //$keys = array('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
377         $v1 = php_xmlrpc_encode($data, array('auto_dates'));
378         $v2 = php_xmlrpc_decode_xml($v1->serialize());
379         $this->assertEquals($v1, $v2);
380         $r1 = new PhpXmlRpc\Response($v1);
381         $r2 = php_xmlrpc_decode_xml($r1->serialize());
382         $r2->serialize(); // needed to set internal member payload
383         $this->assertEquals($r1, $r2);
384         $m1 = new PhpXmlRpc\Request('hello dolly', array($v1));
385         $m2 = php_xmlrpc_decode_xml($m1->serialize());
386         $m2->serialize(); // needed to set internal member payload
387         $this->assertEquals($m1, $m2);
388     }
389
390     public function testUTF8Request()
391     {
392         $sendstring = 'κόσμε'; // Greek word 'kosme'. NB: NOT a valid ISO8859 string!
393         $GLOBALS['xmlrpc_internalencoding'] = 'UTF-8';
394         \PhpXmlRpc\PhpXmlRpc::importGlobals();
395         $f = new xmlrpcval($sendstring, 'string');
396         $v = $f->serialize();
397         $this->assertEquals("<value><string>&#954;&#8057;&#963;&#956;&#949;</string></value>\n", $v);
398         $GLOBALS['xmlrpc_internalencoding'] = 'ISO-8859-1';
399         \PhpXmlRpc\PhpXmlRpc::importGlobals();
400     }
401
402     public function testUTF8Response()
403     {
404         $s = new xmlrpcmsg('dummy');
405         $f = "HTTP/1.1 200 OK\r\nContent-type: text/xml; charset=UTF-8\r\n\r\n" . '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
406 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>' . utf8_encode('àüèàüè') . '</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
407 ';
408         $r = $s->parseResponse($f, false, 'phpvals');
409         $v = $r->value();
410         $v = $v['content'];
411         $this->assertEquals("àüèàüè", $v);
412         $f = '<?xml version="1.0" encoding="utf-8"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
413 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>' . utf8_encode('àüèàüè') . '</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
414 ';
415         $r = $s->parseResponse($f, false, 'phpvals');
416         $v = $r->value();
417         $v = $v['content'];
418         $this->assertEquals("àüèàüè", $v);
419     }
420
421     public function testUTF8IntString()
422     {
423         $v = new xmlrpcval(100, 'int');
424         $s = $v->serialize('UTF-8');
425         $this->assertequals("<value><int>100</int></value>\n", $s);
426     }
427
428     public function testStringInt()
429     {
430         $v = new xmlrpcval('hello world', 'int');
431         $s = $v->serialize();
432         $this->assertequals("<value><int>0</int></value>\n", $s);
433     }
434
435     public function testStructMemExists()
436     {
437         $v = php_xmlrpc_encode(array('hello' => 'world'));
438         $b = $v->structmemexists('hello');
439         $this->assertequals(true, $b);
440         $b = $v->structmemexists('world');
441         $this->assertequals(false, $b);
442     }
443
444     public function testNilvalue()
445     {
446         // default case: we do not accept nil values received
447         $v = new xmlrpcval('hello', 'null');
448         $r = new xmlrpcresp($v);
449         $s = $r->serialize();
450         $m = new xmlrpcmsg('dummy');
451         $r = $m->parseresponse($s);
452         $this->assertequals(2, $r->faultCode());
453         // enable reception of nil values
454         $GLOBALS['xmlrpc_null_extension'] = true;
455         \PhpXmlRpc\PhpXmlRpc::importGlobals();
456         $r = $m->parseresponse($s);
457         $v = $r->value();
458         $this->assertequals('null', $v->scalartyp());
459         // test with the apache version: EX:NIL
460         $GLOBALS['xmlrpc_null_apache_encoding'] = true;
461         \PhpXmlRpc\PhpXmlRpc::importGlobals();
462         // serialization
463         $v = new xmlrpcval('hello', 'null');
464         $s = $v->serialize();
465         $this->assertequals(1, preg_match('#<value><ex:nil/></value>#', $s));
466         // deserialization
467         $r = new xmlrpcresp($v);
468         $s = $r->serialize();
469         $r = $m->parseresponse($s);
470         $v = $r->value();
471         $this->assertequals('null', $v->scalartyp());
472         $GLOBALS['xmlrpc_null_extension'] = false;
473         \PhpXmlRpc\PhpXmlRpc::importGlobals();
474         $r = $m->parseresponse($s);
475         $this->assertequals(2, $r->faultCode());
476     }
477
478     public function TestLocale()
479     {
480         $locale = setlocale(LC_NUMERIC, 0);
481         /// @todo on php 5.3/win setting locale to german does not seem to set decimal separator to comma...
482         if (setlocale(LC_NUMERIC, 'deu', 'de_DE@euro', 'de_DE', 'de', 'ge') !== false) {
483             $v = new xmlrpcval(1.1, 'double');
484             if (strpos($v->scalarval(), ',') == 1) {
485                 $r = $v->serialize();
486                 $this->assertequals(false, strpos($r, ','));
487                 setlocale(LC_NUMERIC, $locale);
488             } else {
489                 setlocale(LC_NUMERIC, $locale);
490                 $this->markTestSkipped('did not find a locale which sets decimal separator to comma');
491             }
492         } else {
493             $this->markTestSkipped('did not find a locale which sets decimal separator to comma');
494         }
495     }
496 }