This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * @package Fuel\Common |
||
4 | * @version 2.0 |
||
5 | * @author Fuel Development Team |
||
6 | * @license MIT License |
||
7 | * @copyright 2010 - 2015 Fuel Development Team |
||
8 | * @link http://fuelphp.com |
||
9 | */ |
||
10 | |||
11 | namespace Fuel\Common; |
||
12 | |||
13 | /** |
||
14 | * Help convert between various formats such as XML, JSON, CSV, etc. |
||
15 | * |
||
16 | * @package Fuel\Common |
||
17 | * |
||
18 | * @since 1.0 |
||
19 | */ |
||
20 | class Format |
||
21 | { |
||
22 | /** |
||
23 | * @var array|mixed Input data to convert |
||
24 | */ |
||
25 | protected $data = array(); |
||
26 | |||
27 | /** |
||
28 | * @var array|mixed Configuration for this Format instance |
||
29 | */ |
||
30 | protected $config = array(); |
||
31 | |||
32 | /** |
||
33 | * @var bool whether to ignore namespaces when parsing xml |
||
34 | */ |
||
35 | protected $xmlIgnoreNamespaces = true; |
||
36 | |||
37 | /** |
||
38 | * @var Fuel\Common\Datacontainer Input Container |
||
39 | */ |
||
40 | protected $input; |
||
41 | |||
42 | /** |
||
43 | * @var Fuel\Common\Inflector Inflector object |
||
44 | */ |
||
45 | protected $inflector; |
||
46 | |||
47 | /** |
||
48 | * @param mixed $data Input data to format or convert |
||
49 | * @param mixed $from_type The data type of the input data |
||
50 | * |
||
51 | * @throws InvalidArgumentException if the from_type isn't a known type |
||
52 | */ |
||
53 | public function __construct($data = null, $from_type = null, Array $config = array(), $input = null, $inflector = null) |
||
54 | { |
||
55 | // If the provided data is already formatted we should probably convert it to an array |
||
56 | if ($from_type !== null) |
||
57 | { |
||
58 | if ($from_type == 'xml:ns') |
||
59 | { |
||
60 | $this->xmlIgnoreNamespaces = false; |
||
61 | $from_type = 'xml'; |
||
62 | } |
||
63 | |||
64 | if (method_exists($this, $method = '_from'.ucfirst($from_type))) |
||
65 | { |
||
66 | $data = call_user_func(array($this, $method), $data); |
||
67 | } |
||
68 | else |
||
69 | { |
||
70 | throw new \InvalidArgumentException('Format class does not support conversion from "' . $from_type . '".'); |
||
71 | } |
||
72 | } |
||
73 | |||
74 | // store the passed data and config |
||
75 | $this->data = $data; |
||
76 | $this->config = $config; |
||
77 | |||
78 | // store the injected objects |
||
79 | $this->input = $input; |
||
80 | $this->inflector = $inflector; |
||
81 | } |
||
82 | |||
83 | // FORMATING OUTPUT --------------------------------------------------------- |
||
84 | |||
85 | /** |
||
86 | * To array conversion |
||
87 | * |
||
88 | * Goes through the input and makes sure everything is either a scalar value or array |
||
89 | * |
||
90 | * @param mixed $data |
||
91 | * @return array |
||
92 | */ |
||
93 | public function toArray($data = null) |
||
94 | { |
||
95 | if ($data === null) |
||
96 | { |
||
97 | $data = $this->data; |
||
98 | } |
||
99 | |||
100 | $array = array(); |
||
101 | |||
102 | if (is_object($data) and ! $data instanceof \Iterator) |
||
103 | { |
||
104 | $data = get_object_vars($data); |
||
105 | } |
||
106 | |||
107 | if (empty($data)) |
||
108 | { |
||
109 | return array(); |
||
110 | } |
||
111 | |||
112 | foreach ($data as $key => $value) |
||
113 | { |
||
114 | if (is_object($value) or is_array($value)) |
||
115 | { |
||
116 | $array[$key] = $this->toArray($value); |
||
117 | } |
||
118 | else |
||
119 | { |
||
120 | $array[$key] = $value; |
||
121 | } |
||
122 | } |
||
123 | |||
124 | return $array; |
||
125 | } |
||
126 | |||
127 | /** |
||
128 | * To XML conversion |
||
129 | * |
||
130 | * @param mixed $data |
||
131 | * @param null $structure |
||
132 | * @param null|string $basenode |
||
133 | * @param null|bool whether to use CDATA in nodes |
||
134 | * @return string |
||
135 | */ |
||
136 | public function toXml($data = null, $structure = null, $basenode = null, $usecdata = null) |
||
137 | { |
||
138 | if ($data === null) |
||
139 | { |
||
140 | $data = $this->data; |
||
141 | } |
||
142 | |||
143 | if ($basenode === null) |
||
144 | { |
||
145 | $basenode = Arr::get($this->config, 'xml.basenode', 'xml'); |
||
146 | } |
||
147 | |||
148 | if ($usecdata === null) |
||
149 | { |
||
150 | $usecdata = Arr::get($this->config, 'xml.usecdata', false); |
||
151 | } |
||
152 | |||
153 | if ($structure === null) |
||
154 | { |
||
155 | $structure = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><$basenode />"); |
||
156 | } |
||
157 | |||
158 | // Force it to be something useful |
||
159 | if ( ! is_array($data) and ! is_object($data)) |
||
160 | { |
||
161 | $data = (array) $data; |
||
162 | } |
||
163 | |||
164 | foreach ($data as $key => $value) |
||
165 | { |
||
166 | // replace anything not alpha numeric |
||
167 | $key = preg_replace('/[^a-z_\-0-9]/i', '', $key); |
||
168 | |||
169 | // no numeric keys in our xml please! |
||
170 | if (is_numeric($key)) |
||
171 | { |
||
172 | // make string key... |
||
173 | $key = ($this->inflector->singularize($basenode) != $basenode) ? $this->inflector->singularize($basenode) : 'item'; |
||
174 | } |
||
175 | |||
176 | // if there is another array found recrusively call this function |
||
177 | if (is_array($value) or is_object($value)) |
||
178 | { |
||
179 | $node = $structure->addChild($key); |
||
180 | |||
181 | // recursive call if value is not empty |
||
182 | if( ! empty($value)) |
||
183 | { |
||
184 | $this->toXml($value, $node, $key, $usecdata); |
||
185 | } |
||
186 | } |
||
187 | |||
188 | else |
||
189 | { |
||
190 | // add single node. |
||
191 | $encoded = htmlspecialchars(html_entity_decode($value, ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8'); |
||
192 | |||
193 | if ($usecdata and ($encoded !== (string) $value)) |
||
194 | { |
||
195 | $dom = dom_import_simplexml($structure->addChild($key)); |
||
196 | $owner = $dom->ownerDocument; |
||
197 | $dom->appendChild($owner->createCDATASection($value)); |
||
198 | } |
||
199 | else |
||
200 | { |
||
201 | $structure->addChild($key, $encoded); |
||
202 | } |
||
203 | } |
||
204 | } |
||
205 | |||
206 | // pass back as string. or simple xml object if you want! |
||
207 | return $structure->asXML(); |
||
208 | } |
||
209 | |||
210 | /** |
||
211 | * To CSV conversion |
||
212 | * |
||
213 | * @param mixed $data |
||
214 | * @param mixed $delimiter |
||
215 | * @return string |
||
216 | */ |
||
217 | public function toCsv($data = null, $delimiter = null) |
||
218 | { |
||
219 | // csv format settings |
||
220 | $newline = Arr::get($this->config, 'csv.newline', "\n"); |
||
221 | $delimiter or $delimiter = Arr::get($this->config, 'csv.delimiter', ','); |
||
222 | $enclosure = Arr::get($this->config, 'csv.enclosure', '"'); |
||
223 | $escape = Arr::get($this->config, 'csv.escape', '\\'); |
||
224 | |||
225 | // escape function |
||
226 | $escaper = function($items) use($enclosure, $escape) { |
||
227 | return array_map(function($item) use($enclosure, $escape){ |
||
228 | return str_replace($enclosure, $escape.$enclosure, $item); |
||
229 | }, $items); |
||
230 | }; |
||
231 | |||
232 | if ($data === null) |
||
233 | { |
||
234 | $data = $this->data; |
||
235 | } |
||
236 | |||
237 | if (is_object($data) and ! $data instanceof \Iterator) |
||
238 | { |
||
239 | $data = $this->toArray($data); |
||
240 | } |
||
241 | |||
242 | // Multi-dimensional array |
||
243 | if (is_array($data) and Arr::isMulti($data)) |
||
244 | { |
||
245 | $data = array_values($data); |
||
246 | |||
247 | if (Arr::isAssoc($data[0])) |
||
248 | { |
||
249 | $headings = array_keys($data[0]); |
||
250 | } |
||
251 | else |
||
252 | { |
||
253 | $headings = array_shift($data); |
||
254 | } |
||
255 | } |
||
256 | // Single array |
||
257 | else |
||
258 | { |
||
259 | $headings = array_keys((array) $data); |
||
260 | $data = array($data); |
||
261 | } |
||
262 | |||
263 | $output = $enclosure.implode($enclosure.$delimiter.$enclosure, $escaper($headings)).$enclosure.$newline; |
||
264 | |||
265 | foreach ($data as $row) |
||
266 | { |
||
267 | $output .= $enclosure.implode($enclosure.$delimiter.$enclosure, $escaper((array) $row)).$enclosure.$newline; |
||
268 | } |
||
269 | |||
270 | return rtrim($output, $newline); |
||
271 | } |
||
272 | |||
273 | /** |
||
274 | * To JSON conversion |
||
275 | * |
||
276 | * @param mixed $data |
||
277 | * @param bool wether to make the json pretty |
||
278 | * @return string |
||
279 | */ |
||
280 | public function toJson($data = null, $pretty = false) |
||
281 | { |
||
282 | if ($data === null) |
||
283 | { |
||
284 | $data = $this->data; |
||
285 | } |
||
286 | |||
287 | // To allow exporting ArrayAccess objects like Orm\Model instances they need to be |
||
288 | // converted to an array first |
||
289 | $data = (is_array($data) or is_object($data)) ? $this->toArray($data) : $data; |
||
290 | |||
291 | // Return the result in the requested format |
||
292 | if ($pretty) |
||
293 | { |
||
294 | return $this->prettyJson($data); |
||
295 | } |
||
296 | else |
||
297 | { |
||
298 | $result = json_encode($data, Arr::get($this->config, 'json.encode.options', JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP)); |
||
299 | return json_last_error() === JSON_ERROR_NONE ? $result : false; |
||
300 | } |
||
301 | } |
||
302 | |||
303 | /** |
||
304 | * To JSONP conversion |
||
305 | * |
||
306 | * @param mixed $data |
||
307 | * @param bool $pretty wether to make the json pretty |
||
308 | * @param string $callback JSONP callback |
||
309 | * @return string formatted JSONP |
||
310 | */ |
||
311 | public function toJsonp($data = null, $pretty = false, $callback = null) |
||
312 | { |
||
313 | if ( ! $callback and $this->input) |
||
314 | { |
||
315 | $callback = $this->input->getParam('callback'); |
||
316 | if ( ! $callback) |
||
317 | { |
||
318 | $callback = 'response'; |
||
319 | } |
||
320 | } |
||
321 | |||
322 | return $callback.'('.(string) $this->toJson($data, $pretty).')'; |
||
323 | } |
||
324 | |||
325 | /** |
||
326 | * Serialize |
||
327 | * |
||
328 | * @param mixed $data |
||
329 | * @return string |
||
330 | */ |
||
331 | public function toSerialized($data = null) |
||
332 | { |
||
333 | if ($data === null) |
||
334 | { |
||
335 | $data = $this->data; |
||
336 | } |
||
337 | |||
338 | return serialize($data); |
||
339 | } |
||
340 | |||
341 | /** |
||
342 | * Return as a string representing the PHP structure |
||
343 | * |
||
344 | * @param mixed $data |
||
345 | * @return string |
||
346 | */ |
||
347 | public function toPhp($data = null) |
||
348 | { |
||
349 | if ($data === null) |
||
350 | { |
||
351 | $data = $this->data; |
||
352 | } |
||
353 | |||
354 | return var_export($data, true); |
||
355 | } |
||
356 | |||
357 | /** |
||
358 | * Convert to YAML |
||
359 | * |
||
360 | * @param mixed $data |
||
361 | * @throws RuntimeException if the Symfony/YAML composer package is not installed |
||
362 | * @return string |
||
363 | */ |
||
364 | public function toYaml($data = null) |
||
365 | { |
||
366 | if ($data == null) |
||
367 | { |
||
368 | $data = $this->data; |
||
369 | } |
||
370 | |||
371 | if ( ! class_exists('Symfony\Component\Yaml\Yaml')) |
||
372 | { |
||
373 | // @codeCoverageIgnoreStart |
||
374 | throw new \RuntimeException('You need to install the "symfony/yaml" composer package to use Format::toYaml()'); |
||
375 | // @codeCoverageIgnoreEnd |
||
376 | } |
||
377 | |||
378 | $parser = new \Symfony\Component\Yaml\Yaml(); |
||
379 | return $parser::dump($data); |
||
380 | } |
||
381 | |||
382 | /** |
||
383 | * Import XML data |
||
384 | * |
||
385 | * @param string $string |
||
386 | * @return array |
||
387 | */ |
||
388 | protected function _fromXml($string, $recursive = false) |
||
389 | { |
||
390 | // If it forged with 'xml:ns' |
||
391 | if ( ! $this->xmlIgnoreNamespaces) |
||
392 | { |
||
393 | static $escape_keys = array(); |
||
394 | |||
395 | if ( ! $recursive) |
||
396 | { |
||
397 | $escape_keys = array('_xmlns' => 'xmlns'); |
||
398 | } |
||
399 | |||
400 | if ( ! $recursive and strpos($string, 'xmlns') !== false and preg_match_all('/(\<.+?\>)/s', $string, $matches)) |
||
401 | { |
||
402 | foreach ($matches[1] as $tag) |
||
403 | { |
||
404 | $escaped_tag = $tag; |
||
405 | |||
406 | strpos($tag, 'xmlns=') !== false and $escaped_tag = str_replace('xmlns=', '_xmlns=', $tag); |
||
407 | |||
408 | if (preg_match_all('/[\s\<\/]([^\/\s\'"]*?:\S*?)[=\/\>\s]/s', $escaped_tag, $xmlns)) |
||
409 | { |
||
410 | foreach ($xmlns[1] as $ns) |
||
411 | { |
||
412 | $escaped = Arr::search($escape_keys, $ns); |
||
413 | $escaped or $escape_keys[$escaped = str_replace(':', '_', $ns)] = $ns; |
||
414 | $string = str_replace($tag, $escaped_tag = str_replace($ns, $escaped, $escaped_tag), $string); |
||
415 | $tag = $escaped_tag; |
||
416 | } |
||
417 | } |
||
418 | } |
||
419 | } |
||
420 | } |
||
421 | |||
422 | $_arr = is_string($string) ? simplexml_load_string($string, 'SimpleXMLElement', LIBXML_NOCDATA) : $string; |
||
423 | $arr = array(); |
||
424 | |||
425 | // Convert all objects SimpleXMLElement to array recursively |
||
426 | foreach ((array)$_arr as $key => $val) |
||
427 | { |
||
428 | if ( ! $this->xmlIgnoreNamespaces) |
||
429 | { |
||
430 | $key = Arr::get($escape_keys, $key, $key); |
||
0 ignored issues
–
show
|
|||
431 | } |
||
432 | $arr[$key] = (is_array($val) or is_object($val)) ? $this->_fromXml($val, true) : $val; |
||
433 | } |
||
434 | |||
435 | return $arr; |
||
436 | } |
||
437 | |||
438 | /** |
||
439 | * Import YAML data |
||
440 | * |
||
441 | * @param string $string |
||
442 | * @return array |
||
443 | */ |
||
444 | protected function _fromYaml($data) |
||
445 | { |
||
446 | if ( ! class_exists('Symfony\Component\Yaml\Yaml')) |
||
447 | { |
||
448 | // @codeCoverageIgnoreStart |
||
449 | throw new \RuntimeException('You need to install the "symfony/yaml" composer package to use Format::fromYaml()'); |
||
450 | // @codeCoverageIgnoreEnd |
||
451 | } |
||
452 | |||
453 | $parser = new \Symfony\Component\Yaml\Yaml(); |
||
454 | return $parser::parse($data); |
||
455 | } |
||
456 | |||
457 | /** |
||
458 | * Import CSV data |
||
459 | * |
||
460 | * @param string $string |
||
461 | * @return array |
||
462 | */ |
||
463 | protected function _fromCsv($string) |
||
464 | { |
||
465 | $data = array(); |
||
466 | |||
467 | $rows = preg_split('/(?<='.preg_quote(Arr::get($this->config, 'csv.enclosure', '"')).')'.Arr::get($this->config, 'csv.regex_newline', '\n').'/', trim($string)); |
||
468 | |||
469 | // csv config |
||
470 | $delimiter = Arr::get($this->config, 'csv.delimiter', ','); |
||
471 | $enclosure = Arr::get($this->config, 'csv.enclosure', '"'); |
||
472 | $escape = Arr::get($this->config, 'csv.escape', '\\'); |
||
473 | |||
474 | // Get the headings |
||
475 | $headings = str_replace($escape.$enclosure, $enclosure, str_getcsv(array_shift($rows), $delimiter, $enclosure, $escape)); |
||
476 | |||
477 | foreach ($rows as $row) |
||
478 | { |
||
479 | $data_fields = str_replace($escape.$enclosure, $enclosure, str_getcsv($row, $delimiter, $enclosure, $escape)); |
||
480 | |||
481 | if (count($data_fields) == count($headings)) |
||
482 | { |
||
483 | $data[] = array_combine($headings, $data_fields); |
||
484 | } |
||
485 | |||
486 | } |
||
487 | |||
488 | return $data; |
||
489 | } |
||
490 | |||
491 | /** |
||
492 | * Import JSON data |
||
493 | * |
||
494 | * @param string $string |
||
495 | * @return mixed |
||
496 | */ |
||
497 | private function _fromJson($string) |
||
498 | { |
||
499 | return json_decode(trim($string)); |
||
500 | } |
||
501 | |||
502 | /** |
||
503 | * Import Serialized data |
||
504 | * |
||
505 | * @param string $string |
||
506 | * @return mixed |
||
507 | */ |
||
508 | private function _fromSerialized($string) |
||
509 | { |
||
510 | return unserialize(trim($string)); |
||
511 | } |
||
512 | |||
513 | /** |
||
514 | * Makes json pretty the json output. |
||
515 | * Borrowed from http://www.php.net/manual/en/function.json-encode.php#80339 |
||
516 | * |
||
517 | * @param string $json json encoded array |
||
518 | * @return string|false pretty json output or false when the input was not valid |
||
519 | */ |
||
520 | protected function prettyJson($data) |
||
521 | { |
||
522 | $json = json_encode($data, Arr::get($this->config, 'json.encode.options', JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP)); |
||
523 | |||
524 | if (json_last_error() !== JSON_ERROR_NONE) |
||
525 | { |
||
526 | return false; |
||
527 | } |
||
528 | |||
529 | $tab = "\t"; |
||
530 | $newline = "\n"; |
||
531 | $new_json = ""; |
||
532 | $indent_level = 0; |
||
533 | $in_string = false; |
||
534 | $len = strlen($json); |
||
535 | |||
536 | for ($c = 0; $c < $len; $c++) |
||
537 | { |
||
538 | $char = $json[$c]; |
||
539 | switch($char) |
||
540 | { |
||
541 | case '{': |
||
542 | View Code Duplication | case '[': |
|
543 | if ( ! $in_string) |
||
544 | { |
||
545 | $new_json .= $char.$newline.str_repeat($tab, $indent_level+1); |
||
546 | $indent_level++; |
||
547 | } |
||
548 | else |
||
549 | { |
||
550 | $new_json .= $char; |
||
551 | } |
||
552 | break; |
||
553 | case '}': |
||
554 | View Code Duplication | case ']': |
|
555 | if ( ! $in_string) |
||
556 | { |
||
557 | $indent_level--; |
||
558 | $new_json .= $newline.str_repeat($tab, $indent_level).$char; |
||
559 | } |
||
560 | else |
||
561 | { |
||
562 | $new_json .= $char; |
||
563 | } |
||
564 | break; |
||
565 | View Code Duplication | case ',': |
|
566 | if ( ! $in_string) |
||
567 | { |
||
568 | $new_json .= ','.$newline.str_repeat($tab, $indent_level); |
||
569 | } |
||
570 | else |
||
571 | { |
||
572 | $new_json .= $char; |
||
573 | } |
||
574 | break; |
||
575 | case ':': |
||
576 | if ( ! $in_string) |
||
577 | { |
||
578 | $new_json .= ': '; |
||
579 | } |
||
580 | else |
||
581 | { |
||
582 | $new_json .= $char; |
||
583 | } |
||
584 | break; |
||
585 | case '"': |
||
586 | if ($c > 0 and $json[$c-1] !== '\\') |
||
587 | { |
||
588 | $in_string = ! $in_string; |
||
589 | } |
||
590 | default: |
||
591 | $new_json .= $char; |
||
592 | break; |
||
593 | } |
||
594 | } |
||
595 | |||
596 | return $new_json; |
||
597 | } |
||
598 | } |
||
599 |
If you define a variable conditionally, it can happen that it is not defined for all execution paths.
Let’s take a look at an example:
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.
Available Fixes
Check for existence of the variable explicitly:
Define a default value for the variable:
Add a value for the missing path: