3 include_once __DIR__ . '/../lib/xmlrpc.inc';
4 include_once __DIR__ . '/../lib/xmlrpcs.inc';
6 include_once __DIR__ . '/parse_args.php';
8 include_once __DIR__ . '/PolyfillTestCase.php';
10 use PHPUnit\Runner\BaseTestRunner;
13 * Tests involving the Request and Response classes.
14 * @todo some tests are here only because we use a Response to trigger parsing of xml for a single Value, but they
15 * logically belong elsewhere...
17 class MessageTests extends PhpXmlRpc_PolyfillTestCase
19 public $args = array();
21 protected function set_up()
23 $this->args = argParser::getArgs();
24 if ($this->args['DEBUG'] == 1)
28 protected function tear_down()
30 if ($this->args['DEBUG'] != 1)
32 $out = ob_get_clean();
33 $status = $this->getStatus();
34 if ($status == BaseTestRunner::STATUS_ERROR
35 || $status == BaseTestRunner::STATUS_FAILURE) {
40 protected function newMsg($methodName, $params = array())
42 $msg = new xmlrpcmsg($methodName, $params);
43 $msg->setDebug($this->args['DEBUG']);
48 public function testValidNumbers()
50 $m = $this->newMsg('dummy');
52 '<?xml version="1.0"?>
60 <value><int>01</int></value>
64 <value><int>+1</int></value>
68 <value><i4>1</i4></value>
72 <value><double>01.10</double></value>
76 <value><double>+1.10</double></value>
80 <value><double>-1.10e2</double></value>
87 $r = $m->parseResponse($fp);
89 $s = $v->structmem('integer1');
90 $t = $v->structmem('integer2');
91 $u = $v->structmem('integer3');
92 $x = $v->structmem('float1');
93 $y = $v->structmem('float2');
94 $z = $v->structmem('float3');
95 $this->assertEquals(1, $s->scalarval());
96 $this->assertEquals(1, $t->scalarval());
97 $this->assertEquals(1, $u->scalarval());
99 $this->assertEquals(1.1, $x->scalarval());
100 $this->assertEquals(1.1, $y->scalarval());
101 $this->assertEquals(-110.0, $z->scalarval());
104 public function testI8()
106 if (PHP_INT_SIZE == 4 ) {
107 $this->markTestSkipped('Can not test i8 as php is compiled in 32 bit mode');
111 $m = $this->newMsg('dummy');
113 '<?xml version="1.0"?>
120 <name>integer1</name>
121 <value><i8>1</i8></value>
128 $r = $m->parseResponse($fp);
130 $s = $v->structmem('integer1');
131 $this->assertEquals(1, $s->scalarval());
134 public function testUnicodeInMemberName()
136 $str = "G" . chr(252) . "nter, El" . chr(232) . "ne";
137 $v = array($str => new xmlrpcval(1));
138 $r = new xmlrpcresp(new xmlrpcval($v, 'struct'));
139 $r = $r->serialize();
140 $m = $this->newMsg('dummy');
141 $r = $m->parseResponse($r);
143 $this->assertEquals(true, $v->structmemexists($str));
146 public function testUnicodeInErrorString()
148 $response = utf8_encode(
149 '<?xml version="1.0"?>
151 <!-- found by G. Giunta, covers what happens when lib receives UTF8 chars in response text and comments -->
152 <!-- ' . chr(224) . chr(252) . chr(232) . 'àüè -->
158 <name>faultCode</name>
159 <value><int>888</int></value>
162 <name>faultString</name>
163 <value><string>' . chr(224) . chr(252) . chr(232) . 'àüè</string></value>
169 $m = $this->newMsg('dummy');
170 $r = $m->parseResponse($response);
171 $v = $r->faultString();
172 $this->assertEquals(chr(224) . chr(252) . chr(232) . chr(224) . chr(252) . chr(232), $v);
175 public function testBrokenRequests()
177 $s = new xmlrpc_server();
178 // omitting the 'params' tag: not tolerated by the lib anymore
179 $f = '<?xml version="1.0"?>
181 <methodName>system.methodHelp</methodName>
183 <value><string>system.methodHelp</string></value>
186 $r = $s->parserequest($f);
187 $this->assertEquals(15, $r->faultCode());
188 // omitting a 'param' tag
189 $f = '<?xml version="1.0"?>
191 <methodName>system.methodHelp</methodName>
193 <value><string>system.methodHelp</string></value>
196 $r = $s->parserequest($f);
197 $this->assertEquals(15, $r->faultCode());
198 // omitting a 'value' tag
199 $f = '<?xml version="1.0"?>
201 <methodName>system.methodHelp</methodName>
203 <param><string>system.methodHelp</string></param>
206 $r = $s->parserequest($f);
207 $this->assertEquals(15, $r->faultCode());
210 public function testBrokenResponses()
212 $m = $this->newMsg('dummy');
213 // omitting the 'params' tag: no more tolerated by the lib...
214 $f = '<?xml version="1.0"?>
217 <value><string>system.methodHelp</string></value>
220 $r = $m->parseResponse($f);
221 $this->assertEquals(2, $r->faultCode());
222 // omitting the 'param' tag: no more tolerated by the lib...
223 $f = '<?xml version="1.0"?>
226 <value><string>system.methodHelp</string></value>
229 $r = $m->parseResponse($f);
230 $this->assertEquals(2, $r->faultCode());
231 // omitting a 'value' tag: KO
232 $f = '<?xml version="1.0"?>
235 <param><string>system.methodHelp</string></param>
238 $r = $m->parseResponse($f);
239 $this->assertEquals(2, $r->faultCode());
242 public function testBuggyHttp()
244 $s = $this->newMsg('dummy');
245 $f = 'HTTP/1.1 100 Welcome to the jungle
248 X-Content-Marx-Brothers: Harpo
250 Content-Length: who knows?
254 <?xml version="1.0"?>
255 <!-- First of all, let\'s check out if the lib properly handles a commented </methodResponse> tag... -->
256 <methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
257 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
260 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
261 <script type="text\javascript">document.write(\'Hello, my name is added nag, I\\\'m happy to serve your content for free\');</script>
263 $r = $s->parseResponse($f);
265 $s = $v->structmem('content');
266 $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s->scalarval());
269 public function testStringBug()
271 $s = $this->newMsg('dummy');
272 $f = '<?xml version="1.0"?>
274 <!-- found by 2z69xks7bpy001@sneakemail.com, amongst others
275 covers what happens when there\'s character data after </string>
276 and before </value> -->
289 <name>sessionID</name>
291 <string>S300510007I</string>
299 $r = $s->parseResponse($f);
301 $s = $v->structmem('sessionID');
302 $this->assertEquals('S300510007I', $s->scalarval());
305 public function testWhiteSpace()
307 $s = $this->newMsg('dummy');
308 $f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
309 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
312 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
314 $r = $s->parseResponse($f);
316 $s = $v->structmem('content');
317 $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s->scalarval());
320 public function testDoubleDataInArrayTag()
322 $s = $this->newMsg('dummy');
323 $f = '<?xml version="1.0"?><methodResponse><params><param><value><array>
326 </array></value></param></params></methodResponse>
328 $r = $s->parseResponse($f);
329 $v = $r->faultCode();
330 $this->assertEquals(2, $v);
331 $f = '<?xml version="1.0"?><methodResponse><params><param><value><array>
332 <data><value>Hello world</value></data>
334 </array></value></param></params></methodResponse>
336 $r = $s->parseResponse($f);
337 $v = $r->faultCode();
338 $this->assertEquals(2, $v);
341 public function testDoubleStuffInValueTag()
343 $s = $this->newMsg('dummy');
344 $f = '<?xml version="1.0"?><methodResponse><params><param><value>
345 <string>hello world</string>
346 <array><data></data></array>
347 </value></param></params></methodResponse>
349 $r = $s->parseResponse($f);
350 $v = $r->faultCode();
351 $this->assertEquals(2, $v);
352 $f = '<?xml version="1.0"?><methodResponse><params><param><value>
353 <string>hello</string>
354 <string>world</string>
355 </value></param></params></methodResponse>
357 $r = $s->parseResponse($f);
358 $v = $r->faultCode();
359 $this->assertEquals(2, $v);
360 $f = '<?xml version="1.0"?><methodResponse><params><param><value>
361 <string>hello</string>
362 <struct><member><name>hello><value>world</value></member></struct>
363 </value></param></params></methodResponse>
365 $r = $s->parseResponse($f);
366 $v = $r->faultCode();
367 $this->assertEquals(2, $v);
370 public function testAutodecodeResponse()
372 $s = $this->newMsg('dummy');
373 $f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
374 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 3 newlines follow
377 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
379 $r = $s->parseResponse($f, true, 'phpvals');
382 $this->assertEquals("hello world. 3 newlines follow\n\n\nand there they were.", $s);
385 public function testNoDecodeResponse()
387 $s = $this->newMsg('dummy');
388 $f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
389 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 3 newlines follow
392 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>';
393 $r = $s->parseResponse($f, true, 'xml');
395 $this->assertEquals($f, $v);
398 public function testUTF8Request()
400 $sendstring = 'κόσμε'; // Greek word 'kosme'. NB: NOT a valid ISO8859 string!
401 $GLOBALS['xmlrpc_internalencoding'] = 'UTF-8';
402 \PhpXmlRpc\PhpXmlRpc::importGlobals();
403 $f = new xmlrpcval($sendstring, 'string');
404 $v = $f->serialize();
405 $this->assertEquals("<value><string>κόσμε</string></value>\n", $v);
406 $GLOBALS['xmlrpc_internalencoding'] = 'ISO-8859-1';
407 \PhpXmlRpc\PhpXmlRpc::importGlobals();
410 public function testUTF8Response()
412 $string = chr(224) . chr(252) . chr(232);
414 $s = $this->newMsg('dummy');
415 $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>
416 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>' . utf8_encode($string) . '</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
418 $r = $s->parseResponse($f, false, 'phpvals');
421 $this->assertEquals($string, $v);
423 $f = '<?xml version="1.0" encoding="UTF-8"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
424 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>' . utf8_encode($string) . '</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
426 $r = $s->parseResponse($f, false, 'phpvals');
429 $this->assertEquals($string, $v);
431 /// @todo move to EncoderTest
432 $r = php_xmlrpc_decode_xml($f);
434 $v = $v->structmem('content')->scalarval();
435 $this->assertEquals($string, $v);
438 public function testLatin1Response()
440 $string = chr(224) . chr(252) . chr(232);
442 $s = $this->newMsg('dummy');
443 $f = "HTTP/1.1 200 OK\r\nContent-type: text/xml; charset=ISO-8859-1\r\n\r\n" . '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
444 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>' . $string . '</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
446 $r = $s->parseResponse($f, false, 'phpvals');
449 $this->assertEquals($string, $v);
451 $f = '<?xml version="1.0" encoding="ISO-8859-1"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
452 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>' . $string . '</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
454 $r = $s->parseResponse($f, false, 'phpvals');
457 $this->assertEquals($string, $v);
459 /// @todo move to EncoderTest
460 $r = php_xmlrpc_decode_xml($f);
462 $v = $v->structmem('content')->scalarval();
463 $this->assertEquals($string, $v);
466 /// @todo can we change this test to purely using the Value class ?
467 public function testNilvalue()
469 // default case: we do not accept nil values received
470 $v = new xmlrpcval('hello', 'null');
471 $r = new xmlrpcresp($v);
472 $s = $r->serialize();
473 $m = $this->newMsg('dummy');
474 $r = $m->parseresponse($s);
475 $this->assertequals(2, $r->faultCode());
476 // enable reception of nil values
477 $GLOBALS['xmlrpc_null_extension'] = true;
478 \PhpXmlRpc\PhpXmlRpc::importGlobals();
479 $r = $m->parseresponse($s);
481 $this->assertequals('null', $v->scalartyp());
482 // test with the apache version: EX:NIL
483 $GLOBALS['xmlrpc_null_apache_encoding'] = true;
484 \PhpXmlRpc\PhpXmlRpc::importGlobals();
486 $v = new xmlrpcval('hello', 'null');
487 $s = $v->serialize();
488 $this->assertequals(1, preg_match('#<value><ex:nil/></value>#', $s));
490 $r = new xmlrpcresp($v);
491 $s = $r->serialize();
492 $r = $m->parseresponse($s);
494 $this->assertequals('null', $v->scalartyp());
495 $GLOBALS['xmlrpc_null_extension'] = false;
496 \PhpXmlRpc\PhpXmlRpc::importGlobals();
497 $r = $m->parseresponse($s);
498 $this->assertequals(2, $r->faultCode());