X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=src%2FHelper%2FXMLParser.php;h=2d3296d4ee6eae2dad2f8617cda1d743ba0dd749;hb=25b0d7c6c540615e854f941dc457f556bfca2408;hp=0f7e0fe9912c5e4dcc916f7d4b9bcb2bea2b18fd;hpb=17cd116908c042fcb2a418a021c83549f75231c7;p=plcapi.git
diff --git a/src/Helper/XMLParser.php b/src/Helper/XMLParser.php
index 0f7e0fe..2d3296d 100644
--- a/src/Helper/XMLParser.php
+++ b/src/Helper/XMLParser.php
@@ -7,15 +7,18 @@ use PhpXmlRpc\Value;
/**
* Deals with parsing the XML.
+ * @see http://xmlrpc.com/spec.md
*/
class XMLParser
{
const RETURN_XMLRPCVALS = 'xmlrpcvals';
+ const RETURN_EPIVALS = 'epivals';
const RETURN_PHP = 'phpvals';
const ACCEPT_REQUEST = 1;
const ACCEPT_RESPONSE = 2;
const ACCEPT_VALUE = 4;
+ const ACCEPT_FAULT = 8;
// Used to store state during parsing.
// Quick explanation of components:
@@ -30,7 +33,7 @@ class XMLParser
// method - used to store method name
// params - used to store parameters in method calls
// pt - used to store the type of each received parameter. Useful if parameters are automatically decoded to php values
- // rt - 'methodcall', 'methodresponse' or 'value'
+ // rt - 'methodcall', 'methodresponse', 'value' or 'fault' (the last one used only in EPI emulation mode)
public $_xh = array(
'ac' => '',
'stack' => array(),
@@ -121,10 +124,15 @@ class XMLParser
xml_set_object($parser, $this);
- if ($returnType == self::RETURN_PHP) {
- xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee_fast');
- } else {
- xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee');
+ switch($returnType) {
+ case self::RETURN_PHP:
+ xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee_fast');
+ break;
+ case self::RETURN_EPIVALS:
+ xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee_epi');
+ break;
+ default:
+ xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee');
}
xml_set_character_data_handler($parser, 'xmlrpc_cd');
@@ -152,6 +160,7 @@ class XMLParser
/**
* xml parser handler function for opening element tags.
+ * @internal
* @param resource $parser
* @param string $name
* @param $attrs
@@ -175,7 +184,8 @@ class XMLParser
}
if (($name == 'METHODCALL' && ($accept & self::ACCEPT_REQUEST)) ||
($name == 'METHODRESPONSE' && ($accept & self::ACCEPT_RESPONSE)) ||
- ($name == 'VALUE' && ($accept & self::ACCEPT_VALUE))) {
+ ($name == 'VALUE' && ($accept & self::ACCEPT_VALUE)) ||
+ ($name == 'FAULT' && ($accept & self::ACCEPT_FAULT))) {
$this->_xh['rt'] = strtolower($name);
} else {
$this->_xh['isf'] = 2;
@@ -296,7 +306,7 @@ class XMLParser
// we do not support the extension, so
// drop through intentionally
default:
- /// INVALID ELEMENT: RAISE ISF so that it is later recognized!!!
+ // INVALID ELEMENT: RAISE ISF so that it is later recognized!!!
$this->_xh['isf'] = 2;
$this->_xh['isf_reason'] = "found not-xmlrpc xml element $name";
break;
@@ -327,11 +337,12 @@ class XMLParser
/**
* xml parser handler function for close element tags.
+ * @internal
* @param resource $parser
* @param string $name
- * @param bool $rebuildXmlrpcvals
+ * @param int $rebuildXmlrpcvals >1 for rebuilding xmlrpcvals, 0 for rebuilding php values, -1 for xmlrpc-extension compatibility
*/
- public function xmlrpc_ee($parser, $name, $rebuildXmlrpcvals = true)
+ public function xmlrpc_ee($parser, $name, $rebuildXmlrpcvals = 1)
{
if ($this->_xh['isf'] < 2) {
// push this element name from stack
@@ -348,7 +359,7 @@ class XMLParser
$this->_xh['vt'] = Value::$xmlrpcString;
}
- if ($rebuildXmlrpcvals) {
+ if ($rebuildXmlrpcvals > 0) {
// build the xmlrpc val out of the data received, and substitute it
$temp = new Value($this->_xh['value'], $this->_xh['vt']);
// in case we got info about underlying php class, save it
@@ -356,27 +367,33 @@ class XMLParser
if (isset($this->_xh['php_class'])) {
$temp->_php_class = $this->_xh['php_class'];
}
- // check if we are inside an array or struct:
- // if value just built is inside an array, let's move it into array on the stack
- $vscount = count($this->_xh['valuestack']);
- if ($vscount && $this->_xh['valuestack'][$vscount - 1]['type'] == 'ARRAY') {
- $this->_xh['valuestack'][$vscount - 1]['values'][] = $temp;
- } else {
- $this->_xh['value'] = $temp;
+ $this->_xh['value'] = $temp;
+ } elseif ($rebuildXmlrpcvals < 0) {
+ if ($this->_xh['vt'] == Value::$xmlrpcDateTime) {
+ $this->_xh['value'] = (object)array(
+ 'xmlrpc_type' => 'datetime',
+ 'scalar' => $this->_xh['value'],
+ 'timestamp' => \PhpXmlRpc\Helper\Date::iso8601Decode($this->_xh['value'])
+ );
+ } elseif ($this->_xh['vt'] == Value::$xmlrpcBase64) {
+ $this->_xh['value'] = (object)array(
+ 'xmlrpc_type' => 'base64',
+ 'scalar' => $this->_xh['value']
+ );
}
} else {
- /// @todo this needs to treat correctly php-serialized objects,
+ /// @todo this should handle php-serialized objects,
/// since std deserializing is done by php_xmlrpc_decode,
/// which we will not be calling...
- if (isset($this->_xh['php_class'])) {
- }
+ //if (isset($this->_xh['php_class'])) {
+ //}
+ }
- // check if we are inside an array or struct:
- // if value just built is inside an array, let's move it into array on the stack
- $vscount = count($this->_xh['valuestack']);
- if ($vscount && $this->_xh['valuestack'][$vscount - 1]['type'] == 'ARRAY') {
- $this->_xh['valuestack'][$vscount - 1]['values'][] = $this->_xh['value'];
- }
+ // check if we are inside an array or struct:
+ // if value just built is inside an array, let's move it into array on the stack
+ $vscount = count($this->_xh['valuestack']);
+ if ($vscount && $this->_xh['valuestack'][$vscount - 1]['type'] == 'ARRAY') {
+ $this->_xh['valuestack'][$vscount - 1]['values'][] = $this->_xh['value'];
}
break;
case 'BOOLEAN':
@@ -395,7 +412,7 @@ class XMLParser
$this->_xh['value'] = $this->_xh['ac'];
} elseif ($name == 'DATETIME.ISO8601') {
if (!preg_match('/^[0-9]{8}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/', $this->_xh['ac'])) {
- error_log('XML-RPC: ' . __METHOD__ . ': invalid value received in DATETIME: ' . $this->_xh['ac']);
+ Logger::instance()->errorLog('XML-RPC: ' . __METHOD__ . ': invalid value received in DATETIME: ' . $this->_xh['ac']);
}
$this->_xh['vt'] = Value::$xmlrpcDateTime;
$this->_xh['value'] = $this->_xh['ac'];
@@ -414,7 +431,7 @@ class XMLParser
} else {
// log if receiving something strange, even though we set the value to false anyway
if ($this->_xh['ac'] != '0' && strcasecmp($this->_xh['ac'], 'false') != 0) {
- error_log('XML-RPC: ' . __METHOD__ . ': invalid value received in BOOLEAN: ' . $this->_xh['ac']);
+ Logger::instance()->errorLog('XML-RPC: ' . __METHOD__ . ': invalid value received in BOOLEAN: ' . $this->_xh['ac']);
}
$this->_xh['value'] = false;
}
@@ -424,7 +441,7 @@ class XMLParser
// NOTE: regexp could be much stricter than this...
if (!preg_match('/^[+-eE0123456789 \t.]+$/', $this->_xh['ac'])) {
/// @todo: find a better way of throwing an error than this!
- error_log('XML-RPC: ' . __METHOD__ . ': non numeric value received in DOUBLE: ' . $this->_xh['ac']);
+ Logger::instance()->errorLog('XML-RPC: ' . __METHOD__ . ': non numeric value received in DOUBLE: ' . $this->_xh['ac']);
$this->_xh['value'] = 'ERROR_NON_NUMERIC_FOUND';
} else {
// it's ok, add it on
@@ -435,7 +452,7 @@ class XMLParser
// we must check that only 0123456789- are characters here
if (!preg_match('/^[+-]?[0123456789 \t]+$/', $this->_xh['ac'])) {
/// @todo find a better way of throwing an error than this!
- error_log('XML-RPC: ' . __METHOD__ . ': non numeric value received in INT: ' . $this->_xh['ac']);
+ Logger::instance()->errorLog('XML-RPC: ' . __METHOD__ . ': non numeric value received in INT: ' . $this->_xh['ac']);
$this->_xh['value'] = 'ERROR_NON_NUMERIC_FOUND';
} else {
// it's ok, add it on
@@ -454,7 +471,7 @@ class XMLParser
$vscount = count($this->_xh['valuestack']);
$this->_xh['valuestack'][$vscount - 1]['values'][$this->_xh['valuestack'][$vscount - 1]['name']] = $this->_xh['value'];
} else {
- error_log('XML-RPC: ' . __METHOD__ . ': missing VALUE inside STRUCT in received xml');
+ Logger::instance()->errorLog('XML-RPC: ' . __METHOD__ . ': missing VALUE inside STRUCT in received xml');
}
break;
case 'DATA':
@@ -477,7 +494,7 @@ class XMLParser
$this->_xh['params'][] = $this->_xh['value'];
$this->_xh['pt'][] = $this->_xh['vt'];
} else {
- error_log('XML-RPC: ' . __METHOD__ . ': missing VALUE inside PARAM in received xml');
+ Logger::instance()->errorLog('XML-RPC: ' . __METHOD__ . ': missing VALUE inside PARAM in received xml');
}
break;
case 'METHODNAME':
@@ -507,16 +524,29 @@ class XMLParser
/**
* Used in decoding xmlrpc requests/responses without rebuilding xmlrpc Values.
+ * @internal
* @param resource $parser
* @param string $name
*/
public function xmlrpc_ee_fast($parser, $name)
{
- $this->xmlrpc_ee($parser, $name, false);
+ $this->xmlrpc_ee($parser, $name, 0);
+ }
+
+ /**
+ * Used in decoding xmlrpc requests/responses while building xmlrpc-extension Values (plain php for all but base64 and datetime).
+ * @internal
+ * @param resource $parser
+ * @param string $name
+ */
+ public function xmlrpc_ee_epi($parser, $name)
+ {
+ $this->xmlrpc_ee($parser, $name, -1);
}
/**
* xml parser handler function for character data.
+ * @internal
* @param resource $parser
* @param string $data
*/
@@ -535,6 +565,7 @@ class XMLParser
/**
* xml parser handler function for 'other stuff', ie. not char data or
* element start/end tag. In fact it only gets called on unknown entities...
+ * @internal
* @param $parser
* @param string data
*/