Open Monograph Press  3.3.0
Encoder.php
1 <?php
2 
3 namespace PhpXmlRpc;
4 
6 
7 class Encoder
8 {
31  public function decode($xmlrpcVal, $options = array())
32  {
33  switch ($xmlrpcVal->kindOf()) {
34  case 'scalar':
35  if (in_array('extension_api', $options)) {
36  reset($xmlrpcVal->me);
37  list($typ, $val) = each($xmlrpcVal->me);
38  switch ($typ) {
39  case 'dateTime.iso8601':
40  $xmlrpcVal->scalar = $val;
41  $xmlrpcVal->type = 'datetime';
42  $xmlrpcVal->timestamp = \PhpXmlRpc\Helper\Date::iso8601Decode($val);
43 
44  return $xmlrpcVal;
45  case 'base64':
46  $xmlrpcVal->scalar = $val;
47  $xmlrpcVal->type = $typ;
48 
49  return $xmlrpcVal;
50  default:
51  return $xmlrpcVal->scalarval();
52  }
53  }
54  if (in_array('dates_as_objects', $options) && $xmlrpcVal->scalartyp() == 'dateTime.iso8601') {
55  // we return a Datetime object instead of a string
56  // since now the constructor of xmlrpc value accepts safely strings, ints and datetimes,
57  // we cater to all 3 cases here
58  $out = $xmlrpcVal->scalarval();
59  if (is_string($out)) {
60  $out = strtotime($out);
61  }
62  if (is_int($out)) {
63  $result = new \Datetime();
64  $result->setTimestamp($out);
65 
66  return $result;
67  } elseif (is_a($out, 'Datetime')) {
68  return $out;
69  }
70  }
71 
72  return $xmlrpcVal->scalarval();
73  case 'array':
74  $arr = array();
75  foreach($xmlrpcVal as $value) {
76  $arr[] = $this->decode($value, $options);
77  }
78 
79  return $arr;
80  case 'struct':
81  // If user said so, try to rebuild php objects for specific struct vals.
83  // shall we check for proper subclass of xmlrpc value instead of
84  // presence of _php_class to detect what we can do?
85  if (in_array('decode_php_objs', $options) && $xmlrpcVal->_php_class != ''
86  && class_exists($xmlrpcVal->_php_class)
87  ) {
88  $obj = @new $xmlrpcVal->_php_class();
89  foreach ($xmlrpcVal as $key => $value) {
90  $obj->$key = $this->decode($value, $options);
91  }
92 
93  return $obj;
94  } else {
95  $arr = array();
96  foreach ($xmlrpcVal as $key => $value) {
97  $arr[$key] = $this->decode($value, $options);
98  }
99 
100  return $arr;
101  }
102  case 'msg':
103  $paramCount = $xmlrpcVal->getNumParams();
104  $arr = array();
105  for ($i = 0; $i < $paramCount; $i++) {
106  $arr[] = $this->decode($xmlrpcVal->getParam($i), $options);
107  }
108 
109  return $arr;
110  }
111  }
112 
131  public function encode($phpVal, $options = array())
132  {
133  $type = gettype($phpVal);
134  switch ($type) {
135  case 'string':
136  if (in_array('auto_dates', $options) && preg_match('/^[0-9]{8}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/', $phpVal)) {
137  $xmlrpcVal = new Value($phpVal, Value::$xmlrpcDateTime);
138  } else {
139  $xmlrpcVal = new Value($phpVal, Value::$xmlrpcString);
140  }
141  break;
142  case 'integer':
143  $xmlrpcVal = new Value($phpVal, Value::$xmlrpcInt);
144  break;
145  case 'double':
146  $xmlrpcVal = new Value($phpVal, Value::$xmlrpcDouble);
147  break;
148  // <G_Giunta_2001-02-29>
149  // Add support for encoding/decoding of booleans, since they are supported in PHP
150  case 'boolean':
151  $xmlrpcVal = new Value($phpVal, Value::$xmlrpcBoolean);
152  break;
153  // </G_Giunta_2001-02-29>
154  case 'array':
155  // PHP arrays can be encoded to either xmlrpc structs or arrays,
156  // depending on wheter they are hashes or plain 0..n integer indexed
157  // A shorter one-liner would be
158  // $tmp = array_diff(array_keys($phpVal), range(0, count($phpVal)-1));
159  // but execution time skyrockets!
160  $j = 0;
161  $arr = array();
162  $ko = false;
163  foreach ($phpVal as $key => $val) {
164  $arr[$key] = $this->encode($val, $options);
165  if (!$ko && $key !== $j) {
166  $ko = true;
167  }
168  $j++;
169  }
170  if ($ko) {
171  $xmlrpcVal = new Value($arr, Value::$xmlrpcStruct);
172  } else {
173  $xmlrpcVal = new Value($arr, Value::$xmlrpcArray);
174  }
175  break;
176  case 'object':
177  if (is_a($phpVal, 'PhpXmlRpc\Value')) {
178  $xmlrpcVal = $phpVal;
179  } elseif (is_a($phpVal, 'DateTime')) {
180  $xmlrpcVal = new Value($phpVal->format('Ymd\TH:i:s'), Value::$xmlrpcStruct);
181  } else {
182  $arr = array();
183  reset($phpVal);
184  while (list($k, $v) = each($phpVal)) {
185  $arr[$k] = $this->encode($v, $options);
186  }
187  $xmlrpcVal = new Value($arr, Value::$xmlrpcStruct);
188  if (in_array('encode_php_objs', $options)) {
189  // let's save original class name into xmlrpc value:
190  // might be useful later on...
191  $xmlrpcVal->_php_class = get_class($phpVal);
192  }
193  }
194  break;
195  case 'NULL':
196  if (in_array('extension_api', $options)) {
197  $xmlrpcVal = new Value('', Value::$xmlrpcString);
198  } elseif (in_array('null_extension', $options)) {
199  $xmlrpcVal = new Value('', Value::$xmlrpcNull);
200  } else {
201  $xmlrpcVal = new Value();
202  }
203  break;
204  case 'resource':
205  if (in_array('extension_api', $options)) {
206  $xmlrpcVal = new Value((int)$phpVal, Value::$xmlrpcInt);
207  } else {
208  $xmlrpcVal = new Value();
209  }
210  // catch "user function", "unknown type"
211  default:
212  // giancarlo pinerolo <ping@alt.it>
213  // it has to return
214  // an empty object in case, not a boolean.
215  $xmlrpcVal = new Value();
216  break;
217  }
218 
219  return $xmlrpcVal;
220  }
221 
231  public function decodeXml($xmlVal, $options = array())
232  {
233  // 'guestimate' encoding
234  $valEncoding = XMLParser::guessEncoding('', $xmlVal);
235  if ($valEncoding != '') {
236 
237  // Since parsing will fail if charset is not specified in the xml prologue,
238  // the encoding is not UTF8 and there are non-ascii chars in the text, we try to work round that...
239  // The following code might be better for mb_string enabled installs, but
240  // makes the lib about 200% slower...
241  //if (!is_valid_charset($valEncoding, array('UTF-8'))
242  if (!in_array($valEncoding, array('UTF-8', 'US-ASCII')) && !XMLParser::hasEncoding($xmlVal)) {
243  if ($valEncoding == 'ISO-8859-1') {
244  $xmlVal = utf8_encode($xmlVal);
245  } else {
246  if (extension_loaded('mbstring')) {
247  $xmlVal = mb_convert_encoding($xmlVal, 'UTF-8', $valEncoding);
248  } else {
249  error_log('XML-RPC: ' . __METHOD__ . ': invalid charset encoding of xml text: ' . $valEncoding);
250  }
251  }
252  }
253  }
254 
255  $parser = xml_parser_create();
256  xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
257  // What if internal encoding is not in one of the 3 allowed?
258  // we use the broadest one, ie. utf8!
259  if (!in_array(PhpXmlRpc::$xmlrpc_internalencoding, array('UTF-8', 'ISO-8859-1', 'US-ASCII'))) {
260  xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
261  } else {
262  xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, PhpXmlRpc::$xmlrpc_internalencoding);
263  }
264 
265  $xmlRpcParser = new XMLParser();
266  xml_set_object($parser, $xmlRpcParser);
267 
268  xml_set_element_handler($parser, 'xmlrpc_se_any', 'xmlrpc_ee');
269  xml_set_character_data_handler($parser, 'xmlrpc_cd');
270  xml_set_default_handler($parser, 'xmlrpc_dh');
271  if (!xml_parse($parser, $xmlVal, 1)) {
272  $errstr = sprintf('XML error: %s at line %d, column %d',
273  xml_error_string(xml_get_error_code($parser)),
274  xml_get_current_line_number($parser), xml_get_current_column_number($parser));
275  error_log($errstr);
276  xml_parser_free($parser);
277 
278  return false;
279  }
280  xml_parser_free($parser);
281  if ($xmlRpcParser->_xh['isf'] > 1) {
282  // test that $xmlrpc->_xh['value'] is an obj, too???
283 
284  error_log($xmlRpcParser->_xh['isf_reason']);
285 
286  return false;
287  }
288  switch ($xmlRpcParser->_xh['rt']) {
289  case 'methodresponse':
290  $v = &$xmlRpcParser->_xh['value'];
291  if ($xmlRpcParser->_xh['isf'] == 1) {
292  $vc = $v['faultCode'];
293  $vs = $v['faultString'];
294  $r = new Response(0, $vc->scalarval(), $vs->scalarval());
295  } else {
296  $r = new Response($v);
297  }
298 
299  return $r;
300  case 'methodcall':
301  $req = new Request($xmlRpcParser->_xh['method']);
302  for ($i = 0; $i < count($xmlRpcParser->_xh['params']); $i++) {
303  $req->addParam($xmlRpcParser->_xh['params'][$i]);
304  }
305 
306  return $req;
307  case 'value':
308  return $xmlRpcParser->_xh['value'];
309  default:
310  return false;
311  }
312  }
313 
314 }
PhpXmlRpc\Response
Definition: generic/plagiarism/vendor/phpxmlrpc/phpxmlrpc/src/Response.php:7
PhpXmlRpc\Encoder\decode
decode($xmlrpcVal, $options=array())
Definition: Encoder.php:31
PhpXmlRpc\Encoder\decodeXml
decodeXml($xmlVal, $options=array())
Definition: Encoder.php:231
PhpXmlRpc\Helper\Date\iso8601Decode
static iso8601Decode($idate, $utc=0)
Definition: Date.php:50
PhpXmlRpc\Value
Definition: Value.php:7
PhpXmlRpc\Helper\XMLParser
Definition: XMLParser.php:11
PhpXmlRpc\Encoder
Definition: Encoder.php:7
PhpXmlRpc\Encoder\encode
encode($phpVal, $options=array())
Definition: Encoder.php:131
PhpXmlRpc
Definition: Autoloader.php:3
PhpXmlRpc\Request
Definition: generic/plagiarism/vendor/phpxmlrpc/phpxmlrpc/src/Request.php:10