Skip to content

Commit

Permalink
Add support for i8
Browse files Browse the repository at this point in the history
  • Loading branch information
gggeek committed Jun 26, 2016
1 parent b0a92b1 commit b5d242c
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 27 deletions.
9 changes: 9 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
XML-RPC for PHP version 4.1.0 - 2016/6/26

* improved: Added support for receiving <I8> and <EX:I8> integers, sending <I8>

If php is compiled in 32 bit mode, and an i8 int is received from a 3rd party, and error will be emitted.
Integers sent from the library to 3rd parties can be encoded using the i8 tag, but default to using 'int' by default;
the developer will have to create values as i8 explicitly if needed.
The library does *not* check if an outgoing integer is too big to fit in 4 bytes and convert it to an i8 automatically.

XML-RPC for PHP version 4.0.1 - 2016/3/27

* improved: all of the API documentation has been moved out of the manual and into the source code phpdoc comments
Expand Down
8 changes: 6 additions & 2 deletions doc/manual/phpxmlrpc_manual.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -220,12 +220,16 @@ If you've benefited from the effort that has been put into writing this software

===== int

The type i4 and i8 are accepted as a synonym
The type i4 is accepted as a synonym
for int when creating xmlrpcval objects. The
xml parsing code will always convert i4 and i8 to
xml parsing code will always convert i4 to
int: int is regarded
by this implementation as the canonical name for this type.

The type i8 on the other hand is considered as a separate type.
Note that the library will never output integers as 'i8' on its own,
even when php is compiled in 64-bit mode.

===== base64

Base 64 encoding is performed transparently to the caller when
Expand Down
17 changes: 14 additions & 3 deletions src/Helper/XMLParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class XMLParser
'BOOLEAN' => array('VALUE'),
'I4' => array('VALUE'),
'I8' => array('VALUE'),
'EX:I8' => array('VALUE'),
'INT' => array('VALUE'),
'STRING' => array('VALUE'),
'DOUBLE' => array('VALUE'),
Expand Down Expand Up @@ -101,16 +102,25 @@ public function xmlrpc_se($parser, $name, $attrs, $acceptSingleVals = false)
$this->_xh['lv'] = 1;
$this->_xh['php_class'] = null;
break;
case 'I4':
case 'I8':
case 'EX:I8':
if (PHP_INT_SIZE === 4) {
/// INVALID ELEMENT: RAISE ISF so that it is later recognized!!!
$this->_xh['isf'] = 2;
$this->_xh['isf_reason'] = "Received i8 element but php is compiled in 32 bit mode";

return;
}
// fall through voluntarily
case 'I4':
case 'INT':
case 'STRING':
case 'BOOLEAN':
case 'DOUBLE':
case 'DATETIME.ISO8601':
case 'BASE64':
if ($this->_xh['vt'] != 'value') {
//two data elements inside a value: an error occurred!
// two data elements inside a value: an error occurred!
$this->_xh['isf'] = 2;
$this->_xh['isf_reason'] = "$name element following a {$this->_xh['vt']} element inside a single value";

Expand Down Expand Up @@ -262,6 +272,7 @@ public function xmlrpc_ee($parser, $name, $rebuildXmlrpcvals = true)
case 'BOOLEAN':
case 'I4':
case 'I8':
case 'EX:I8':
case 'INT':
case 'STRING':
case 'DOUBLE':
Expand Down Expand Up @@ -310,7 +321,7 @@ public function xmlrpc_ee($parser, $name, $rebuildXmlrpcvals = true)
$this->_xh['value'] = (double)$this->_xh['ac'];
}
} else {
// we have an I4/INT
// we have an I4/I8/INT
// we must check that only 0123456789-<space> are characters here
if (!preg_match('/^[+-]?[0123456789 \t]+$/', $this->_xh['ac'])) {
/// @todo find a better way of throwing an error than this!
Expand Down
2 changes: 1 addition & 1 deletion src/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ protected function verifySignature($in, $sigs)
$pt = $p->kindOf();
}
} else {
$pt = ($in[$n] == 'i4' || $in[$n] == 'i8') ? 'int' : strtolower($in[$n]); // dispatch maps never use i4...
$pt = ($in[$n] == 'i4') ? 'int' : strtolower($in[$n]); // dispatch maps never use i4...
}

// param index is $n+1, as first member of sig is return type
Expand Down
15 changes: 5 additions & 10 deletions src/Value.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public function addScalar($val, $type = 'string')
}

// coerce booleans into correct values
// NB: we should either do it for datetimes, integers and doubles, too,
// NB: we should either do it for datetimes, integers, i8 and doubles, too,
// or just plain remove this check, implemented on booleans only...
if ($type == static::$xmlrpcBoolean) {
if (strcasecmp($val, 'true') == 0 || $val == 1 || ($val == true && strcasecmp($val, 'false'))) {
Expand Down Expand Up @@ -329,14 +329,10 @@ protected function serializedata($typ, $val, $charsetEncoding = '')
*/
public function serialize($charsetEncoding = '')
{
// add check? slower, but helps to avoid recursion in serializing broken xmlrpc values...
//if (is_object($o) && (get_class($o) == 'xmlrpcval' || is_subclass_of($o, 'xmlrpcval')))
//{
reset($this->me);
list($typ, $val) = each($this->me);

return '<value>' . $this->serializedata($typ, $val, $charsetEncoding) . "</value>\n";
//}
}

/**
Expand Down Expand Up @@ -407,15 +403,15 @@ public function scalarval()
/**
* Returns the type of the xmlrpc value.
*
* For integers, 'int' is always returned in place of 'i4' or 'i8'.
* For integers, 'int' is always returned in place of 'i4'. 'i8' is considered a separate type and returned as such
*
* @return string
*/
public function scalartyp()
{
reset($this->me);
list($a,) = each($this->me);
if ($a == static::$xmlrpcI4 || $a == static::$xmlrpcI8) {
if ($a == static::$xmlrpcI4) {
$a = static::$xmlrpcInt;
}

Expand Down Expand Up @@ -501,7 +497,6 @@ public function getIterator() {
return new \ArrayIterator();
}


public function offsetSet($offset, $value) {

switch ($this->mytype) {
Expand All @@ -528,7 +523,7 @@ public function offsetSet($offset, $value) {
}
return;
case 1:
// todo: handle i4/i8 vs int
// todo: handle i4 vs int
reset($this->me);
list($type,) = each($this->me);
if ($type != $offset) {
Expand All @@ -549,7 +544,7 @@ public function offsetExists($offset) {
case 2:
return isset($this->me['array'][$offset]);
case 1:
// todo: handle i4/i8 vs int
// todo: handle i4 vs int
return $offset == $this->scalartyp();
default:
return false;
Expand Down
60 changes: 49 additions & 11 deletions tests/1ParsingBugsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,18 @@ public function testValidNumbers()
<value><int>01</int></value>
</member>
<member>
<name>float1</name>
<value><double>01.10</double></value>
</member>
<member>
<name>integer2</name>
<value><int>+1</int></value>
</member>
<member>
<name>integer3</name>
<value><i4>1</i4></value>
</member>
<member>
<name>float1</name>
<value><double>01.10</double></value>
</member>
<member>
<name>float2</name>
<value><double>+1.10</double></value>
</member>
Expand All @@ -139,15 +143,49 @@ public function testValidNumbers()
$r = $m->parseResponse($fp);
$v = $r->value();
$s = $v->structmem('integer1');
$t = $v->structmem('float1');
$u = $v->structmem('integer2');
$w = $v->structmem('float2');
$x = $v->structmem('float3');
$t = $v->structmem('integer2');
$u = $v->structmem('integer3');
$x = $v->structmem('float1');
$y = $v->structmem('float2');
$z = $v->structmem('float3');
$this->assertEquals(1, $s->scalarval());
$this->assertEquals(1.1, $t->scalarval());
$this->assertEquals(1, $t->scalarval());
$this->assertEquals(1, $u->scalarval());
$this->assertEquals(1.1, $w->scalarval());
$this->assertEquals(-110.0, $x->scalarval());

$this->assertEquals(1.1, $x->scalarval());
$this->assertEquals(1.1, $y->scalarval());
$this->assertEquals(-110.0, $z->scalarval());
}

public function testI8()
{
if (PHP_INT_SIZE == 4 ) {
$this->markTestSkipped('did not find a locale which sets decimal separator to comma');
return;
}

$m = $this->newMsg('dummy');
$fp =
'<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value>
<struct>
<member>
<name>integer1</name>
<value><i8>1</i8></value>
</member>
</member>
</struct>
</value>
</param>
</params>
</methodResponse>';
$r = $m->parseResponse($fp);
$v = $r->value();
$s = $v->structmem('integer1');
$this->assertEquals(1, $s->scalarval());
}

public function testAddScalarToStruct()
Expand Down

0 comments on commit b5d242c

Please sign in to comment.