From c27693ac87a6a64a63d410f3e0cd9aa00cf7841a Mon Sep 17 00:00:00 2001 From: gggeek Date: Mon, 11 Jan 2021 09:22:31 +0000 Subject: [PATCH] nitpicks; prepare for release --- NEWS | 6 +- lib/xmlrpc.inc | 6 +- src/Client.php | 3 +- src/Encoder.php.bak | 339 -------------------------------------------- src/PhpXmlRpc.php | 2 +- 5 files changed, 11 insertions(+), 345 deletions(-) delete mode 100644 src/Encoder.php.bak diff --git a/NEWS b/NEWS index 0ff0d6d..3d2f11d 100644 --- a/NEWS +++ b/NEWS @@ -1,13 +1,13 @@ -XML-RPC for PHP version 4.5.2 - 2021/1/9 +XML-RPC for PHP version 4.5.2 - 2021/1/11 * improved: better phpdocs in the the php code generated by the Wrapper class -* improved: allow usage of 'epivals' for the 'parameters_type' member of methods definitions in the Server dispatch map - * improved: debugger favicon and page title when used from the phpjsonrpc library * fixed: allow `Encoder::decode` to properly support different target character sets for polyfill-xmlrpc decode functions +* improved: allow usage of 'epivals' for the 'parameters_type' member of methods definitions in the Server dispatch map + XML-RPC for PHP version 4.5.1 - 2021/1/3 diff --git a/lib/xmlrpc.inc b/lib/xmlrpc.inc index 7e03834..8059405 100644 --- a/lib/xmlrpc.inc +++ b/lib/xmlrpc.inc @@ -41,7 +41,11 @@ * This file is only used to insure backwards compatibility * with the API of the library <= rev. 3 * - * If it is included, the library will work without any further autoloading + * If it is included, the library will work without any further autoloading. + * + * NB: including this file will also alter the library configuration setting the + * expected charset encoding used by the app to ISO-8859-1. Please see the + * file api_changes_v4.md for how to change this if required. *****************************************************************************/ include_once(__DIR__.'/../src/Client.php'); diff --git a/src/Client.php b/src/Client.php index 2f6444a..fe4eb5d 100644 --- a/src/Client.php +++ b/src/Client.php @@ -168,7 +168,7 @@ class Client // if ZLIB is enabled, let the client by default accept compressed responses if (function_exists('gzinflate') || ( - function_exists('curl_init') && (($info = curl_version()) && + function_exists('curl_version') && (($info = curl_version()) && ((is_string($info) && strpos($info, 'zlib') !== null) || isset($info['libz_version']))) ) ) { @@ -463,6 +463,7 @@ class Client * chosen during creation of the object will be used. * * @return Response|Response[] Note that the client will always return a Response object, even if the call fails + * @todo allow throwing exceptions instead of returning responses in case of failed calls and/or Fault responses */ public function send($req, $timeout = 0, $method = '') { diff --git a/src/Encoder.php.bak b/src/Encoder.php.bak deleted file mode 100644 index ab4311c..0000000 --- a/src/Encoder.php.bak +++ /dev/null @@ -1,339 +0,0 @@ -kindOf()) { - case 'scalar': - if (in_array('extension_api', $options)) { - $val = reset($xmlrpcVal->me); - $typ = key($xmlrpcVal->me); - switch ($typ) { - case 'dateTime.iso8601': - $xmlrpcVal = array( - 'xmlrpc_type' => 'datetime', - 'scalar' => $val, - 'timestamp' => \PhpXmlRpc\Helper\Date::iso8601Decode($val) - ); - return (object)$xmlrpcVal; - case 'base64': - $xmlrpcVal = array( - 'xmlrpc_type' => 'base64', - 'scalar' => $val - ); - return (object)$xmlrpcVal; - default: - return $xmlrpcVal->scalarval(); - } - } - if (in_array('dates_as_objects', $options) && $xmlrpcVal->scalartyp() == 'dateTime.iso8601') { - // we return a Datetime object instead of a string since now the constructor of xmlrpc value accepts - // safely strings, ints and datetimes, we cater to all 3 cases here - $out = $xmlrpcVal->scalarval(); - if (is_string($out)) { - $out = strtotime($out); - } - if (is_int($out)) { - $result = new \DateTime(); - $result->setTimestamp($out); - - return $result; - } elseif (is_a($out, 'DateTimeInterface')) { - return $out; - } - } - return $xmlrpcVal->scalarval(); - - case 'array': - $arr = array(); - foreach($xmlrpcVal as $value) { - $arr[] = $this->decode($value, $options); - } - return $arr; - - case 'struct': - // If user said so, try to rebuild php objects for specific struct vals. - /// @todo should we raise a warning for class not found? - // shall we check for proper subclass of xmlrpc value instead of presence of _php_class to detect - // what we can do? - if (in_array('decode_php_objs', $options) && $xmlrpcVal->_php_class != '' - && class_exists($xmlrpcVal->_php_class) - ) { - $obj = @new $xmlrpcVal->_php_class(); - foreach ($xmlrpcVal as $key => $value) { - $obj->$key = $this->decode($value, $options); - } - return $obj; - } else { - $arr = array(); - foreach ($xmlrpcVal as $key => $value) { - $arr[$key] = $this->decode($value, $options); - } - return $arr; - } - - case 'msg': - $paramCount = $xmlrpcVal->getNumParams(); - $arr = array(); - for ($i = 0; $i < $paramCount; $i++) { - $arr[] = $this->decode($xmlrpcVal->getParam($i), $options); - } - return $arr; - - /// @todo throw on unsupported type - } - } - - /** - * Takes native php types and encodes them into xmlrpc PHP object format. - * It will not re-encode xmlrpc value objects. - * - * Feature creep -- could support more types via optional type argument - * (string => datetime support has been added, ??? => base64 not yet) - * - * If given a proper options parameter, php object instances will be encoded into 'special' xmlrpc values, that can - * later be decoded into php objects by calling php_xmlrpc_decode() with a corresponding option - * - * @author Dan Libby (dan@libby.com) - * - * @param mixed $phpVal the value to be converted into an xmlrpc value object - * @param array $options can include 'encode_php_objs', 'auto_dates', 'null_extension' or 'extension_api' - * - * @return Value - */ - public function encode($phpVal, $options = array()) - { - $type = gettype($phpVal); - switch ($type) { - case 'string': - /// @todo should we be stricter in the accepted dates (ie. 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)) { - $xmlrpcVal = new Value($phpVal, Value::$xmlrpcDateTime); - } else { - $xmlrpcVal = new Value($phpVal, Value::$xmlrpcString); - } - break; - case 'integer': - $xmlrpcVal = new Value($phpVal, Value::$xmlrpcInt); - break; - case 'double': - $xmlrpcVal = new Value($phpVal, Value::$xmlrpcDouble); - break; - // Add support for encoding/decoding of booleans, since they are supported in PHP - case 'boolean': - $xmlrpcVal = new Value($phpVal, Value::$xmlrpcBoolean); - break; - case 'array': - // PHP arrays can be encoded to either xmlrpc structs or arrays, depending on whether they are hashes - // or plain 0..n integer indexed - // A shorter one-liner would be - // $tmp = array_diff(array_keys($phpVal), range(0, count($phpVal)-1)); - // but execution time skyrockets! - $j = 0; - $arr = array(); - $ko = false; - foreach ($phpVal as $key => $val) { - $arr[$key] = $this->encode($val, $options); - if (!$ko && $key !== $j) { - $ko = true; - } - $j++; - } - if ($ko) { - $xmlrpcVal = new Value($arr, Value::$xmlrpcStruct); - } else { - $xmlrpcVal = new Value($arr, Value::$xmlrpcArray); - } - break; - case 'object': - if (is_a($phpVal, 'PhpXmlRpc\Value')) { - $xmlrpcVal = $phpVal; - } elseif (is_a($phpVal, 'DateTimeInterface')) { - $xmlrpcVal = new Value($phpVal->format('Ymd\TH:i:s'), Value::$xmlrpcDateTime); - } elseif (in_array('extension_api', $options) && $phpVal instanceof \stdClass && isset($phpVal->xmlrpc_type)) { - // Handle the 'pre-converted' base64 and datetime values - if (isset($phpVal->scalar)) { - switch ($phpVal->xmlrpc_type) { - case 'base64': - $xmlrpcVal = new Value($phpVal->scalar, Value::$xmlrpcBase64); - break; - case 'datetime': - $xmlrpcVal = new Value($phpVal->scalar, Value::$xmlrpcDateTime); - break; - default: - $xmlrpcVal = new Value(); - } - } else { - $xmlrpcVal = new Value(); - } - - } else { - $arr = array(); - foreach($phpVal as $k => $v) { - $arr[$k] = $this->encode($v, $options); - } - $xmlrpcVal = new Value($arr, Value::$xmlrpcStruct); - if (in_array('encode_php_objs', $options)) { - // let's save original class name into xmlrpc value: - // might be useful later on... - $xmlrpcVal->_php_class = get_class($phpVal); - } - } - break; - case 'NULL': - if (in_array('extension_api', $options)) { - $xmlrpcVal = new Value('', Value::$xmlrpcString); - } elseif (in_array('null_extension', $options)) { - $xmlrpcVal = new Value('', Value::$xmlrpcNull); - } else { - $xmlrpcVal = new Value(); - } - break; - case 'resource': - if (in_array('extension_api', $options)) { - $xmlrpcVal = new Value((int)$phpVal, Value::$xmlrpcInt); - } else { - $xmlrpcVal = new Value(); - } - break; - // catch "user function", "unknown type" - default: - // giancarlo pinerolo - // it has to return an empty object in case, not a boolean. - $xmlrpcVal = new Value(); - break; - } - - return $xmlrpcVal; - } - - /** - * Convert the xml representation of a method response, method request or single - * xmlrpc value into the appropriate object (a.k.a. deserialize). - * - * @todo is this a good name/class for this method? It does something quite different from 'decode' after all - * (returning objects vs returns plain php values)... In fact it belongs rather to a Parser class - * - * @param string $xmlVal - * @param array $options - * - * @return Value|Request|Response|false false on error, or an instance of either Value, Request or Response - */ - public function decodeXml($xmlVal, $options = array()) - { - // 'guestimate' encoding - $valEncoding = XMLParser::guessEncoding('', $xmlVal); - if ($valEncoding != '') { - - // Since parsing will fail if - // - charset is not specified in the xml prologue, - // - the encoding is not UTF8 and - // - there are non-ascii chars in the text, - // we try to work round that... - // The following code might be better for mb_string enabled installs, but makes the lib about 200% slower... - //if (!is_valid_charset($valEncoding, array('UTF-8')) - if (!in_array($valEncoding, array('UTF-8', 'US-ASCII')) && !XMLParser::hasEncoding($xmlVal)) { - if ($valEncoding == 'ISO-8859-1') { - $xmlVal = utf8_encode($xmlVal); - } else { - if (extension_loaded('mbstring')) { - $xmlVal = mb_convert_encoding($xmlVal, 'UTF-8', $valEncoding); - } else { - Logger::instance()->errorLog('XML-RPC: ' . __METHOD__ . ': invalid charset encoding of xml text: ' . $valEncoding); - } - } - } - } - - // What if internal encoding is not in one of the 3 allowed? We use the broadest one, ie. utf8! - if (!in_array(PhpXmlRpc::$xmlrpc_internalencoding, array('UTF-8', 'ISO-8859-1', 'US-ASCII'))) { - /// @todo emit a warning - $parserOptions = array(XML_OPTION_TARGET_ENCODING => 'UTF-8'); - } else { - $parserOptions = array(XML_OPTION_TARGET_ENCODING => PhpXmlRpc::$xmlrpc_internalencoding); - } - - $xmlRpcParser = new XMLParser($parserOptions); - $xmlRpcParser->parse($xmlVal, XMLParser::RETURN_XMLRPCVALS, XMLParser::ACCEPT_REQUEST | XMLParser::ACCEPT_RESPONSE | XMLParser::ACCEPT_VALUE | XMLParser::ACCEPT_FAULT); - - if ($xmlRpcParser->_xh['isf'] > 1) { - // test that $xmlrpc->_xh['value'] is an obj, too??? - - Logger::instance()->errorLog($xmlRpcParser->_xh['isf_reason']); - - return false; - } - - switch ($xmlRpcParser->_xh['rt']) { - case 'methodresponse': - $v = $xmlRpcParser->_xh['value']; - if ($xmlRpcParser->_xh['isf'] == 1) { - /** @var Value $vc */ - $vc = $v['faultCode']; - /** @var Value $vs */ - $vs = $v['faultString']; - $r = new Response(0, $vc->scalarval(), $vs->scalarval()); - } else { - $r = new Response($v); - } - return $r; - - case 'methodcall': - $req = new Request($xmlRpcParser->_xh['method']); - for ($i = 0; $i < count($xmlRpcParser->_xh['params']); $i++) { - $req->addParam($xmlRpcParser->_xh['params'][$i]); - } - return $req; - - case 'value': - return $xmlRpcParser->_xh['value']; - - case 'fault': - // EPI api emulation - $v = $xmlRpcParser->_xh['value']; - // use a known error code - /** @var Value $vc */ - $vc = isset($v['faultCode']) ? $v['faultCode']->scalarval() : PhpXmlRpc::$xmlrpcerr['invalid_return']; - /** @var Value $vs */ - $vs = isset($v['faultString']) ? $v['faultString']->scalarval() : ''; - if (!is_int($vc) || $vc == 0) { - $vc = PhpXmlRpc::$xmlrpcerr['invalid_return']; - } - return new Response(0, $vc, $vs); - default: - return false; - } - } -} diff --git a/src/PhpXmlRpc.php b/src/PhpXmlRpc.php index e812634..8dd945d 100644 --- a/src/PhpXmlRpc.php +++ b/src/PhpXmlRpc.php @@ -78,7 +78,7 @@ class PhpXmlRpc public static $xmlrpc_internalencoding = "UTF-8"; public static $xmlrpcName = "XML-RPC for PHP"; - public static $xmlrpcVersion = "4.5.2-dev"; + public static $xmlrpcVersion = "4.5.2"; // let user errors start at 800 public static $xmlrpcerruser = 800; -- 2.43.0