Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes the compatibility of XML-RPC library with PHP 8 #6264

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 77 additions & 84 deletions system/libraries/Xmlrpc.php
Original file line number Diff line number Diff line change
Expand Up @@ -1151,8 +1151,7 @@ public function parseResponse($fp)
//-------------------------------------

$parser = xml_parser_create($this->xmlrpc_defencoding);
$pname = (string) $parser;
$this->xh[$pname] = array(
$this->xh = array(
'isf' => 0,
'ac' => '',
'headers' => array(),
Expand All @@ -1175,7 +1174,7 @@ public function parseResponse($fp)
{
break;
}
$this->xh[$pname]['headers'][] = $line;
$this->xh['headers'][] = $line;
}
$data = implode("\r\n", $lines);

Expand All @@ -1193,43 +1192,43 @@ public function parseResponse($fp)
xml_parser_free($parser);

// Got ourselves some badness, it seems
if ($this->xh[$pname]['isf'] > 1)
if ($this->xh['isf'] > 1)
{
if ($this->debug === TRUE)
{
echo "---Invalid Return---\n".$this->xh[$pname]['isf_reason']."---Invalid Return---\n\n";
echo "---Invalid Return---\n".$this->xh['isf_reason']."---Invalid Return---\n\n";
}

return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['isf_reason']);
return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh['isf_reason']);
}
elseif ( ! is_object($this->xh[$pname]['value']))
elseif ( ! is_object($this->xh['value']))
{
return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['isf_reason']);
return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh['isf_reason']);
}

// Display XML content for debugging
if ($this->debug === TRUE)
{
echo '<pre>';

if (count($this->xh[$pname]['headers']) > 0)
if (count($this->xh['headers']) > 0)
{
echo "---HEADERS---\n";
foreach ($this->xh[$pname]['headers'] as $header)
foreach ($this->xh['headers'] as $header)
{
echo $header."\n";
}
echo "---END HEADERS---\n\n";
}

echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n---PARSED---\n";
var_dump($this->xh[$pname]['value']);
var_dump($this->xh['value']);
echo "\n---END PARSED---</pre>";
}

// Send response
$v = $this->xh[$pname]['value'];
if ($this->xh[$pname]['isf'])
$v = $this->xh['value'];
if ($this->xh['isf'])
{
$errno_v = $v->me['struct']['faultCode'];
$errstr_v = $v->me['struct']['faultString'];
Expand All @@ -1248,7 +1247,7 @@ public function parseResponse($fp)
$r = new XML_RPC_Response($v);
}

$r->headers = $this->xh[$pname]['headers'];
$r->headers = $this->xh['headers'];
return $r;
}

Expand Down Expand Up @@ -1279,26 +1278,24 @@ public function parseResponse($fp)
*/
public function open_tag($the_parser, $name)
{
$the_parser = (string) $the_parser;

// If invalid nesting, then return
if ($this->xh[$the_parser]['isf'] > 1) return;
if ($this->xh['isf'] > 1) return;

// Evaluate and check for correct nesting of XML elements
if (count($this->xh[$the_parser]['stack']) === 0)
if (count($this->xh['stack']) === 0)
{
if ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')
{
$this->xh[$the_parser]['isf'] = 2;
$this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
$this->xh['isf'] = 2;
$this->xh['isf_reason'] = 'Top level XML-RPC element is missing';
return;
}
}
// not top level element: see if parent is OK
elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
elseif ( ! in_array($this->xh['stack'][0], $this->valid_parents[$name], TRUE))
{
$this->xh[$the_parser]['isf'] = 2;
$this->xh[$the_parser]['isf_reason'] = 'XML-RPC element '.$name.' cannot be child of '.$this->xh[$the_parser]['stack'][0];
$this->xh['isf'] = 2;
$this->xh['isf_reason'] = 'XML-RPC element '.$name.' cannot be child of '.$this->xh['stack'][0];
return;
}

Expand All @@ -1308,22 +1305,22 @@ public function open_tag($the_parser, $name)
case 'ARRAY':
// Creates array for child elements
$cur_val = array('value' => array(), 'type' => $name);
array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
array_unshift($this->xh['valuestack'], $cur_val);
break;
case 'METHODNAME':
case 'NAME':
$this->xh[$the_parser]['ac'] = '';
$this->xh['ac'] = '';
break;
case 'FAULT':
$this->xh[$the_parser]['isf'] = 1;
$this->xh['isf'] = 1;
break;
case 'PARAM':
$this->xh[$the_parser]['value'] = NULL;
$this->xh['value'] = NULL;
break;
case 'VALUE':
$this->xh[$the_parser]['vt'] = 'value';
$this->xh[$the_parser]['ac'] = '';
$this->xh[$the_parser]['lv'] = 1;
$this->xh['vt'] = 'value';
$this->xh['ac'] = '';
$this->xh['lv'] = 1;
break;
case 'I4':
case 'INT':
Expand All @@ -1332,23 +1329,23 @@ public function open_tag($the_parser, $name)
case 'DOUBLE':
case 'DATETIME.ISO8601':
case 'BASE64':
if ($this->xh[$the_parser]['vt'] !== 'value')
if ($this->xh['vt'] !== 'value')
{
//two data elements inside a value: an error occurred!
$this->xh[$the_parser]['isf'] = 2;
$this->xh[$the_parser]['isf_reason'] = 'There is a '.$name.' element following a '
.$this->xh[$the_parser]['vt'].' element inside a single value';
$this->xh['isf'] = 2;
$this->xh['isf_reason'] = 'There is a '.$name.' element following a '
.$this->xh['vt'].' element inside a single value';
return;
}

$this->xh[$the_parser]['ac'] = '';
$this->xh['ac'] = '';
break;
case 'MEMBER':
// Set name of <member> to nothing to prevent errors later if no <name> is found
$this->xh[$the_parser]['valuestack'][0]['name'] = '';
$this->xh['valuestack'][0]['name'] = '';

// Set NULL value to check to see if value passed for this param/member
$this->xh[$the_parser]['value'] = NULL;
$this->xh['value'] = NULL;
break;
case 'DATA':
case 'METHODCALL':
Expand All @@ -1358,15 +1355,15 @@ public function open_tag($the_parser, $name)
break;
default:
/// An Invalid Element is Found, so we have trouble
$this->xh[$the_parser]['isf'] = 2;
$this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;
$this->xh['isf'] = 2;
$this->xh['isf_reason'] = 'Invalid XML-RPC element found: '.$name;
break;
}

// Add current element name to stack, to allow validation of nesting
array_unshift($this->xh[$the_parser]['stack'], $name);
array_unshift($this->xh['stack'], $name);

$name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;
$name === 'VALUE' OR $this->xh['lv'] = 0;
}

// --------------------------------------------------------------------
Expand All @@ -1380,27 +1377,25 @@ public function open_tag($the_parser, $name)
*/
public function closing_tag($the_parser, $name)
{
$the_parser = (string) $the_parser;

if ($this->xh[$the_parser]['isf'] > 1) return;
if ($this->xh['isf'] > 1) return;

// Remove current element from stack and set variable
// NOTE: If the XML validates, then we do not have to worry about
// the opening and closing of elements. Nesting is checked on the opening
// tag so we be safe there as well.

$curr_elem = array_shift($this->xh[$the_parser]['stack']);
$curr_elem = array_shift($this->xh['stack']);

switch ($name)
{
case 'STRUCT':
case 'ARRAY':
$cur_val = array_shift($this->xh[$the_parser]['valuestack']);
$this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();
$this->xh[$the_parser]['vt'] = strtolower($name);
$cur_val = array_shift($this->xh['valuestack']);
$this->xh['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();
$this->xh['vt'] = strtolower($name);
break;
case 'NAME':
$this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
$this->xh['valuestack'][0]['name'] = $this->xh['ac'];
break;
case 'BOOLEAN':
case 'I4':
Expand All @@ -1409,87 +1404,87 @@ public function closing_tag($the_parser, $name)
case 'DOUBLE':
case 'DATETIME.ISO8601':
case 'BASE64':
$this->xh[$the_parser]['vt'] = strtolower($name);
$this->xh['vt'] = strtolower($name);

if ($name === 'STRING')
{
$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
$this->xh['value'] = $this->xh['ac'];
}
elseif ($name === 'DATETIME.ISO8601')
{
$this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime;
$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
$this->xh['vt'] = $this->xmlrpcDateTime;
$this->xh['value'] = $this->xh['ac'];
}
elseif ($name === 'BASE64')
{
$this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
$this->xh['value'] = base64_decode($this->xh['ac']);
}
elseif ($name === 'BOOLEAN')
{
// Translated BOOLEAN values to TRUE AND FALSE
$this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];
$this->xh['value'] = (bool) $this->xh['ac'];
}
elseif ($name=='DOUBLE')
{
// we have a DOUBLE
// we must check that only 0123456789-.<space> are characters here
$this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])
? (float) $this->xh[$the_parser]['ac']
$this->xh['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh['ac'])
? (float) $this->xh['ac']
: 'ERROR_NON_NUMERIC_FOUND';
}
else
{
// we have an I4/INT
// we must check that only 0123456789-<space> are characters here
$this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])
? (int) $this->xh[$the_parser]['ac']
$this->xh['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh['ac'])
? (int) $this->xh['ac']
: 'ERROR_NON_NUMERIC_FOUND';
}
$this->xh[$the_parser]['ac'] = '';
$this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
$this->xh['ac'] = '';
$this->xh['lv'] = 3; // indicate we've found a value
break;
case 'VALUE':
// This if() detects if no scalar was inside <VALUE></VALUE>
if ($this->xh[$the_parser]['vt'] == 'value')
if ($this->xh['vt'] == 'value')
{
$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
$this->xh[$the_parser]['vt'] = $this->xmlrpcString;
$this->xh['value'] = $this->xh['ac'];
$this->xh['vt'] = $this->xmlrpcString;
}

// build the XML-RPC value out of the data received, and substitute it
$temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
$temp = new XML_RPC_Values($this->xh['value'], $this->xh['vt']);

if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')
if (count($this->xh['valuestack']) && $this->xh['valuestack'][0]['type'] === 'ARRAY')
{
// Array
$this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
$this->xh['valuestack'][0]['values'][] = $temp;
}
else
{
// Struct
$this->xh[$the_parser]['value'] = $temp;
$this->xh['value'] = $temp;
}
break;
case 'MEMBER':
$this->xh[$the_parser]['ac'] = '';
$this->xh['ac'] = '';

// If value add to array in the stack for the last element built
if ($this->xh[$the_parser]['value'])
if ($this->xh['value'])
{
$this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
$this->xh['valuestack'][0]['values'][$this->xh['valuestack'][0]['name']] = $this->xh['value'];
}
break;
case 'DATA':
$this->xh[$the_parser]['ac'] = '';
$this->xh['ac'] = '';
break;
case 'PARAM':
if ($this->xh[$the_parser]['value'])
if ($this->xh['value'])
{
$this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
$this->xh['params'][] = $this->xh['value'];
}
break;
case 'METHODNAME':
$this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
$this->xh['method'] = ltrim($this->xh['ac']);
break;
case 'PARAMS':
case 'FAULT':
Expand All @@ -1514,24 +1509,22 @@ public function closing_tag($the_parser, $name)
*/
public function character_data($the_parser, $data)
{
$the_parser = (string) $the_parser;

if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
if ($this->xh['isf'] > 1) return; // XML Fault found already

// If a value has not been found
if ($this->xh[$the_parser]['lv'] !== 3)
if ($this->xh['lv'] !== 3)
{
if ($this->xh[$the_parser]['lv'] === 1)
if ($this->xh['lv'] === 1)
{
$this->xh[$the_parser]['lv'] = 2; // Found a value
$this->xh['lv'] = 2; // Found a value
}

if ( ! isset($this->xh[$the_parser]['ac']))
if ( ! isset($this->xh['ac']))
{
$this->xh[$the_parser]['ac'] = '';
$this->xh['ac'] = '';
}

$this->xh[$the_parser]['ac'] .= $data;
$this->xh['ac'] .= $data;
}
}

Expand Down
Loading
Loading