From f31a58c86c780c483ed231b9f7156fadf679eef6 Mon Sep 17 00:00:00 2001 From: gggeek Date: Sat, 21 Jan 2023 17:37:51 +0000 Subject: [PATCH] use everywhere the same regexp to validate datetime values and allow it to be changed --- NEWS.md | 8 ++++++++ src/Encoder.php | 3 +-- src/Helper/Date.php | 4 +++- src/Helper/XMLParser.php | 16 ++++++++-------- src/PhpXmlRpc.php | 7 +++++++ 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/NEWS.md b/NEWS.md index 0035d2df..096ec66d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -19,6 +19,12 @@ NB: since the xml-rpc spec mandates that no Timezone is used on the wire for dateTime values, the DateTime objects created by the library will be set to the default php timzeone, set using the 'date.timezone' ini setting. +* new: it is now possible to tell the library to allow non-standard formats for received datetime value, such as f.e. + datetimes with a timezone specifier, by setting a custom value to `PhpXmlRpc\PhpXmlRpc::$xmlrpc_datetime_format`. + Note that the regex used by default to validate the incoming date strings has been tightened not to accept clearly + invalid dates such as a month '13', day '32' or hour '25'. The vale '60' is now allowed for seconds, as required by + the ISO 8601 standard for leap seconds. + * fixed: when calling `Client::multicall()` with `$client->return_type = 'xml'`, we would be always falling back to non-multicall requests @@ -69,6 +75,8 @@ to a custom character set and the mbstring extension is enabled. It will be encoded instead in the specified character set. We expect this to affect few users, as setting `PhpXmlRpc::$internal_encoding` to a custom character set did not make a lot of sense beforehand + - the regular expression used to check if incoming datetime values are valid has been tightened to reject clearly + invalid dates. It has been widened as well, to allow leap seconds. - parameters `$timeout` and `$method` are now considered deprecated in `Client::send()` and `Client::multicall()` - Client properties `$errno` and `$errstring` are now deprecated - the code generated by the debugger when using "Generate stub for method call" will throw on errors instead of diff --git a/src/Encoder.php b/src/Encoder.php index 8ce78a7d..72277005 100644 --- a/src/Encoder.php +++ b/src/Encoder.php @@ -210,8 +210,7 @@ class Encoder $type = gettype($phpVal); switch ($type) { case 'string': - /// @todo should we be stricter in the accepted dates (i.e. reject more of invalid days & times)? - if (in_array('auto_dates', $options) && preg_match('/^[0-9]{8}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/', $phpVal)) { + if (in_array('auto_dates', $options) && preg_match(PhpXmlRpc::$xmlrpc_datetime_format, $phpVal)) { $xmlrpcVal = new Value($phpVal, Value::$xmlrpcDateTime); } else { $xmlrpcVal = new Value($phpVal, Value::$xmlrpcString); diff --git a/src/Helper/Date.php b/src/Helper/Date.php index 4d840cc0..ad4c3d51 100644 --- a/src/Helper/Date.php +++ b/src/Helper/Date.php @@ -2,6 +2,8 @@ namespace PhpXmlRpc\Helper; +use PhpXmlRpc\PhpXmlRpc; + /** * Helps to convert timestamps to the xml-rpc date format. * @@ -49,7 +51,7 @@ class Date public static function iso8601Decode($idate, $utc = 0) { $t = 0; - if (preg_match('/([0-9]{4})([0-1][0-9])([0-3][0-9])T([0-2][0-9]):([0-5][0-9]):([0-5][0-9])/', $idate, $regs)) { + if (preg_match(PhpXmlRpc::$xmlrpc_datetime_format, $idate, $regs)) { if ($utc) { $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); } else { diff --git a/src/Helper/XMLParser.php b/src/Helper/XMLParser.php index 2e7dcaf0..1666a82a 100644 --- a/src/Helper/XMLParser.php +++ b/src/Helper/XMLParser.php @@ -559,7 +559,7 @@ class XMLParser if ($name == 'STRING') { $this->_xh['value'] = $this->_xh['ac']; } elseif ($name == 'DATETIME.ISO8601') { - if (!preg_match('/^[0-9]{8}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/', $this->_xh['ac'])) { + if (!preg_match(PhpXmlRpc::$xmlrpc_datetime_format, $this->_xh['ac'])) { $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': invalid value received in DATETIME: ' . $this->_xh['ac']); } $this->_xh['vt'] = Value::$xmlrpcDateTime; @@ -803,11 +803,11 @@ class XMLParser // in the xml declaration, and verify if they match. /// @todo implement check as described above? /// @todo implement check for first bytes of string even without a BOM? (It sure looks harder than for cases WITH a BOM) - if (preg_match('/^(\x00\x00\xFE\xFF|\xFF\xFE\x00\x00|\x00\x00\xFF\xFE|\xFE\xFF\x00\x00)/', $xmlChunk)) { + if (preg_match('/^(?:\x00\x00\xFE\xFF|\xFF\xFE\x00\x00|\x00\x00\xFF\xFE|\xFE\xFF\x00\x00)/', $xmlChunk)) { return 'UCS-4'; - } elseif (preg_match('/^(\xFE\xFF|\xFF\xFE)/', $xmlChunk)) { + } elseif (preg_match('/^(?:\xFE\xFF|\xFF\xFE)/', $xmlChunk)) { return 'UTF-16'; - } elseif (preg_match('/^(\xEF\xBB\xBF)/', $xmlChunk)) { + } elseif (preg_match('/^(?:\xEF\xBB\xBF)/', $xmlChunk)) { return 'UTF-8'; } @@ -862,11 +862,11 @@ class XMLParser { // scan the first bytes of the data for a UTF-16 (or other) BOM pattern // (source: http://www.w3.org/TR/2000/REC-xml-20001006) - if (preg_match('/^(\x00\x00\xFE\xFF|\xFF\xFE\x00\x00|\x00\x00\xFF\xFE|\xFE\xFF\x00\x00)/', $xmlChunk)) { + if (preg_match('/^(?:\x00\x00\xFE\xFF|\xFF\xFE\x00\x00|\x00\x00\xFF\xFE|\xFE\xFF\x00\x00)/', $xmlChunk)) { return true; - } elseif (preg_match('/^(\xFE\xFF|\xFF\xFE)/', $xmlChunk)) { + } elseif (preg_match('/^(?:\xFE\xFF|\xFF\xFE)/', $xmlChunk)) { return true; - } elseif (preg_match('/^(\xEF\xBB\xBF)/', $xmlChunk)) { + } elseif (preg_match('/^(?:\xEF\xBB\xBF)/', $xmlChunk)) { return true; } @@ -876,7 +876,7 @@ class XMLParser // EQ: SPACE?=SPACE? === [ \x9\xD\xA]*=[ \x9\xD\xA]* if (preg_match('/^<\?xml\s+version\s*=\s*' . "((?:\"[a-zA-Z0-9_.:-]+\")|(?:'[a-zA-Z0-9_.:-]+'))" . '\s+encoding\s*=\s*' . "((?:\"[A-Za-z][A-Za-z0-9._-]*\")|(?:'[A-Za-z][A-Za-z0-9._-]*'))/", - $xmlChunk, $matches)) { + $xmlChunk)) { return true; } diff --git a/src/PhpXmlRpc.php b/src/PhpXmlRpc.php index e93b92ee..b2d0409b 100644 --- a/src/PhpXmlRpc.php +++ b/src/PhpXmlRpc.php @@ -156,6 +156,13 @@ class PhpXmlRpc */ public static $xmlpc_double_precision = 128; + /** + * @var string + * Used to validate received date values. Alter this if the server/client you are communicating with uses date + * formats non-conformant with the spec + */ + 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)$/'; + /** * 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... -- 2.47.0