3 * NB: do not let your IDE fool you. The correct encoding for this file is NOT UTF8.
5 include_once __DIR__ . '/../lib/xmlrpc.inc';
6 include_once __DIR__ . '/../lib/xmlrpcs.inc';
8 class ParsingBugsTests extends PHPUnit_Framework_TestCase
10 public function testMinusOneString()
12 $v = new xmlrpcval('-1');
13 $u = new xmlrpcval('-1', 'string');
14 $this->assertEquals($u->scalarval(), $v->scalarval());
17 public function testMinusOneInt()
19 $v = new xmlrpcval(-1);
20 $u = new xmlrpcval(-1, 'string');
21 $this->assertEquals($u->scalarval(), $v->scalarval());
24 public function testUnicodeInMemberName()
26 $str = "G" . chr(252) . "nter, El" . chr(232) . "ne";
27 $v = array($str => new xmlrpcval(1));
28 $r = new xmlrpcresp(new xmlrpcval($v, 'struct'));
30 $m = new xmlrpcmsg('dummy');
31 $r = $m->parseResponse($r);
33 $this->assertEquals($v->structmemexists($str), true);
36 public function testUnicodeInErrorString()
38 $response = utf8_encode(
39 '<?xml version="1.0"?>
41 <!-- found by G. giunta, covers what happens when lib receives
42 UTF8 chars in response text and comments -->
43 <!-- ' . chr(224) . chr(252) . chr(232) . 'àüè -->
49 <name>faultCode</name>
50 <value><int>888</int></value>
53 <name>faultString</name>
54 <value><string>' . chr(224) . chr(252) . chr(232) . 'àüè</string></value>
60 $m = new xmlrpcmsg('dummy');
61 $r = $m->parseResponse($response);
62 $v = $r->faultString();
63 $this->assertEquals(chr(224) . chr(252) . chr(232) . chr(224) . chr(252) . chr(232), $v);
66 public function testValidNumbers()
68 $m = new xmlrpcmsg('dummy');
70 '<?xml version="1.0"?>
78 <value><int>01</int></value>
82 <value><double>01.10</double></value>
86 <value><int>+1</int></value>
90 <value><double>+1.10</double></value>
94 <value><double>-1.10e2</double></value>
101 $r = $m->parseResponse($fp);
103 $s = $v->structmem('integer1');
104 $t = $v->structmem('float1');
105 $u = $v->structmem('integer2');
106 $w = $v->structmem('float2');
107 $x = $v->structmem('float3');
108 $this->assertEquals(1, $s->scalarval());
109 $this->assertEquals(1.1, $t->scalarval());
110 $this->assertEquals(1, $u->scalarval());
111 $this->assertEquals(1.1, $w->scalarval());
112 $this->assertEquals(-110.0, $x->scalarval());
115 public function testAddScalarToStruct()
117 $v = new xmlrpcval(array('a' => 'b'), 'struct');
118 // use @ operator in case error_log gets on screen
119 $r = @$v->addscalar('c');
120 $this->assertEquals(0, $r);
123 public function testAddStructToStruct()
125 $v = new xmlrpcval(array('a' => new xmlrpcval('b')), 'struct');
126 $r = $v->addstruct(array('b' => new xmlrpcval('c')));
127 $this->assertEquals(2, $v->structsize());
128 $this->assertEquals(1, $r);
129 $r = $v->addstruct(array('b' => new xmlrpcval('b')));
130 $this->assertEquals(2, $v->structsize());
133 public function testAddArrayToArray()
135 $v = new xmlrpcval(array(new xmlrpcval('a'), new xmlrpcval('b')), 'array');
136 $r = $v->addarray(array(new xmlrpcval('b'), new xmlrpcval('c')));
137 $this->assertEquals(4, $v->arraysize());
138 $this->assertEquals(1, $r);
141 public function testEncodeArray()
144 $v = php_xmlrpc_encode($r);
145 $this->assertEquals('array', $v->kindof());
148 public function testEncodeRecursive()
150 $v = php_xmlrpc_encode(php_xmlrpc_encode('a simple string'));
151 $this->assertEquals('scalar', $v->kindof());
154 public function testBrokenRequests()
156 $s = new xmlrpc_server();
157 // omitting the 'params' tag: not tolerated by the lib anymore
158 $f = '<?xml version="1.0"?>
160 <methodName>system.methodHelp</methodName>
162 <value><string>system.methodHelp</string></value>
165 $r = $s->parserequest($f);
166 $this->assertEquals(15, $r->faultCode());
167 // omitting a 'param' tag
168 $f = '<?xml version="1.0"?>
170 <methodName>system.methodHelp</methodName>
172 <value><string>system.methodHelp</string></value>
175 $r = $s->parserequest($f);
176 $this->assertEquals(15, $r->faultCode());
177 // omitting a 'value' tag
178 $f = '<?xml version="1.0"?>
180 <methodName>system.methodHelp</methodName>
182 <param><string>system.methodHelp</string></param>
185 $r = $s->parserequest($f);
186 $this->assertEquals(15, $r->faultCode());
189 public function testBrokenResponses()
191 $m = new xmlrpcmsg('dummy');
193 // omitting the 'params' tag: no more tolerated by the lib...
194 $f = '<?xml version="1.0"?>
197 <value><string>system.methodHelp</string></value>
200 $r = $m->parseResponse($f);
201 $this->assertEquals(2, $r->faultCode());
202 // omitting the 'param' tag: no more tolerated by the lib...
203 $f = '<?xml version="1.0"?>
206 <value><string>system.methodHelp</string></value>
209 $r = $m->parseResponse($f);
210 $this->assertEquals(2, $r->faultCode());
211 // omitting a 'value' tag: KO
212 $f = '<?xml version="1.0"?>
215 <param><string>system.methodHelp</string></param>
218 $r = $m->parseResponse($f);
219 $this->assertEquals(2, $r->faultCode());
222 public function testBuggyHttp()
224 $s = new xmlrpcmsg('dummy');
225 $f = 'HTTP/1.1 100 Welcome to the jungle
228 X-Content-Marx-Brothers: Harpo
230 Content-Length: who knows?
234 <?xml version="1.0"?>
235 <!-- First of all, let\'s check out if the lib properly handles a commented </methodResponse> tag... -->
236 <methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
237 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
240 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
241 <script type="text\javascript">document.write(\'Hello, my name is added nag, I\\\'m happy to serve your content for free\');</script>
243 $r = $s->parseResponse($f);
245 $s = $v->structmem('content');
246 $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s->scalarval());
249 public function testStringBug()
251 $s = new xmlrpcmsg('dummy');
252 $f = '<?xml version="1.0"?>
254 <!-- found by 2z69xks7bpy001@sneakemail.com, amongst others
255 covers what happens when there\'s character data after </string>
256 and before </value> -->
269 <name>sessionID</name>
271 <string>S300510007I</string>
279 $r = $s->parseResponse($f);
281 $s = $v->structmem('sessionID');
282 $this->assertEquals('S300510007I', $s->scalarval());
285 public function testWhiteSpace()
287 $s = new xmlrpcmsg('dummy');
288 $f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
289 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
292 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
294 $r = $s->parseResponse($f);
296 $s = $v->structmem('content');
297 $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s->scalarval());
300 public function testDoubleDataInArrayTag()
302 $s = new xmlrpcmsg('dummy');
303 $f = '<?xml version="1.0"?><methodResponse><params><param><value><array>
306 </array></value></param></params></methodResponse>
308 $r = $s->parseResponse($f);
309 $v = $r->faultCode();
310 $this->assertEquals(2, $v);
311 $f = '<?xml version="1.0"?><methodResponse><params><param><value><array>
312 <data><value>Hello world</value></data>
314 </array></value></param></params></methodResponse>
316 $r = $s->parseResponse($f);
317 $v = $r->faultCode();
318 $this->assertEquals(2, $v);
321 public function testDoubleStuffInValueTag()
323 $s = new xmlrpcmsg('dummy');
324 $f = '<?xml version="1.0"?><methodResponse><params><param><value>
325 <string>hello world</string>
326 <array><data></data></array>
327 </value></param></params></methodResponse>
329 $r = $s->parseResponse($f);
330 $v = $r->faultCode();
331 $this->assertEquals(2, $v);
332 $f = '<?xml version="1.0"?><methodResponse><params><param><value>
333 <string>hello</string>
334 <string>world</string>
335 </value></param></params></methodResponse>
337 $r = $s->parseResponse($f);
338 $v = $r->faultCode();
339 $this->assertEquals(2, $v);
340 $f = '<?xml version="1.0"?><methodResponse><params><param><value>
341 <string>hello</string>
342 <struct><member><name>hello><value>world</value></member></struct>
343 </value></param></params></methodResponse>
345 $r = $s->parseResponse($f);
346 $v = $r->faultCode();
347 $this->assertEquals(2, $v);
350 public function testAutodecodeResponse()
352 $s = new xmlrpcmsg('dummy');
353 $f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
354 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
357 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
359 $r = $s->parseResponse($f, true, 'phpvals');
362 $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s);
365 public function testNoDecodeResponse()
367 $s = new xmlrpcmsg('dummy');
368 $f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
369 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
372 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>';
373 $r = $s->parseResponse($f, true, 'xml');
375 $this->assertEquals($f, $v);
378 public function testAutoCoDec()
380 $data1 = array(1, 1.0, 'hello world', true, '20051021T23:43:00', -1, 11.0, '~!@#$%^&*()_+|', false, '20051021T23:43:00');
381 $data2 = array('zero' => $data1, 'one' => $data1, 'two' => $data1, 'three' => $data1, 'four' => $data1, 'five' => $data1, 'six' => $data1, 'seven' => $data1, 'eight' => $data1, 'nine' => $data1);
382 $data = array($data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2);
383 //$keys = array('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
384 $v1 = php_xmlrpc_encode($data, array('auto_dates'));
385 $v2 = php_xmlrpc_decode_xml($v1->serialize());
386 $this->assertEquals($v1, $v2);
387 $r1 = new PhpXmlRpc\Response($v1);
388 $r2 = php_xmlrpc_decode_xml($r1->serialize());
389 $r2->serialize(); // needed to set internal member payload
390 $this->assertEquals($r1, $r2);
391 $m1 = new PhpXmlRpc\Request('hello dolly', array($v1));
392 $m2 = php_xmlrpc_decode_xml($m1->serialize());
393 $m2->serialize(); // needed to set internal member payload
394 $this->assertEquals($m1, $m2);
397 public function testUTF8Request()
399 $sendstring = 'κόσμε'; // Greek word 'kosme'. NB: NOT a valid ISO8859 string!
400 $GLOBALS['xmlrpc_internalencoding'] = 'UTF-8';
401 \PhpXmlRpc\PhpXmlRpc::importGlobals();
402 $f = new xmlrpcval($sendstring, 'string');
403 $v = $f->serialize();
404 $this->assertEquals("<value><string>κόσμε</string></value>\n", $v);
405 $GLOBALS['xmlrpc_internalencoding'] = 'ISO-8859-1';
406 \PhpXmlRpc\PhpXmlRpc::importGlobals();
409 public function testUTF8Response()
411 $s = new xmlrpcmsg('dummy');
412 $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>
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>
415 $r = $s->parseResponse($f, false, 'phpvals');
418 $this->assertEquals("������", $v);
419 $f = '<?xml version="1.0" encoding="utf-8"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
420 <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>
422 $r = $s->parseResponse($f, false, 'phpvals');
425 $this->assertEquals("������", $v);
428 public function testUTF8IntString()
430 $v = new xmlrpcval(100, 'int');
431 $s = $v->serialize('UTF-8');
432 $this->assertequals("<value><int>100</int></value>\n", $s);
435 public function testStringInt()
437 $v = new xmlrpcval('hello world', 'int');
438 $s = $v->serialize();
439 $this->assertequals("<value><int>0</int></value>\n", $s);
442 public function testStructMemExists()
444 $v = php_xmlrpc_encode(array('hello' => 'world'));
445 $b = $v->structmemexists('hello');
446 $this->assertequals(true, $b);
447 $b = $v->structmemexists('world');
448 $this->assertequals(false, $b);
451 public function testNilvalue()
453 // default case: we do not accept nil values received
454 $v = new xmlrpcval('hello', 'null');
455 $r = new xmlrpcresp($v);
456 $s = $r->serialize();
457 $m = new xmlrpcmsg('dummy');
458 $r = $m->parseresponse($s);
459 $this->assertequals(2, $r->faultCode());
460 // enable reception of nil values
461 $GLOBALS['xmlrpc_null_extension'] = true;
462 \PhpXmlRpc\PhpXmlRpc::importGlobals();
463 $r = $m->parseresponse($s);
465 $this->assertequals('null', $v->scalartyp());
466 // test with the apache version: EX:NIL
467 $GLOBALS['xmlrpc_null_apache_encoding'] = true;
468 \PhpXmlRpc\PhpXmlRpc::importGlobals();
470 $v = new xmlrpcval('hello', 'null');
471 $s = $v->serialize();
472 $this->assertequals(1, preg_match('#<value><ex:nil/></value>#', $s));
474 $r = new xmlrpcresp($v);
475 $s = $r->serialize();
476 $r = $m->parseresponse($s);
478 $this->assertequals('null', $v->scalartyp());
479 $GLOBALS['xmlrpc_null_extension'] = false;
480 \PhpXmlRpc\PhpXmlRpc::importGlobals();
481 $r = $m->parseresponse($s);
482 $this->assertequals(2, $r->faultCode());
485 public function TestLocale()
487 $locale = setlocale(LC_NUMERIC, 0);
488 /// @todo on php 5.3/win setting locale to german does not seem to set decimal separator to comma...
489 if (setlocale(LC_NUMERIC, 'deu', 'de_DE@euro', 'de_DE', 'de', 'ge') !== false) {
490 $v = new xmlrpcval(1.1, 'double');
491 if (strpos($v->scalarval(), ',') == 1) {
492 $r = $v->serialize();
493 $this->assertequals(false, strpos($r, ','));
494 setlocale(LC_NUMERIC, $locale);
496 setlocale(LC_NUMERIC, $locale);
497 $this->markTestSkipped('did not find a locale which sets decimal separator to comma');
500 $this->markTestSkipped('did not find a locale which sets decimal separator to comma');