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 testUnicodeInMemberName()
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'));
23 $m = new xmlrpcmsg('dummy');
24 $r = $m->parseResponse($r);
26 $this->assertEquals($v->structmemexists($str), true);
29 public function testUnicodeInErrorString()
31 $response = utf8_encode(
32 '<?xml version="1.0"?>
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) . 'àüè -->
42 <name>faultCode</name>
43 <value><int>888</int></value>
46 <name>faultString</name>
47 <value><string>' . chr(224) . chr(252) . chr(232) . 'àüè</string></value>
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);
59 public function testValidNumbers()
61 $m = new xmlrpcmsg('dummy');
63 '<?xml version="1.0"?>
71 <value><int>01</int></value>
75 <value><double>01.10</double></value>
79 <value><int>+1</int></value>
83 <value><double>+1.10</double></value>
87 <value><double>-1.10e2</double></value>
94 $r = $m->parseResponse($fp);
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());
108 public function testAddScalarToStruct()
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);
116 public function testAddStructToStruct()
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());
126 public function testAddArrayToArray()
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);
134 public function testEncodeArray()
137 $v = php_xmlrpc_encode($r);
138 $this->assertEquals('array', $v->kindof());
141 public function testEncodeRecursive()
143 $v = php_xmlrpc_encode(php_xmlrpc_encode('a simple string'));
144 $this->assertEquals('scalar', $v->kindof());
147 public function testBrokenRequests()
149 $s = new xmlrpc_server();
150 // omitting the 'params' tag: not tolerated by the lib anymore
151 $f = '<?xml version="1.0"?>
153 <methodName>system.methodHelp</methodName>
155 <value><string>system.methodHelp</string></value>
158 $r = $s->parserequest($f);
159 $this->assertEquals(15, $r->faultCode());
160 // omitting a 'param' tag
161 $f = '<?xml version="1.0"?>
163 <methodName>system.methodHelp</methodName>
165 <value><string>system.methodHelp</string></value>
168 $r = $s->parserequest($f);
169 $this->assertEquals(15, $r->faultCode());
170 // omitting a 'value' tag
171 $f = '<?xml version="1.0"?>
173 <methodName>system.methodHelp</methodName>
175 <param><string>system.methodHelp</string></param>
178 $r = $s->parserequest($f);
179 $this->assertEquals(15, $r->faultCode());
182 public function testBrokenResponses()
184 $m = new xmlrpcmsg('dummy');
186 // omitting the 'params' tag: no more tolerated by the lib...
187 $f = '<?xml version="1.0"?>
190 <value><string>system.methodHelp</string></value>
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"?>
199 <value><string>system.methodHelp</string></value>
202 $r = $m->parseResponse($f);
203 $this->assertEquals(2, $r->faultCode());
204 // omitting a 'value' tag: KO
205 $f = '<?xml version="1.0"?>
208 <param><string>system.methodHelp</string></param>
211 $r = $m->parseResponse($f);
212 $this->assertEquals(2, $r->faultCode());
215 public function testBuggyHttp()
217 $s = new xmlrpcmsg('dummy');
218 $f = 'HTTP/1.1 100 Welcome to the jungle
221 X-Content-Marx-Brothers: Harpo
223 Content-Length: who knows?
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
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>
236 $r = $s->parseResponse($f);
238 $s = $v->structmem('content');
239 $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s->scalarval());
242 public function testStringBug()
244 $s = new xmlrpcmsg('dummy');
245 $f = '<?xml version="1.0"?>
247 <!-- found by 2z69xks7bpy001@sneakemail.com, amongst others
248 covers what happens when there\'s character data after </string>
249 and before </value> -->
262 <name>sessionID</name>
264 <string>S300510007I</string>
272 $r = $s->parseResponse($f);
274 $s = $v->structmem('sessionID');
275 $this->assertEquals('S300510007I', $s->scalarval());
278 public function testWhiteSpace()
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
285 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
287 $r = $s->parseResponse($f);
289 $s = $v->structmem('content');
290 $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s->scalarval());
293 public function testDoubleDataInArrayTag()
295 $s = new xmlrpcmsg('dummy');
296 $f = '<?xml version="1.0"?><methodResponse><params><param><value><array>
299 </array></value></param></params></methodResponse>
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>
307 </array></value></param></params></methodResponse>
309 $r = $s->parseResponse($f);
310 $v = $r->faultCode();
311 $this->assertEquals(2, $v);
314 public function testDoubleStuffInValueTag()
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>
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>
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>
338 $r = $s->parseResponse($f);
339 $v = $r->faultCode();
340 $this->assertEquals(2, $v);
343 public function testAutodecodeResponse()
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
350 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
352 $r = $s->parseResponse($f, true, 'phpvals');
355 $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s);
358 public function testNoDecodeResponse()
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
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');
368 $this->assertEquals($f, $v);
371 public function testAutoCoDec()
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);
390 public function testUTF8Request()
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>κόσμε</string></value>\n", $v);
398 $GLOBALS['xmlrpc_internalencoding'] = 'ISO-8859-1';
399 \PhpXmlRpc\PhpXmlRpc::importGlobals();
402 public function testUTF8Response()
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>
408 $r = $s->parseResponse($f, false, 'phpvals');
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>
415 $r = $s->parseResponse($f, false, 'phpvals');
418 $this->assertEquals("àüèàüè", $v);
421 public function testUTF8IntString()
423 $v = new xmlrpcval(100, 'int');
424 $s = $v->serialize('UTF-8');
425 $this->assertequals("<value><int>100</int></value>\n", $s);
428 public function testStringInt()
430 $v = new xmlrpcval('hello world', 'int');
431 $s = $v->serialize();
432 $this->assertequals("<value><int>0</int></value>\n", $s);
435 public function testStructMemExists()
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);
444 public function testNilvalue()
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);
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();
463 $v = new xmlrpcval('hello', 'null');
464 $s = $v->serialize();
465 $this->assertequals(1, preg_match('#<value><ex:nil/></value>#', $s));
467 $r = new xmlrpcresp($v);
468 $s = $r->serialize();
469 $r = $m->parseresponse($s);
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());
478 public function TestLocale()
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);
489 setlocale(LC_NUMERIC, $locale);
490 $this->markTestSkipped('did not find a locale which sets decimal separator to comma');
493 $this->markTestSkipped('did not find a locale which sets decimal separator to comma');