1 : <?php
2 :
3 : /**
4 : * Parses string representations into their corresponding native PHP
5 : * variable type. The base implementation does a simple type-check.
6 : */
7 : class HTMLPurifier_VarParser
8 1 : {
9 :
10 : const STRING = 1;
11 : const ISTRING = 2;
12 : const TEXT = 3;
13 : const ITEXT = 4;
14 : const INT = 5;
15 : const FLOAT = 6;
16 : const BOOL = 7;
17 : const LOOKUP = 8;
18 : const ALIST = 9;
19 : const HASH = 10;
20 : const MIXED = 11;
21 :
22 : /**
23 : * Lookup table of allowed types. Mainly for backwards compatibility, but
24 : * also convenient for transforming string type names to the integer constants.
25 : */
26 : static public $types = array(
27 : 'string' => self::STRING,
28 : 'istring' => self::ISTRING,
29 : 'text' => self::TEXT,
30 : 'itext' => self::ITEXT,
31 : 'int' => self::INT,
32 : 'float' => self::FLOAT,
33 : 'bool' => self::BOOL,
34 : 'lookup' => self::LOOKUP,
35 : 'list' => self::ALIST,
36 : 'hash' => self::HASH,
37 : 'mixed' => self::MIXED
38 : );
39 :
40 : /**
41 : * Lookup table of types that are string, and can have aliases or
42 : * allowed value lists.
43 : */
44 : static public $stringTypes = array(
45 : self::STRING => true,
46 : self::ISTRING => true,
47 : self::TEXT => true,
48 : self::ITEXT => true,
49 : );
50 :
51 : /**
52 : * Validate a variable according to type. Throws
53 : * HTMLPurifier_VarParserException if invalid.
54 : * It may return NULL as a valid type if $allow_null is true.
55 : *
56 : * @param $var Variable to validate
57 : * @param $type Type of variable, see HTMLPurifier_VarParser->types
58 : * @param $allow_null Whether or not to permit null as a value
59 : * @return Validated and type-coerced variable
60 : */
61 : final public function parse($var, $type, $allow_null = false) {
62 2 : if (is_string($type)) {
63 : if (!isset(HTMLPurifier_VarParser::$types[$type])) {
64 : throw new HTMLPurifier_VarParserException("Invalid type '$type'");
65 : } else {
66 : $type = HTMLPurifier_VarParser::$types[$type];
67 : }
68 : }
69 2 : $var = $this->parseImplementation($var, $type, $allow_null);
70 2 : if ($allow_null && $var === null) return null;
71 : // These are basic checks, to make sure nothing horribly wrong
72 : // happened in our implementations.
73 : switch ($type) {
74 2 : case (self::STRING):
75 2 : case (self::ISTRING):
76 2 : case (self::TEXT):
77 2 : case (self::ITEXT):
78 2 : if (!is_string($var)) break;
79 2 : if ($type == self::ISTRING || $type == self::ITEXT) $var = strtolower($var);
80 2 : return $var;
81 2 : case (self::INT):
82 : if (!is_int($var)) break;
83 : return $var;
84 2 : case (self::FLOAT):
85 : if (!is_float($var)) break;
86 : return $var;
87 2 : case (self::BOOL):
88 2 : if (!is_bool($var)) break;
89 2 : return $var;
90 : case (self::LOOKUP):
91 : case (self::ALIST):
92 : case (self::HASH):
93 : if (!is_array($var)) break;
94 : if ($type === self::LOOKUP) {
95 : foreach ($var as $k) if ($k !== true) $this->error('Lookup table contains value other than true');
96 : } elseif ($type === self::ALIST) {
97 : $keys = array_keys($var);
98 : if (array_keys($keys) !== $keys) $this->error('Indices for list are not uniform');
99 : }
100 : return $var;
101 : case (self::MIXED):
102 : return $var;
103 : default:
104 : $this->errorInconsistent(get_class($this), $type);
105 : }
106 : $this->errorGeneric($var, $type);
107 : }
108 :
109 : /**
110 : * Actually implements the parsing. Base implementation is to not
111 : * do anything to $var. Subclasses should overload this!
112 : */
113 : protected function parseImplementation($var, $type, $allow_null) {
114 0 : return $var;
115 : }
116 :
117 : /**
118 : * Throws an exception.
119 : */
120 : protected function error($msg) {
121 0 : throw new HTMLPurifier_VarParserException($msg);
122 : }
123 :
124 : /**
125 : * Throws an inconsistency exception.
126 : * @note This should not ever be called. It would be called if we
127 : * extend the allowed values of HTMLPurifier_VarParser without
128 : * updating subclasses.
129 : */
130 : protected function errorInconsistent($class, $type) {
131 0 : throw new HTMLPurifier_Exception("Inconsistency in $class: ".HTMLPurifier_VarParser::getTypeName($type)." not implemented");
132 : }
133 :
134 : /**
135 : * Generic error for if a type didn't work.
136 : */
137 : protected function errorGeneric($var, $type) {
138 0 : $vtype = gettype($var);
139 0 : $this->error("Expected type ".HTMLPurifier_VarParser::getTypeName($type).", got $vtype");
140 0 : }
141 :
142 : static public function getTypeName($type) {
143 0 : static $lookup;
144 0 : if (!$lookup) {
145 : // Lazy load the alternative lookup table
146 0 : $lookup = array_flip(HTMLPurifier_VarParser::$types);
147 0 : }
148 0 : if (!isset($lookup[$type])) return 'unknown';
149 0 : return $lookup[$type];
150 : }
151 :
152 : }
|