Skip to content

Commit 3b8cead

Browse files
onligarvinhicking
andauthored
XML/RPC: Fix spl_object_hash parser conversion (#875)
* Replace (int) parser conversion with spl_object_hash The (int) conversion does not work anymore since PHP 8 changed the xml parser from being a resource to being an object. Hardcoding it to a number, the initial fix, destroys the logic of having multiple parsers available and was not done everywhere. The object hash approach should be a valid replacement. * Add test for XML_RPC_Message * Add test for XML_RPC_Response, when valid * Add test for invalid XML_Response, simplify code * Fix $message access * Try test fix for PHP 7.4 * Try test for PHP 7.4, LANG-CHARSET missing * PHP 7.4 bc fix for XML_PARSER hash * Try PHP 7.4 'ha' fix * Try fix for undefined 'ha' index * Use ?? check for legibility Co-authored-by: Garvin Hicking <blog@garv.in> --------- Co-authored-by: Garvin Hicking <blog@garv.in>
1 parent 9859f6b commit 3b8cead

File tree

3 files changed

+85
-7
lines changed

3 files changed

+85
-7
lines changed

bundled-libs/XML/RPC.php

+7-5
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ function XML_RPC_se($parser_resource, $name, $attrs)
245245
{
246246
global $XML_RPC_xh, $XML_RPC_valid_parents;
247247

248-
$parser = (int) $parser_resource;
248+
$parser = is_resource($parser_resource) ? ((int) $parser_resource) : spl_object_hash($parser_resource);
249249

250250
// if invalid xmlrpc already detected, skip all processing
251251
if ($XML_RPC_xh[$parser]['isf'] >= 2) {
@@ -374,7 +374,7 @@ function XML_RPC_ee($parser_resource, $name)
374374
{
375375
global $XML_RPC_xh;
376376

377-
$parser = (int) $parser_resource;
377+
$parser = is_resource($parser_resource) ? ((int) $parser_resource) : spl_object_hash($parser_resource);
378378

379379
if ($XML_RPC_xh[$parser]['isf'] >= 2) {
380380
return;
@@ -511,7 +511,7 @@ function XML_RPC_cd($parser_resource, $data)
511511
{
512512
global $XML_RPC_xh, $XML_RPC_backslash;
513513

514-
$parser = (int) $parser_resource;
514+
$parser = is_resource($parser_resource) ? ((int) $parser_resource) : spl_object_hash($parser_resource);
515515

516516
if ($XML_RPC_xh[$parser]['lv'] != 3) {
517517
// "lookforvalue==3" means that we've found an entire value
@@ -1433,7 +1433,9 @@ function parseResponse($data = '')
14331433

14341434
$encoding = $this->getEncoding($data);
14351435
$parser_resource = xml_parser_create($encoding);
1436-
$parser = 1;
1436+
# xml_parser_create returns a resource before PHP 8, an object later. Only a resource can be
1437+
# casted to int
1438+
$parser = is_resource($parser_resource) ? ((int) $parser_resource) : spl_object_hash($parser_resource);
14371439

14381440
$XML_RPC_xh = array();
14391441
$XML_RPC_xh[$parser] = array();
@@ -1530,7 +1532,7 @@ function parseResponse($data = '')
15301532
$r = new XML_RPC_Response($v);
15311533
}
15321534
}
1533-
$r->hdrs = preg_split("@\r?\n@", $XML_RPC_xh[$parser]['ha']);
1535+
$r->hdrs = preg_split("@\r?\n@", $XML_RPC_xh[$parser]['ha'] ?? '');
15341536
return $r;
15351537
}
15361538
}

tests/include/bundledLibsTest.php

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
@define('S9Y_PEAR_PATH', dirname(__FILE__) . '/../../bundled-libs/');
4+
@define('IN_serendipity', true);
5+
@define('LANG_CHARSET', 'UTF-8');
6+
require_once dirname(__FILE__) . '/../../include/compat.inc.php';
7+
if (!class_exists('XML_RPC_Base')) {
8+
include_once(S9Y_PEAR_PATH . "XML/RPC.php");
9+
}
10+
11+
use PHPUnit\Framework\Attributes\Test;
12+
13+
class bundledLibsTest extends PHPUnit\Framework\TestCase {
14+
var $message = null;
15+
16+
protected function setUp(): void {
17+
$args = array(
18+
new XML_RPC_Value(
19+
'testA',
20+
'string'
21+
),
22+
new XML_RPC_Value(
23+
'testB',
24+
'string'
25+
)
26+
);
27+
$this->message = new XML_RPC_Message(
28+
'weblogUpdates.ping',
29+
$args
30+
);
31+
$this->message->createPayload();
32+
}
33+
34+
#[Test]
35+
public function test_serendipity_xml_rpc_message()
36+
{
37+
$expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r
38+
<methodCall>\r
39+
<methodName>weblogUpdates.ping</methodName>\r
40+
<params>\r
41+
<param>\r
42+
<value><string>testA</string></value>\r
43+
</param>\r
44+
<param>\r
45+
<value><string>testB</string></value>\r
46+
</param>\r
47+
</params>\r
48+
</methodCall>\r
49+
";
50+
$this->assertEquals($expected, $this->message->payload);
51+
}
52+
53+
#[Test]
54+
public function test_serendipity_xml_rpc_response_valid()
55+
{
56+
$example_response = "<methodResponse>
57+
<params>
58+
<param>
59+
<value><string>Success!</string></value>
60+
</param>
61+
</params>
62+
</methodResponse>";
63+
64+
$xmlrpc_result = $this->message->parseResponse($example_response);
65+
$this->assertEquals($example_response, $xmlrpc_result->serialize());
66+
}
67+
#[Test]
68+
public function test_serendipity_xml_rpc_response_invalid()
69+
{
70+
$example_response = "some non-xml response";
71+
72+
$xmlrpc_result = $this->message->parseResponse($example_response);
73+
$this->assertEquals(2, $xmlrpc_result->faultCode());
74+
}
75+
76+
}

tests/include/functionsTest.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?php
22

33
$serendipity['dbType'] = 'pdo-sqlite';
4-
define('IN_serendipity', true);
5-
define('S9Y_INCLUDE_PATH', dirname(__FILE__) . '/../../');
4+
@define('IN_serendipity', true);
5+
@define('S9Y_INCLUDE_PATH', dirname(__FILE__) . '/../../');
66
require_once dirname(__FILE__) . '/../../include/functions.inc.php';
77

88
use PHPUnit\Framework\Attributes\DataProvider;

0 commit comments

Comments
 (0)