All php classes have been renamed and moved to separate files.
Class autoloading can now be done in accord with the PSR-4 standard.
All global variables and global functions have been removed.
+ Iterating over xmlrpc value objects is now easier thank to support for ArrayAccess and Traversable interfaces.
Backward compatibility is maintained via lib/xmlrpc.inc, lib/xmlrpcs.inc and lib/xmlrpc_wrappers.inc.
For more details, head on to doc/api_changes_v4.md
$max = $v->count();
echo "<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n";
echo "<thead>\n<tr><th>Method ($max)</th><th>Description</th></tr>\n</thead>\n<tbody>\n";
- for ($i = 0; $i < $max; $i++) {
- $rec = $v->arraymem($i);
+ //for ($i = 0; $i < $max; $i++) {
+ foreach($v as $i => $rec) {
+ //$rec = $v->arraymem($i);
if ($i % 2) {
$class = ' class="oddrow"';
} else {
if ($r2->kindOf() != "array") {
echo "<tr><td class=\"oddrow\">Signature</td><td class=\"oddrow\">Unknown</td><td class=\"oddrow\"> </td></tr>\n";
} else {
- for ($i = 0; $i < $r2->arraysize(); $i++) {
+ //for ($i = 0; $i < $r2->arraysize(); $i++) {
+ foreach($r2 as $i => $x) {
$payload = "";
$alt_payload = "";
if ($i + 1 % 2) {
$class = ' class="evenrow"';
}
echo "<tr><td$class>Signature " . ($i + 1) . "</td><td$class>";
- $x = $r2->arraymem($i);
+ //$x = $r2->arraymem($i);
if ($x->kindOf() == "array") {
- $ret = $x->arraymem(0);
+ //$ret = $x->arraymem(0);
+ $ret = $x[0];
echo "<code>OUT: " . htmlspecialchars($ret->scalarval(), ENT_COMPAT, \PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding) . "<br />IN: (";
if ($x->count() > 1) {
- for ($k = 1; $k < $x->arraysize(); $k++) {
- $y = $x->arraymem($k);
+ foreach($x as $k => $y) {
+ if ($k == 0) continue;
+ //for ($k = 1; $k < $x->arraysize(); $k++) {
+ //$y = $x->arraymem($k);
echo htmlspecialchars($y->scalarval(), ENT_COMPAT, \PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding);
if ($wstype != 1) {
$type = $y->scalarval();
print "The server gave me these results:<pre>";
$value = $resp->value();
foreach ($value as $struct) {
- $name = $struct->structmem("name");
- $age = $struct->structmem("age");
+ //$name = $struct->structmem("name");
+ $name = $struct["name"];
+ //$age = $struct->structmem("age");
+ $age = $struct["age"];
print htmlspecialchars($name->scalarval()) . ", " . htmlspecialchars($age->scalarval()) . "\n";
}
$val = $rs[1]->value();
if ($val->kindOf() == "array") {
foreach ($val as $x) {
- $ret = $x->arraymem(0);
+ //$ret = $x->arraymem(0);
+ $ret = $x[0];
print "<code>" . $ret->scalarval() . " "
. $methodName->scalarval() . "(";
if ($x->count() > 1) {
for ($k = 1; $k < $x->count(); $k++) {
- $y = $x->arraymem($k);
+ //$y = $x->arraymem($k);
+ $y = $x[$k];
print $y->scalarval();
if ($k < $x->count() - 1) {
print ", ";
{
$ar = $req->getParam(0);
$sz = $ar->count();
- $first = $ar->arraymem(0);
- $last = $ar->arraymem($sz - 1);
+ //$first = $ar->arraymem(0);
+ $first = $ar[0];
+ //$last = $ar->arraymem($sz - 1);
+ $last = $ar[$sz - 1];
return new PhpXmlRpc\Response(new Value($first->scalarval() .
$last->scalarval(), "string"));
implementation clashes with the new one if you implemented:
-| Class | Method | Notes |
-| --------- | ----------- | --------------------------------------- |
-| xmlrpcval | count | implements interface: Countable |
-| xmlrpcval | getIterator | implements interface: IteratorAggregate |
+| Class | Method | Notes |
+| --------- | ------------ | --------------------------------------- |
+| xmlrpcval | count | implements interface: Countable |
+| xmlrpcval | getIterator | implements interface: IteratorAggregate |
+| xmlrpcval | offsetExists | implements interface: ArrayAccess |
+| xmlrpcval | offsetGet | implements interface: ArrayAccess |
+| xmlrpcval | offsetSet | implements interface: ArrayAccess |
+| xmlrpcval | offsetUnset | implements interface: ArrayAccess |
Global variables cleanup
The default character set used by the library to deliver data to your app is now UTF8.
It is also the character set that the library expects data from your app to be in (including method names).
-The value can be changed (to either US-ASCII or ISO-8859-1) by setting teh desired value to
+The value can be changed (to either US-ASCII or ISO-8859-1) by setting the desired value to
PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding
Usage of closures for wrapping
$this->proxyport,
$this->proxy_user,
$this->proxy_pass,
- $this->proxy_authtype
+ $this->proxy_authtype,
+ $method
);
}
* @param string $proxyUsername
* @param string $proxyPassword
* @param int $proxyAuthType
+ * @param string $method
* @return Response
*/
protected function sendPayloadHTTP10($req, $server, $port, $timeout = 0,
$username = '', $password = '', $authType = 1, $proxyHost = '',
- $proxyPort = 0, $proxyUsername = '', $proxyPassword = '', $proxyAuthType = 1)
+ $proxyPort = 0, $proxyUsername = '', $proxyPassword = '', $proxyAuthType = 1,
+ $method='http')
{
if ($port == 0) {
- $port = 80;
+ $port = ( $method === "https" ) ? 443 : 80;
}
// Only create the payload if it was not created previously
}
$connectServer = $proxyHost;
$connectPort = $proxyPort;
+ $transport = "tcp";
$uri = 'http://' . $server . ':' . $port . $this->path;
if ($proxyUsername != '') {
if ($proxyAuthType != 1) {
} else {
$connectServer = $server;
$connectPort = $port;
+ /// @todo if supporting https, we should support all its current options as well: peer name verification etc...
+ $transport = ( $method === "https" ) ? "tls" : "tcp";
$uri = $this->path;
}
}
if ($timeout > 0) {
- $fp = @fsockopen($connectServer, $connectPort, $this->errno, $this->errstr, $timeout);
+ $fp = @stream_socket_client("$transport://$connectServer:$connectPort", $this->errno, $this->errstr, $timeout);
} else {
- $fp = @fsockopen($connectServer, $connectPort, $this->errno, $this->errstr);
+ $fp = @stream_socket_client("$transport://$connectServer:$connectPort", $this->errno, $this->errstr);
}
if ($fp) {
- if ($timeout > 0 && function_exists('stream_set_timeout')) {
+ if ($timeout > 0) {
stream_set_timeout($fp, $timeout);
}
} else {
}
$response = array();
- for ($i = 0; $i < $numRets; $i++) {
- $val = $rets->arraymem($i);
+ //for ($i = 0; $i < $numRets; $i++) {
+ foreach($rets as $val) {
+ //$val = $rets->arraymem($i);
switch ($val->kindOf()) {
case 'array':
if ($val->count() != 1) {
return false; // Bad value
}
// Normal return value
- $response[$i] = new Response($val->arraymem(0));
+ //$response[] = new Response($val->arraymem(0));
+ $response[] = new Response($val[0]);
break;
case 'struct':
- $code = $val->structmem('faultCode');
+ //$code = $val->structmem('faultCode');
+ $code = $val['faultCode'];
if ($code->kindOf() != 'scalar' || $code->scalartyp() != 'int') {
return false;
}
- $str = $val->structmem('faultString');
+ //$str = $val->structmem('faultString');
+ $str = $val['faultString'];
if ($str->kindOf() != 'scalar' || $str->scalartyp() != 'string') {
return false;
}
- $response[$i] = new Response(0, $code->scalarval(), $str->scalarval());
+ $response[] = new Response(0, $code->scalarval(), $str->scalarval());
break;
default:
return false;
return $xmlrpcVal->scalarval();
case 'array':
- $size = $xmlrpcVal->count();
+ //$size = $xmlrpcVal->count();
$arr = array();
- for ($i = 0; $i < $size; $i++) {
- $arr[] = $this->decode($xmlrpcVal->arraymem($i), $options);
+ //for ($i = 0; $i < $size; $i++) {
+ foreach($xmlrpcVal as $value) {
+ //$arr[] = $this->decode($xmlrpcVal->arraymem($i), $options);
+ $arr[] = $this->decode($value, $options);
}
return $arr;
case 'methodresponse':
$v = &$xmlRpcParser->_xh['value'];
if ($xmlRpcParser->_xh['isf'] == 1) {
- $vc = $v->structmem('faultCode');
- $vs = $v->structmem('faultString');
+ //$vc = $v->structmem('faultCode');
+ //$vs = $v->structmem('faultString');
+ $vc = $v['faultCode'];
+ $vs = $v['faultString'];
$r = new Response(0, $vc->scalarval(), $vs->scalarval());
} else {
$r = new Response($v);
if ($xmlRpcParser->_xh['isf']) {
/// @todo we should test here if server sent an int and a string, and/or coerce them into such...
if ($returnType == 'xmlrpcvals') {
- $errNo_v = $v->structmem('faultCode');
- $errStr_v = $v->structmem('faultString');
+ //$errNo_v = $v->structmem('faultCode');
+ //$errStr_v = $v->structmem('faultString');
+ $errNo_v = $v['faultCode'];
+ $errStr_v = $v['faultString'];
$errNo = $errNo_v->scalarval();
$errStr = $errStr_v->scalarval();
} else {
if ($call->kindOf() != 'struct') {
return static::_xmlrpcs_multicall_error('notstruct');
}
- $methName = @$call->structmem('methodName');
+ //$methName = $call->structmem('methodName');
+ $methName = @$call['methodName'];
if (!$methName) {
return static::_xmlrpcs_multicall_error('nomethod');
}
return static::_xmlrpcs_multicall_error('recursion');
}
- $params = @$call->structmem('params');
+ //$params = @$call->structmem('params');
+ $params = @$call['params'];
if (!$params) {
return static::_xmlrpcs_multicall_error('noparams');
}
if ($params->kindOf() != 'array') {
return static::_xmlrpcs_multicall_error('notarray');
}
- $numParams = $params->count();
+ //$numParams = $params->count();
$req = new Request($methName->scalarval());
- for ($i = 0; $i < $numParams; $i++) {
- if (!$req->addParam($params->arraymem($i))) {
- $i++;
-
+ //for ($i = 0; $i < $numParams; $i++) {
+ foreach($params as $i => $param) {
+ //if (!$req->addParam($params->arraymem($i))) {
+ if (!$req->addParam($param)) {
+ $i++; // for error message, we count params from 1
return static::_xmlrpcs_multicall_error(new Response(0,
PhpXmlRpc::$xmlrpcerr['incorrect_params'],
PhpXmlRpc::$xmlrpcstr['incorrect_params'] . ": probable xml error in param " . $i));
// let accept a plain list of php parameters, beside a single xmlrpc msg object
if (is_object($req)) {
$calls = $req->getParam(0);
- $numCalls = $calls->count();
- for ($i = 0; $i < $numCalls; $i++) {
- $call = $calls->arraymem($i);
- $result[$i] = static::_xmlrpcs_multicall_do_call($server, $call);
+ //$numCalls = $calls->count();
+ //for ($i = 0; $i < $numCalls; $i++) {
+ foreach($calls as $call) {
+ //$call = $calls->arraymem($i);
+ $result[] = static::_xmlrpcs_multicall_do_call($server, $call);
}
} else {
$numCalls = count($req);
use PhpXmlRpc\Helper\Charset;
-class Value implements \Countable, \IteratorAggregate
+class Value implements \Countable, \IteratorAggregate, \ArrayAccess
{
public static $xmlrpcI4 = "i4";
public static $xmlrpcInt = "int";
* @param string $key the name of the struct member to be looked up
*
* @return boolean
+ *
+ * @deprecated use array access, e.g. isset($val[$key])
*/
public function structmemexists($key)
{
* @param string $key the name of the struct member to be looked up
*
* @return Value
+ *
+ * @deprecated use array access, e.g. $val[$key]
*/
public function structmem($key)
{
* @param integer $key the index of the value to be retrieved (zero based)
*
* @return Value
+ *
+ * @deprecated use array access, e.g. $val[$key]
*/
public function arraymem($key)
{
{
switch ($this->mytype) {
case 3:
- count($this->me['struct']);
+ return count($this->me['struct']);
case 2:
return count($this->me['array']);
case 1:
}
return new \ArrayIterator();
}
+
+
+ public function offsetSet($offset, $value) {
+
+ switch ($this->mytype) {
+ case 3:
+ if (!($value instanceof \PhpXmlRpc\Value)) {
+ throw new \Exception('It is only possible to add Value objects to an XML-RPC Struct');
+ }
+ if (is_null($offset)) {
+ // disallow struct members with empty names
+ throw new \Exception('It is not possible to add anonymous members to an XML-RPC Struct');
+ } else {
+ $this->me['struct'][$offset] = $value;
+ }
+ return;
+ case 2:
+ if (!($value instanceof \PhpXmlRpc\Value)) {
+ throw new \Exception('It is only possible to add Value objects to an XML-RPC Array');
+ }
+ if (is_null($offset)) {
+ $this->me['array'][] = $value;
+ } else {
+ // nb: we are not checking that $offset is above the existing array range...
+ $this->me['array'][$offset] = $value;
+ }
+ return;
+ case 1:
+// todo: handle i4 vs int
+ reset($this->me);
+ list($type,) = each($this->me);
+ if ($type != $offset) {
+ throw new \Exception('');
+ }
+ $this->me[$type] = $value;
+ return;
+ default:
+ // it would be nice to allow empty values to be be turned into non-empty ones this way, but we miss info to do so
+ throw new \Exception("XML-RPC Value is of type 'undef' and its value can not be set using array index");
+ }
+ }
+
+ public function offsetExists($offset) {
+ switch ($this->mytype) {
+ case 3:
+ return isset($this->me['struct'][$offset]);
+ case 2:
+ return isset($this->me['array'][$offset]);
+ case 1:
+// todo: handle i4 vs int
+ return $offset == $this->scalartyp();
+ default:
+ return false;
+ }
+ }
+
+ public function offsetUnset($offset) {
+ switch ($this->mytype) {
+ case 3:
+ unset($this->me['struct'][$offset]);
+ return;
+ case 2:
+ unset($this->me['array'][$offset]);
+ return;
+ case 1:
+ // can not remove value from a scalar
+ throw new \Exception("XML-RPC Value is of type 'scalar' and its value can not be unset using array index");
+ default:
+ throw new \Exception("XML-RPC Value is of type 'undef' and its value can not be unset using array index");
+ }
+ }
+
+ public function offsetGet($offset) {
+ switch ($this->mytype) {
+ case 3:
+ return isset($this->me['struct'][$offset]) ? $this->me['struct'][$offset] : null;
+ case 2:
+ return isset($this->me['array'][$offset]) ? $this->me['array'][$offset] : null;
+ case 1:
+// on bad type: null or exception?
+ reset($this->me);
+ list($type, $value) = each($this->me);
+ return $type == $offset ? $value : null;
+ default:
+// return null or exception?
+ throw new \Exception("XML-RPC Value is of type 'undef' and can not be accessed using array index");
+ }
+ }
}
\ No newline at end of file