/** * Takes an xmlrpc value in object format and translates it into native PHP types. * * Works with xmlrpc requests objects as input, too. * * Given proper options parameter, can rebuild generic php object instances * (provided those have been encoded to xmlrpc format using a corresponding * option in php_xmlrpc_encode()) * PLEASE NOTE that rebuilding php objects involves calling their constructor function. * This means that the remote communication end can decide which php code will * get executed on your server, leaving the door possibly open to 'php-injection' * style of attacks (provided you have some classes defined on your server that * might wreak havoc if instances are built outside an appropriate context). * Make sure you trust the remote server/client before eanbling this! * * @author Dan Libby (dan@libby.com) * * @param Value|Request $xmlrpcVal * @param array $options if 'decode_php_objs' is set in the options array, xmlrpc structs can be decoded into php objects; if 'dates_as_objects' is set xmlrpc datetimes are decoded as php DateTime objects (standard is * * @return mixed */ public function decode($xmlrpcVal, $options = array()) { switch ($xmlrpcVal->kindOf()) { case 'scalar': if (in_array('extension_api', $options)) { reset($xmlrpcVal->me); list($typ, $val) = each($xmlrpcVal->me); switch ($typ) { case 'dateTime.iso8601': $xmlrpcVal->scalar = $val; $xmlrpcVal->type = 'datetime'; $xmlrpcVal->timestamp = \PhpXmlRpc\Helper\Date::iso8601Decode($val); return $xmlrpcVal; case 'base64': $xmlrpcVal->scalar = $val; $xmlrpcVal->type = $typ; return $xmlrpcVal; default: return $xmlrpcVal->scalarval(); } } if (in_array('dates_as_objects', $options) && $xmlrpcVal->scalartyp() == 'dateTime.iso8601') { // we return a Datetime object instead of a string // since now the constructor of xmlrpc value accepts safely strings, ints and datetimes, // we cater to all 3 cases here $out = $xmlrpcVal->scalarval(); if (is_string($out)) { $out = strtotime($out); } if (is_int($out)) { $result = new \Datetime(); $result->setTimestamp($out); return $result; } elseif (is_a($out, 'Datetime')) { return $out; } } return $xmlrpcVal->scalarval(); case 'array': $arr = array(); foreach ($xmlrpcVal as $value) { $arr[] = $this->decode($value, $options); } return $arr; case 'struct': // If user said so, try to rebuild php objects for specific struct vals. /// @todo should we raise a warning for class not found? // shall we check for proper subclass of xmlrpc value instead of // presence of _php_class to detect what we can do? if (in_array('decode_php_objs', $options) && $xmlrpcVal->_php_class != '' && class_exists($xmlrpcVal->_php_class)) { $obj = @new $xmlrpcVal->_php_class(); foreach ($xmlrpcVal as $key => $value) { $obj->{$key} = $this->decode($value, $options); } return $obj; } else { $arr = array(); foreach ($xmlrpcVal as $key => $value) { $arr[$key] = $this->decode($value, $options); } return $arr; } case 'msg': $paramCount = $xmlrpcVal->getNumParams(); $arr = array(); for ($i = 0; $i < $paramCount; $i++) { $arr[] = $this->decode($xmlrpcVal->getParam($i), $options); } return $arr; } }