1: <?php
2:
3: /**
4: * Performs safe variable parsing based on types which can be used by
5: * users. This may not be able to represent all possible data inputs,
6: * however.
7: */
8: class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
9: {
10: /**
11: * @param mixed $var
12: * @param int $type
13: * @param bool $allow_null
14: * @return array|bool|float|int|mixed|null|string
15: * @throws HTMLPurifier_VarParserException
16: */
17: protected function parseImplementation($var, $type, $allow_null)
18: {
19: if ($allow_null && $var === null) {
20: return null;
21: }
22: switch ($type) {
23: // Note: if code "breaks" from the switch, it triggers a generic
24: // exception to be thrown. Specific errors can be specifically
25: // done here.
26: case self::C_MIXED:
27: case self::ISTRING:
28: case self::C_STRING:
29: case self::TEXT:
30: case self::ITEXT:
31: return $var;
32: case self::C_INT:
33: if (is_string($var) && ctype_digit($var)) {
34: $var = (int)$var;
35: }
36: return $var;
37: case self::C_FLOAT:
38: if ((is_string($var) && is_numeric($var)) || is_int($var)) {
39: $var = (float)$var;
40: }
41: return $var;
42: case self::C_BOOL:
43: if (is_int($var) && ($var === 0 || $var === 1)) {
44: $var = (bool)$var;
45: } elseif (is_string($var)) {
46: if ($var == 'on' || $var == 'true' || $var == '1') {
47: $var = true;
48: } elseif ($var == 'off' || $var == 'false' || $var == '0') {
49: $var = false;
50: } else {
51: throw new HTMLPurifier_VarParserException("Unrecognized value '$var' for $type");
52: }
53: }
54: return $var;
55: case self::ALIST:
56: case self::HASH:
57: case self::LOOKUP:
58: if (is_string($var)) {
59: // special case: technically, this is an array with
60: // a single empty string item, but having an empty
61: // array is more intuitive
62: if ($var == '') {
63: return array();
64: }
65: if (strpos($var, "\n") === false && strpos($var, "\r") === false) {
66: // simplistic string to array method that only works
67: // for simple lists of tag names or alphanumeric characters
68: $var = explode(',', $var);
69: } else {
70: $var = preg_split('/(,|[\n\r]+)/', $var);
71: }
72: // remove spaces
73: foreach ($var as $i => $j) {
74: $var[$i] = trim($j);
75: }
76: if ($type === self::HASH) {
77: // key:value,key2:value2
78: $nvar = array();
79: foreach ($var as $keypair) {
80: $c = explode(':', $keypair, 2);
81: if (!isset($c[1])) {
82: continue;
83: }
84: $nvar[trim($c[0])] = trim($c[1]);
85: }
86: $var = $nvar;
87: }
88: }
89: if (!is_array($var)) {
90: break;
91: }
92: $keys = array_keys($var);
93: if ($keys === array_keys($keys)) {
94: if ($type == self::ALIST) {
95: return $var;
96: } elseif ($type == self::LOOKUP) {
97: $new = array();
98: foreach ($var as $key) {
99: $new[$key] = true;
100: }
101: return $new;
102: } else {
103: break;
104: }
105: }
106: if ($type === self::ALIST) {
107: trigger_error("Array list did not have consecutive integer indexes", E_USER_WARNING);
108: return array_values($var);
109: }
110: if ($type === self::LOOKUP) {
111: foreach ($var as $key => $value) {
112: if ($value !== true) {
113: trigger_error(
114: "Lookup array has non-true value at key '$key'; " .
115: "maybe your input array was not indexed numerically",
116: E_USER_WARNING
117: );
118: }
119: $var[$key] = true;
120: }
121: }
122: return $var;
123: default:
124: $this->errorInconsistent(__CLASS__, $type);
125: }
126: $this->errorGeneric($var, $type);
127: }
128: }
129:
130: // vim: et sw=4 sts=4
131: