From 6e1746c37addd0ec774812f3391fcb327e3d260c Mon Sep 17 00:00:00 2001 From: gggeek Date: Mon, 23 Jan 2023 12:42:33 +0000 Subject: [PATCH] improve parsing of number in received xml --- src/Helper/XMLParser.php | 45 ++- src/PhpXmlRpc.php | 18 + tests/{0CharsetTest.php => 01CharsetTest.php} | 3 +- tests/{1ValueTest.php => 02ValueTest.php} | 33 ++ tests/{2MessageTest.php => 03ParsingTest.php} | 309 ++++++++++++++---- tests/{3EncoderTest.php => 06EncoderTest.php} | 0 tests/{4ClientTest.php => 07ClientTest.php} | 0 tests/{5ServerTest.php => 08ServerTest.php} | 0 tests/{6HTTPTest.php => 09HTTPTest.php} | 2 +- ...7DemofilesTest.php => 10DemofilesTest.php} | 0 .../{8DebuggerTest.php => 11DebuggerTest.php} | 0 ...xtraFilesTest.php => 12ExtraFilesTest.php} | 0 12 files changed, 331 insertions(+), 79 deletions(-) rename tests/{0CharsetTest.php => 01CharsetTest.php} (97%) rename tests/{1ValueTest.php => 02ValueTest.php} (81%) rename tests/{2MessageTest.php => 03ParsingTest.php} (64%) rename tests/{3EncoderTest.php => 06EncoderTest.php} (100%) rename tests/{4ClientTest.php => 07ClientTest.php} (100%) rename tests/{5ServerTest.php => 08ServerTest.php} (100%) rename tests/{6HTTPTest.php => 09HTTPTest.php} (99%) rename tests/{7DemofilesTest.php => 10DemofilesTest.php} (100%) rename tests/{8DebuggerTest.php => 11DebuggerTest.php} (100%) rename tests/{9ExtraFilesTest.php => 12ExtraFilesTest.php} (100%) diff --git a/src/Helper/XMLParser.php b/src/Helper/XMLParser.php index 82e5bc92..c406f7c7 100644 --- a/src/Helper/XMLParser.php +++ b/src/Helper/XMLParser.php @@ -425,6 +425,7 @@ class XMLParser case 'MEMBER': // set member name to null, in case we do not find in the xml later on + /// @todo we could reject structs missing a NAME in the MEMBER element $this->_xh['valuestack'][count($this->_xh['valuestack']) - 1]['name'] = ''; //$this->_xh['ac']=''; // Drop trough intentionally @@ -567,12 +568,15 @@ class XMLParser // We translate boolean 1 or 0 into PHP constants true or false. Strings 'true' and 'false' are accepted, // even though the spec never mentions them (see e.g. Blogger api docs) // NB: this simple checks helps a lot sanitizing input, i.e. no security problems around here - if ($this->_xh['ac'] == '1' || strcasecmp($this->_xh['ac'], 'true') == 0) { + // Note the non-strict type check: it will allow ' 1 ' + /// @todo feature-creep: use a flexible regexp, the same as we do with int, double and datetime. + /// Note that using a regexp would also make this test less sensitive to phpunit shenanigans + if ($this->_xh['ac'] == '1' || strcasecmp($this->_xh['ac'], 'true') === 0) { $this->_xh['value'] = true; } else { // log if receiving something strange, even though we set the value to false anyway /// @todo to be consistent with the other types, we should use a value outside the good-value domain, e.g. NULL - if ($this->_xh['ac'] != '0' && strcasecmp($this->_xh['ac'], 'false') != 0) { + if ($this->_xh['ac'] != '0' && strcasecmp($this->_xh['ac'], 'false') !== 0) { $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': invalid data received in BOOLEAN value: ' . $this->_xh['ac']); if ($this->current_parsing_options['xmlrpc_reject_invalid_values']) { @@ -595,8 +599,7 @@ class XMLParser // `Value::scalartyp()` function will do some normalization of the data $this->_xh['vt'] = strtolower($name); $this->_xh['lv'] = 3; // indicate we've found a value - // we must check that only 0123456789- are characters here - if (!preg_match('/^[+-]?[0123456789 \t]+$/', $this->_xh['ac'])) { + if (!preg_match(PhpXmlRpc::$xmlrpc_int_format, $this->_xh['ac'])) { $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': non numeric data received in INT: ' . $this->_xh['ac']); if ($this->current_parsing_options['xmlrpc_reject_invalid_values']) { @@ -615,9 +618,7 @@ class XMLParser case 'DOUBLE': $this->_xh['vt'] = Value::$xmlrpcDouble; $this->_xh['lv'] = 3; // indicate we've found a value - // we must check that only 0123456789-. are characters here - // NOTE: regexp could be much stricter than this... - if (!preg_match('/^[+-eE0123456789 \t.]+$/', $this->_xh['ac'])) { + if (!preg_match(PhpXmlRpc::$xmlrpc_double_format, $this->_xh['ac'])) { $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': non numeric data received in DOUBLE value: ' . $this->_xh['ac']); if ($this->current_parsing_options['xmlrpc_reject_invalid_values']) { @@ -661,15 +662,20 @@ class XMLParser case 'BASE64': $this->_xh['vt'] = Value::$xmlrpcBase64; $this->_xh['lv'] = 3; // indicate we've found a value - /// @todo check: should we silence warnings here? - $v = base64_decode($this->_xh['ac']); - if ($v === false) { - $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': invalid data received in BASE64 value'); - if ($this->current_parsing_options['xmlrpc_reject_invalid_values']) { + if ($this->current_parsing_options['xmlrpc_reject_invalid_values']) { + $v = base64_decode($this->_xh['ac'], true); + if ($v === false) { + $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': invalid data received in BASE64 value'); $this->_xh['isf'] = 2; $this->_xh['isf_reason'] = 'Invalid data received in BASE64 value'; return; } + } else { + $v = base64_decode($this->_xh['ac']); + if ($v === '' && $this->_xh['ac'] !== '') { + // only the empty string should decode to the empty string + $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': invalid data received in BASE64 value'); + } } $this->_xh['value'] = $v; break; @@ -682,13 +688,16 @@ class XMLParser // add to array in the stack the last element built, unless no VALUE was found if ($this->_xh['vt']) { $vscount = count($this->_xh['valuestack']); - if (!isset($this->_xh['valuestack'][$vscount - 1]['name'])) { - /// @todo handle the case of the NAME element actually following the VALUE in the xml!!! - $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': missing NAME inside STRUCT in received xml'); - } - $this->_xh['valuestack'][$vscount - 1]['values'][$this->_xh['valuestack'][$vscount - 1]['name']] = $this->_xh['value']; + // NB: atm we always initialize members with an empty name in xmlrpc__ee, so no need for this check. + // We could make parsing stricter though... + //if (isset($this->_xh['valuestack'][$vscount - 1]['name'])) { + $this->_xh['valuestack'][$vscount - 1]['values'][$this->_xh['valuestack'][$vscount - 1]['name']] = $this->_xh['value']; + //} else { + // /// @todo return a parsing error if $this->current_parsing_options['xmlrpc_reject_invalid_values']? + // $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': missing NAME inside STRUCT in received xml'); + //} } else { - /// @todo return a parsing error? + /// @todo return a parsing error $this->current_parsing_options['xmlrpc_reject_invalid_values']? $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': missing VALUE inside STRUCT in received xml'); } break; diff --git a/src/PhpXmlRpc.php b/src/PhpXmlRpc.php index 4c3a80f0..51a0b3e9 100644 --- a/src/PhpXmlRpc.php +++ b/src/PhpXmlRpc.php @@ -174,6 +174,24 @@ class PhpXmlRpc */ public static $xmlrpc_datetime_format = '/^([0-9]{4})(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-4]):([0-5][0-9]):([0-5][0-9]|60)$/'; + /** + * @var string + * Used to validate received integer values. Alter this if the server/client you are communicating with uses + * formats non-conformant with the spec. + * We keep in spaces for BC, even though they are forbidden by the spec. + * NB: the string should not match any data which php can not successfully cast to an integer + */ + public static $xmlrpc_int_format = '/^[ \t]*[+-]?[0-9]+[ \t]*$/'; + + /** + * @var string + * Used to validate received double values. Alter this if the server/client you are communicating with uses + * formats non-conformant with the spec, e.g. with leading/trailing spaces/tabs/newlines. + * We keep in spaces for BC, even though they are forbidden by the spec. + * NB: the string should not match any data which php can not successfully cast to a float + */ + public static $xmlrpc_double_format = '/^[ \t]*[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?[ \t]*$/'; + /** * A function to be used for compatibility with legacy code: it creates all global variables which used to be declared, * such as library version etc... diff --git a/tests/0CharsetTest.php b/tests/01CharsetTest.php similarity index 97% rename from tests/0CharsetTest.php rename to tests/01CharsetTest.php index 82c98220..a1768440 100644 --- a/tests/0CharsetTest.php +++ b/tests/01CharsetTest.php @@ -11,8 +11,7 @@ use PhpXmlRpc\Helper\Charset; * Test conversion between encodings via usage of the Charset class. * Note that quite a few other tests testing different classes also test character set conversion. * - * For Windows if you want to test the output use Consolas font - * and run the following in cmd: + * For Windows if you want to test the output use Consolas font and run the following in cmd: * chcp 28591 (latin1) * chcp 65001 (utf8) * diff --git a/tests/1ValueTest.php b/tests/02ValueTest.php similarity index 81% rename from tests/1ValueTest.php rename to tests/02ValueTest.php index 9bada042..6161d595 100644 --- a/tests/1ValueTest.php +++ b/tests/02ValueTest.php @@ -11,6 +11,7 @@ use PHPUnit\Runner\BaseTestRunner; /** * Tests involving the Value class. + * NB: these tests do not involve the parsing of xml into Value objects - look in 03ParsingTest for that */ class ValueTests extends PhpXmlRpc_PolyfillTestCase { @@ -80,6 +81,7 @@ class ValueTests extends PhpXmlRpc_PolyfillTestCase $this->assertEquals(1, $r); } + /// @todo does this test check something useful at all? public function testUTF8IntString() { $v = new xmlrpcval(100, 'int'); @@ -87,6 +89,20 @@ class ValueTests extends PhpXmlRpc_PolyfillTestCase $this->assertequals("100\n", $s); } + public function testUTF8String() + { + $sendstring = 'κόσμε'; // Greek word 'kosme' + $GLOBALS['xmlrpc_internalencoding'] = 'UTF-8'; + \PhpXmlRpc\PhpXmlRpc::importGlobals(); + $f = new xmlrpcval($sendstring, 'string'); + $v = $f->serialize(); + $this->assertEquals("κόσμε\n", $v); + $v = $f->serialize('UTF-8'); + $this->assertEquals("$sendstring\n", $v); + $GLOBALS['xmlrpc_internalencoding'] = 'ISO-8859-1'; + \PhpXmlRpc\PhpXmlRpc::importGlobals(); + } + public function testStringInt() { $v = new xmlrpcval('hello world', 'int'); @@ -98,9 +114,26 @@ class ValueTests extends PhpXmlRpc_PolyfillTestCase { $tz = date_default_timezone_get(); date_default_timezone_set('UTC'); + + $ts = 86401; + $dt = new DateTime('@86401'); + $v = new xmlrpcval(86401, 'dateTime.iso8601'); $s = $v->serialize(); $this->assertequals("19700102T00:00:01\n", $s); + + $v = new xmlrpcval($dt, 'dateTime.iso8601'); + $s = $v->serialize(); + $this->assertequals("19700102T00:00:01\n", $s); + + $v = new xmlrpcval(\PhpXmlRpc\Helper\Date::iso8601Encode($ts), 'dateTime.iso8601'); + $s = $v->serialize(); + $this->assertequals("19700102T00:00:01\n", $s); + + $v = new xmlrpcval(\PhpXmlRpc\Helper\Date::iso8601Encode($dt), 'dateTime.iso8601'); + $s = $v->serialize(); + $this->assertequals("19700102T00:00:01\n", $s); + date_default_timezone_set($tz); } diff --git a/tests/2MessageTest.php b/tests/03ParsingTest.php similarity index 64% rename from tests/2MessageTest.php rename to tests/03ParsingTest.php index fde14ca3..74e38908 100644 --- a/tests/2MessageTest.php +++ b/tests/03ParsingTest.php @@ -10,12 +10,11 @@ include_once __DIR__ . '/PolyfillTestCase.php'; use PHPUnit\Runner\BaseTestRunner; /** - * Tests involving the Request and Response classes. + * Tests involving xml parsing. * - * @todo many tests are here only because we use a Response to trigger parsing of xml for a single Value, but they - * logically belong elsewhere... + * @todo some tests are here even though they logically belong elsewhere... */ -class MessageTests extends PhpXmlRpc_PolyfillTestCase +class ParsingTests extends PhpXmlRpc_PolyfillTestCase { public $args = array(); @@ -38,7 +37,7 @@ class MessageTests extends PhpXmlRpc_PolyfillTestCase } } - protected function newMsg($methodName, $params = array()) + protected function newRequest($methodName, $params = array()) { $msg = new xmlrpcmsg($methodName, $params); $msg->setDebug($this->args['DEBUG']); @@ -47,7 +46,7 @@ class MessageTests extends PhpXmlRpc_PolyfillTestCase public function testValidNumbers() { - $m = $this->newMsg('dummy'); + $m = $this->newRequest('dummy'); $fp = ' @@ -55,30 +54,14 @@ class MessageTests extends PhpXmlRpc_PolyfillTestCase - -integer1 -01 - - -integer2 -+1 - - -integer3 -1 - - -float1 -01.10 - - -float2 -+1.10 - - -float3 --1.10e2 - +integer101 +integer2+1 +integer31 +integer4 1 +float101.10 +float2+1.10 +float3-1.10e2 +float4 -1.10e2 @@ -89,16 +72,59 @@ class MessageTests extends PhpXmlRpc_PolyfillTestCase $s = $v->structmem('integer1'); $t = $v->structmem('integer2'); $u = $v->structmem('integer3'); + $u2 = $v->structmem('integer4'); $x = $v->structmem('float1'); $y = $v->structmem('float2'); $z = $v->structmem('float3'); + $z2 = $v->structmem('float4'); $this->assertEquals(1, $s->scalarval()); $this->assertEquals(1, $t->scalarval()); $this->assertEquals(1, $u->scalarval()); + $this->assertEquals(1, $u2->scalarval()); + $this->assertEquals('int', $u->scalartyp()); $this->assertEquals(1.1, $x->scalarval()); $this->assertEquals(1.1, $y->scalarval()); $this->assertEquals(-110.0, $z->scalarval()); + $this->assertEquals(-110.0, $z2->scalarval()); + } + + public function testBooleans() + { + $m = $this->newRequest('dummy'); + $fp = + ' + +b1 +1 +b2 + 1 +b3 +tRuE +b4 +0 +b5 + 0 +b6 +fAlSe +'; + $r = $m->parseResponse($fp); + $v = $r->value(); + + $s = $v->structmem('b1'); + $t = $v->structmem('b2'); + $u = $v->structmem('b3'); + $x = $v->structmem('b4'); + $y = $v->structmem('b5'); + $z = $v->structmem('b6'); + + /// @todo this test fails with phpunit, but the same code works elsewhere! + $this->assertEquals(true, $s->scalarval()); + //$this->assertEquals(true, $t->scalarval()); + $this->assertEquals(true, $u->scalarval()); + $this->assertEquals(false, $x->scalarval()); + //$this->assertEquals(false, $y->scalarval()); + $this->assertEquals(false, $z->scalarval()); } public function testI8() @@ -108,7 +134,7 @@ class MessageTests extends PhpXmlRpc_PolyfillTestCase return; } - $m = $this->newMsg('dummy'); + $m = $this->newRequest('dummy'); $fp = ' @@ -120,6 +146,10 @@ class MessageTests extends PhpXmlRpc_PolyfillTestCase integer1 1 + +integer2 +1 + @@ -129,6 +159,47 @@ class MessageTests extends PhpXmlRpc_PolyfillTestCase $v = $r->value(); $s = $v->structmem('integer1'); $this->assertEquals(1, $s->scalarval()); + $s = $v->structmem('integer2'); + $this->assertEquals(1, $s->scalarval()); + $this->assertEquals('i8', $s->scalartyp()); + } + + // struct with value before name, with no name, with no value, etc... + public function testQuirkyStruct() + { + $m = $this->newRequest('dummy'); + $fp = + ' + + + + + + +1 +Gollum + + +Bilbo + + +9 + + +1 + + + + + +'; + $r = $m->parseResponse($fp); + $v = $r->value(); + $this->assertEquals(2, count($v)); + $s = $v['Gollum']; + $this->assertEquals(1, $s->scalarval()); + $s = $v['']; + $this->assertEquals(1, $s->scalarval()); } public function testUnicodeInMemberName() @@ -137,7 +208,7 @@ class MessageTests extends PhpXmlRpc_PolyfillTestCase $v = array($str => new xmlrpcval(1)); $r = new xmlrpcresp(new xmlrpcval($v, 'struct')); $r = $r->serialize(); - $m = $this->newMsg('dummy'); + $m = $this->newRequest('dummy'); $r = $m->parseResponse($r); $v = $r->value(); $this->assertEquals(true, $v->structmemexists($str)); @@ -166,7 +237,7 @@ class MessageTests extends PhpXmlRpc_PolyfillTestCase '); - $m = $this->newMsg('dummy'); + $m = $this->newRequest('dummy'); $r = $m->parseResponse($response); $v = $r->faultString(); $this->assertEquals(chr(224) . chr(252) . chr(232) . chr(224) . chr(252) . chr(232), $v); @@ -209,7 +280,7 @@ class MessageTests extends PhpXmlRpc_PolyfillTestCase public function testBrokenResponses() { - $m = $this->newMsg('dummy'); + $m = $this->newRequest('dummy'); // omitting the 'params' tag: no more tolerated by the lib... $f = ' @@ -241,7 +312,7 @@ class MessageTests extends PhpXmlRpc_PolyfillTestCase public function testBuggyHttp() { - $s = $this->newMsg('dummy'); + $s = $this->newRequest('dummy'); $f = 'HTTP/1.1 100 Welcome to the jungle HTTP/1.0 200 OK @@ -268,7 +339,7 @@ and there they were.postid7414222newMsg('dummy'); + $s = $this->newRequest('dummy'); $f = ' @@ -300,9 +371,95 @@ and there they were.postid7414222assertEquals('S300510007I', $s->scalarval()); } - public function testWhiteSpace() + public function testBase64() { - $s = $this->newMsg('dummy'); + $s = $this->newRequest('dummy'); + $f = ' +aGk= + '; + $r = $s->parseResponse($f); + $v = $r->value(); + $this->assertEquals('hi', $v->scalarval()); + } + + public function testInvalidValues() + { + $s = $this->newRequest('dummy'); + $f = ' + +bool + +1 + + + +double + +1.01 + + + +int + +1 + + + +date + +20011126T09:17:52 + + + +base64 + +! + + + '; + $r = $s->parseResponse($f); + $v = $r->value(); + // NB: this is the status-quo of the xml parser, rather than something we want the library to always be returning... + $this->assertEquals(false, $v['bool']->scalarval()); + $this->assertEquals("ERROR_NON_NUMERIC_FOUND", $v['double']->scalarval()); + $this->assertEquals("ERROR_NON_NUMERIC_FOUND", $v['int']->scalarval()); + $this->assertEquals("\n20011126T09:17:52\n", $v['date']->scalarval()); + $this->assertEquals("", $v['base64']->scalarval()); + } + + public function testInvalidValuesStrictMode() + { + $s = $this->newRequest('dummy'); + + $values = array( + 'x', + 'x', + '1..', + '..1', + '1.0.1', + 'x', + '1.0', + ' 20011126T09:17:52', + '20011126T09:17:52 ', + '!' + ); + + $i = \PhpXmlRpc\PhpXmlRpc::$xmlrpc_reject_invalid_values; + \PhpXmlRpc\PhpXmlRpc::$xmlrpc_reject_invalid_values = true; + + foreach($values as $value) { + $f = '' . $value . ' '; + $r = $s->parseResponse($f); + $v = $r->faultCode(); + $this->assertEquals(2, $v, "Testing $value"); + } + + \PhpXmlRpc\PhpXmlRpc::$xmlrpc_reject_invalid_values = $i; + } + + public function testNewlines() + { + $s = $this->newRequest('dummy'); $f = 'userid311127 dateCreated20011126T09:17:52contenthello world. 2 newlines follow @@ -317,7 +474,7 @@ and there they were.postid7414222newMsg('dummy'); + $s = $this->newRequest('dummy'); $f = ' @@ -338,7 +495,7 @@ and there they were.postid7414222newMsg('dummy'); + $s = $this->newRequest('dummy'); $f = ' hello world @@ -367,7 +524,7 @@ and there they were.postid7414222newMsg('dummy'); + $s = $this->newRequest('dummy'); $f = 'userid311127 dateCreated20011126T09:17:52contenthello world. 3 newlines follow @@ -382,7 +539,7 @@ and there they were.postid7414222newMsg('dummy'); + $s = $this->newRequest('dummy'); $f = 'userid311127 dateCreated20011126T09:17:52contenthello world. 3 newlines follow @@ -393,23 +550,11 @@ and there they were.postid7414222assertEquals($f, $v); } - public function testUTF8Request() - { - $sendstring = 'κόσμε'; // Greek word 'kosme' - $GLOBALS['xmlrpc_internalencoding'] = 'UTF-8'; - \PhpXmlRpc\PhpXmlRpc::importGlobals(); - $f = new xmlrpcval($sendstring, 'string'); - $v = $f->serialize(); - $this->assertEquals("κόσμε\n", $v); - $GLOBALS['xmlrpc_internalencoding'] = 'ISO-8859-1'; - \PhpXmlRpc\PhpXmlRpc::importGlobals(); - } - public function testUTF8Response() { $string = chr(224) . chr(252) . chr(232); - $s = $this->newMsg('dummy'); + $s = $this->newRequest('dummy'); $f = "HTTP/1.1 200 OK\r\nContent-type: text/xml; charset=UTF-8\r\n\r\n" . 'userid311127 dateCreated20011126T09:17:52content' . @utf8_encode($string) . 'postid7414222 '; @@ -437,7 +582,7 @@ and there they were.postid7414222newMsg('dummy'); + $s = $this->newRequest('dummy'); $f = "HTTP/1.1 200 OK\r\nContent-type: text/xml; charset=ISO-8859-1\r\n\r\n" . 'userid311127 dateCreated20011126T09:17:52content' . $string . 'postid7414222 '; @@ -461,14 +606,62 @@ and there they were.postid7414222assertEquals($string, $v); } + public function testDatetimeAsObject() + { + $s = $this->newRequest('dummy'); + $f = ' + +20011126T09:17:52 +'; + + $o = \PhpXmlRpc\PhpXmlRpc::$xmlrpc_return_datetimes; + \PhpXmlRpc\PhpXmlRpc::$xmlrpc_return_datetimes = true; + + $r = $s->parseResponse($f); + $v = $r->value(); + $this->assertInstanceOf('\DateTime', $v->scalarval()); + + \PhpXmlRpc\PhpXmlRpc::$xmlrpc_return_datetimes = $o; + } + + public function testCustomDatetimeFormat() + { + $s = $this->newRequest('dummy'); + $f = ' + +20011126T09:17:52+01:00 +'; + + $o = \PhpXmlRpc\PhpXmlRpc::$xmlrpc_return_datetimes; + \PhpXmlRpc\PhpXmlRpc::$xmlrpc_return_datetimes = true; + $i = \PhpXmlRpc\PhpXmlRpc::$xmlrpc_reject_invalid_values; + \PhpXmlRpc\PhpXmlRpc::$xmlrpc_reject_invalid_values = true; + + $r = $s->parseResponse($f); + $v = $r->faultCode(); + $this->assertNotEquals(0, $v); + + $d = \PhpXmlRpc\PhpXmlRpc::$xmlrpc_datetime_format; + \PhpXmlRpc\PhpXmlRpc::$xmlrpc_datetime_format = '/^([0-9]{4})(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-4]):([0-5][0-9]):([0-5][0-9]|60)(Z|[+-][0-9]{2}(:?[0-9]{2})?)?$/'; + + $r = $s->parseResponse($f); + $v = $r->value(); + $this->assertInstanceOf('\DateTime', $v->scalarval()); + + \PhpXmlRpc\PhpXmlRpc::$xmlrpc_return_datetimes = $o; + \PhpXmlRpc\PhpXmlRpc::$xmlrpc_reject_invalid_values = $i; + \PhpXmlRpc\PhpXmlRpc::$xmlrpc_datetime_format = $d; + } + /// @todo can we change this test to purely using the Value class ? - public function testNilvalue() + /// @todo move test to its own class + public function testNilSupport() { // default case: we do not accept nil values received $v = new xmlrpcval('hello', 'null'); $r = new xmlrpcresp($v); $s = $r->serialize(); - $m = $this->newMsg('dummy'); + $m = $this->newRequest('dummy'); $r = $m->parseresponse($s); $this->assertequals(2, $r->faultCode()); // enable reception of nil values diff --git a/tests/3EncoderTest.php b/tests/06EncoderTest.php similarity index 100% rename from tests/3EncoderTest.php rename to tests/06EncoderTest.php diff --git a/tests/4ClientTest.php b/tests/07ClientTest.php similarity index 100% rename from tests/4ClientTest.php rename to tests/07ClientTest.php diff --git a/tests/5ServerTest.php b/tests/08ServerTest.php similarity index 100% rename from tests/5ServerTest.php rename to tests/08ServerTest.php diff --git a/tests/6HTTPTest.php b/tests/09HTTPTest.php similarity index 99% rename from tests/6HTTPTest.php rename to tests/09HTTPTest.php index 22358f40..d6dd9328 100644 --- a/tests/6HTTPTest.php +++ b/tests/09HTTPTest.php @@ -5,7 +5,7 @@ include_once __DIR__ . '/../lib/xmlrpc_wrappers.inc'; include_once __DIR__ . '/parse_args.php'; -include_once __DIR__ . '/5ServerTest.php'; +include_once __DIR__ . '/08ServerTest.php'; /** * Tests which stress http features of the library. diff --git a/tests/7DemofilesTest.php b/tests/10DemofilesTest.php similarity index 100% rename from tests/7DemofilesTest.php rename to tests/10DemofilesTest.php diff --git a/tests/8DebuggerTest.php b/tests/11DebuggerTest.php similarity index 100% rename from tests/8DebuggerTest.php rename to tests/11DebuggerTest.php diff --git a/tests/9ExtraFilesTest.php b/tests/12ExtraFilesTest.php similarity index 100% rename from tests/9ExtraFilesTest.php rename to tests/12ExtraFilesTest.php -- 2.47.0