+## XML-RPC for PHP version 4.10.1 - unreleased
+
+* fixed: let the Server create Response objects whose class can be overridden by subclasses (this is required by the
+ json-rpc server now that the `xml_header` method has been moved to the `Request` object)
+
+
## XML-RPC for PHP version 4.10.0 - 2023/02/11
* changed: the minimum php version required has been increased to 5.4
$call['params'] = new Value($params, 'array');
$calls[] = new Value($call, 'struct');
}
- $multiCall = new Request('system.multicall');
+ $multiCall = new static::$requestClass('system.multicall');
$multiCall->addParam(new Value($calls, 'array'));
// Attempt RPC call
if ($this->return_type == 'xml') {
for ($i = 0; $i < count($reqs); $i++) {
- $response[] = new Response($rets, 0, '', 'xml', $result->httpResponse());
+ $response[] = new static::$responseClass($rets, 0, '', 'xml', $result->httpResponse());
}
} elseif ($this->return_type == 'phpvals') {
if (!is_array($rets)) {
// bad return type from system.multicall
- return new Response(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
+ return new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
PhpXmlRpc::$xmlrpcstr['multicall_error'] . ': not an array', 'phpvals', $result->httpResponse());
}
$numRets = count($rets);
if ($numRets != count($reqs)) {
// wrong number of return values.
- return new Response(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
+ return new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
PhpXmlRpc::$xmlrpcstr['multicall_error'] . ': incorrect number of responses', 'phpvals',
$result->httpResponse());
}
for ($i = 0; $i < $numRets; $i++) {
$val = $rets[$i];
if (!is_array($val)) {
- return new Response(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
+ return new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
PhpXmlRpc::$xmlrpcstr['multicall_error'] . ": response element $i is not an array or struct",
'phpvals', $result->httpResponse());
}
case 1:
if (!isset($val[0])) {
// Bad value
- return new Response(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
+ return new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
PhpXmlRpc::$xmlrpcstr['multicall_error'] . ": response element $i has no value",
'phpvals', $result->httpResponse());
}
// Normal return value
- $response[$i] = new Response($val[0], 0, '', 'phpvals', $result->httpResponse());
+ $response[$i] = new static::$responseClass($val[0], 0, '', 'phpvals', $result->httpResponse());
break;
case 2:
/// @todo remove usage of @: it is apparently quite slow
$code = @$val['faultCode'];
if (!is_int($code)) {
/// @todo should we check that it is != 0?
- return new Response(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
+ return new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
PhpXmlRpc::$xmlrpcstr['multicall_error'] . ": response element $i has invalid or no faultCode",
'phpvals', $result->httpResponse());
}
$str = @$val['faultString'];
if (!is_string($str)) {
- return new Response(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
+ return new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
PhpXmlRpc::$xmlrpcstr['multicall_error'] . ": response element $i has invalid or no FaultString",
'phpvals', $result->httpResponse());
}
- $response[$i] = new Response(0, $code, $str, 'phpvals', $result->httpResponse());
+ $response[$i] = new static::$responseClass(0, $code, $str, 'phpvals', $result->httpResponse());
break;
default:
- return new Response(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
+ return new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
PhpXmlRpc::$xmlrpcstr['multicall_error'] . ": response element $i has too many items",
'phpvals', $result->httpResponse());
}
} else {
// return type == 'xmlrpcvals'
if ($rets->kindOf() != 'array') {
- return new Response(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
+ return new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
PhpXmlRpc::$xmlrpcstr['multicall_error'] . ": response element $i is not an array", 'xmlrpcvals',
$result->httpResponse());
}
$numRets = $rets->count();
if ($numRets != count($reqs)) {
// wrong number of return values.
- return new Response(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
+ return new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
PhpXmlRpc::$xmlrpcstr['multicall_error'] . ': incorrect number of responses', 'xmlrpcvals',
$result->httpResponse());
}
switch ($val->kindOf()) {
case 'array':
if ($val->count() != 1) {
- return new Response(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
+ return new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
PhpXmlRpc::$xmlrpcstr['multicall_error'] . ": response element $i has too many items",
'phpvals', $result->httpResponse());
}
// Normal return value
- $response[] = new Response($val[0], 0, '', 'xmlrpcvals', $result->httpResponse());
+ $response[] = new static::$responseClass($val[0], 0, '', 'xmlrpcvals', $result->httpResponse());
break;
case 'struct':
if ($val->count() != 2) {
- return new Response(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
+ return new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
PhpXmlRpc::$xmlrpcstr['multicall_error'] . ": response element $i has too many items",
'phpvals', $result->httpResponse());
}
/** @var Value $code */
$code = $val['faultCode'];
if ($code->kindOf() != 'scalar' || $code->scalarTyp() != 'int') {
- return new Response(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
+ return new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
PhpXmlRpc::$xmlrpcstr['multicall_error'] . ": response element $i has invalid or no faultCode",
'xmlrpcvals', $result->httpResponse());
}
/** @var Value $str */
$str = $val['faultString'];
if ($str->kindOf() != 'scalar' || $str->scalarTyp() != 'string') {
- return new Response(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
+ return new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
PhpXmlRpc::$xmlrpcstr['multicall_error'] . ": response element $i has invalid or no faultCode",
'xmlrpcvals', $result->httpResponse());
}
- $response[] = new Response(0, $code->scalarVal(), $str->scalarVal(), 'xmlrpcvals', $result->httpResponse());
+ $response[] = new static::$responseClass(0, $code->scalarVal(), $str->scalarVal(), 'xmlrpcvals', $result->httpResponse());
break;
default:
- return new Response(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
+ return new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['multicall_error'],
PhpXmlRpc::$xmlrpcstr['multicall_error'] . ": response element $i is not an array or struct",
'xmlrpcvals', $result->httpResponse());
}
const OPT_PHPVALS_ENCODING_OPTIONS = 'phpvals_encoding_options';
const OPT_RESPONSE_CHARSET_ENCODING = 'response_charset_encoding';
+ /** @var string */
+ protected static $responseClass = '\\PhpXmlRpc\\Response';
+
/**
* @var string
* Defines how functions in $dmap will be invoked: either using an xml-rpc Request object or plain php values.
$this->debugMsg("+++INFLATED REQUEST+++[" . strlen($data) . " chars]+++\n" . $data . "\n+++END+++");
}
} else {
- $r = new Response(0, PhpXmlRpc::$xmlrpcerr['server_decompress_fail'],
+ $r = new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['server_decompress_fail'],
PhpXmlRpc::$xmlrpcstr['server_decompress_fail'], '', array('raw_data' => $rawData)
);
return $r;
}
} else {
- $r = new Response(0, PhpXmlRpc::$xmlrpcerr['server_cannot_decompress'],
+ $r = new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['server_cannot_decompress'],
PhpXmlRpc::$xmlrpcstr['server_cannot_decompress'], '', array('raw_data' => $rawData)
);
$_xh = $xmlRpcParser->_xh;
}
} catch (NoSuchMethodException $e) {
- return new Response(0, $e->getCode(), $e->getMessage());
+ return new static::$responseClass(0, $e->getCode(), $e->getMessage());
}
if ($_xh['isf'] == 3) {
// (BC) we return XML error as a faultCode
preg_match('/^XML error ([0-9]+)/', $_xh['isf_reason'], $matches);
- return new Response(
+ return new static::$responseClass(
0,
PhpXmlRpc::$xmlrpcerrxml + (int)$matches[1],
$_xh['isf_reason']);
} elseif ($_xh['isf']) {
/// @todo separate better the various cases, as we have done in Request::parseResponse: invalid xml-rpc vs.
/// parsing error
- return new Response(
+ return new static::$responseClass(
0,
PhpXmlRpc::$xmlrpcerr['invalid_request'],
PhpXmlRpc::$xmlrpcstr['invalid_request'] . ' ' . $_xh['isf_reason']);
} else {
// build a Request object with data parsed from xml and add parameters in
$req = new Request($_xh['method']);
+ /// @todo for more speed, we could just pass in the array to the constructor (and loose the type validation)...
for ($i = 0; $i < count($_xh['params']); $i++) {
$req->addParam($_xh['params'][$i]);
}
if (!isset($dmap[$methodName]['function'])) {
// No such method
- return new Response(0, PhpXmlRpc::$xmlrpcerr['unknown_method'], PhpXmlRpc::$xmlrpcstr['unknown_method']);
+ return new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['unknown_method'], PhpXmlRpc::$xmlrpcstr['unknown_method']);
}
// Check signature
}
if (!$ok) {
// Didn't match.
- return new Response(
+ return new static::$responseClass(
0,
PhpXmlRpc::$xmlrpcerr['incorrect_params'],
PhpXmlRpc::$xmlrpcstr['incorrect_params'] . ": {$errStr}"
// verify that function to be invoked is in fact callable
if (!is_callable($func)) {
$this->getLogger()->error("XML-RPC: " . __METHOD__ . ": function '$funcName' registered as method handler is not callable");
- return new Response(
+ return new static::$responseClass(
0,
PhpXmlRpc::$xmlrpcerr['server_error'],
PhpXmlRpc::$xmlrpcstr['server_error'] . ": no function matches method"
if (!is_a($r, 'PhpXmlRpc\Response')) {
$this->getLogger()->error("XML-RPC: " . __METHOD__ . ": function '$funcName' registered as method handler does not return an xmlrpc response object but a " . gettype($r));
if (is_a($r, 'PhpXmlRpc\Value')) {
- $r = new Response($r);
+ $r = new static::$responseClass($r);
} else {
- $r = new Response(
+ $r = new static::$responseClass(
0,
PhpXmlRpc::$xmlrpcerr['server_error'],
PhpXmlRpc::$xmlrpcstr['server_error'] . ": function does not return xmlrpc response object"
$r = call_user_func_array($func, array($methodName, $params, $this->user_data));
// mimic EPI behaviour: if we get an array that looks like an error, make it an error response
if (is_array($r) && array_key_exists('faultCode', $r) && array_key_exists('faultString', $r)) {
- $r = new Response(0, (integer)$r['faultCode'], (string)$r['faultString']);
+ $r = new static::$responseClass(0, (integer)$r['faultCode'], (string)$r['faultString']);
} else {
// functions using EPI api should NOT return resp objects, so make sure we encode the
// return type correctly
$encoder = new Encoder();
- $r = new Response($encoder->encode($r, array('extension_api')));
+ $r = new static::$responseClass($encoder->encode($r, array('extension_api')));
}
} else {
$r = call_user_func_array($func, $params);
// q: what should we assume here about automatic encoding of datetimes and php classes instances?
// a: let the user decide
$encoder = new Encoder();
- $r = new Response($encoder->encode($r, $this->phpvals_encoding_options));
+ $r = new static::$responseClass($encoder->encode($r, $this->phpvals_encoding_options));
}
}
/// @todo bump minimum php version to 7.1 and use a single catch clause instead of the duplicate blocks
if ($errCode == 0) {
$errCode = PhpXmlRpc::$xmlrpcerr['server_error'];
}
- $r = new Response(0, $errCode, $e->getMessage());
+ $r = new static::$responseClass(0, $errCode, $e->getMessage());
break;
default:
- $r = new Response(0, PhpXmlRpc::$xmlrpcerr['server_error'], PhpXmlRpc::$xmlrpcstr['server_error']);
+ $r = new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['server_error'], PhpXmlRpc::$xmlrpcstr['server_error']);
}
} catch (\Error $e) {
// (barring errors in the lib) an uncaught exception happened in the called function, we wrap it in a
if ($errCode == 0) {
$errCode = PhpXmlRpc::$xmlrpcerr['server_error'];
}
- $r = new Response(0, $errCode, $e->getMessage());
+ $r = new static::$responseClass(0, $errCode, $e->getMessage());
break;
default:
- $r = new Response(0, PhpXmlRpc::$xmlrpcerr['server_error'], PhpXmlRpc::$xmlrpcstr['server_error']);
+ $r = new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['server_error'], PhpXmlRpc::$xmlrpcstr['server_error']);
}
}
public static function _xmlrpcs_getCapabilities($server, $req = null)
{
$encoder = new Encoder();
- return new Response($encoder->encode($server->getCapabilities()));
+ return new static::$responseClass($encoder->encode($server->getCapabilities()));
}
/**
$outAr[] = new Value($key, 'string');
}
- return new Response(new Value($outAr, 'array'));
+ return new static::$responseClass(new Value($outAr, 'array'));
}
/**
}
$sigs[] = new Value($curSig, 'array');
}
- $r = new Response(new Value($sigs, 'array'));
+ $r = new static::$responseClass(new Value($sigs, 'array'));
} else {
// NB: according to the official docs, we should be returning a
// "none-array" here, which means not-an-array
- $r = new Response(new Value('undef', 'string'));
+ $r = new static::$responseClass(new Value('undef', 'string'));
}
} else {
- $r = new Response(0, PhpXmlRpc::$xmlrpcerr['introspect_unknown'], PhpXmlRpc::$xmlrpcstr['introspect_unknown']);
+ $r = new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['introspect_unknown'], PhpXmlRpc::$xmlrpcstr['introspect_unknown']);
}
return $r;
}
if (isset($dmap[$methName])) {
if (isset($dmap[$methName]['docstring'])) {
- $r = new Response(new Value($dmap[$methName]['docstring'], 'string'));
+ $r = new static::$responseClass(new Value($dmap[$methName]['docstring'], 'string'));
} else {
- $r = new Response(new Value('', 'string'));
+ $r = new static::$responseClass(new Value('', 'string'));
}
} else {
- $r = new Response(0, PhpXmlRpc::$xmlrpcerr['introspect_unknown'], PhpXmlRpc::$xmlrpcstr['introspect_unknown']);
+ $r = new static::$responseClass(0, PhpXmlRpc::$xmlrpcerr['introspect_unknown'], PhpXmlRpc::$xmlrpcstr['introspect_unknown']);
}
return $r;
foreach ($params as $i => $param) {
if (!$req->addParam($param)) {
$i++; // for error message, we count params from 1
- return static::_xmlrpcs_multicall_error(new Response(0,
+ return static::_xmlrpcs_multicall_error(new static::$responseClass(0,
PhpXmlRpc::$xmlrpcerr['incorrect_params'],
PhpXmlRpc::$xmlrpcstr['incorrect_params'] . ": probable xml error in param " . $i));
}
}
}
- return new Response(new Value($result, 'array'));
+ return new static::$responseClass(new Value($result, 'array'));
}
/**