self::STRING, 'istring' => self::ISTRING, 'text' => self::TEXT, 'itext' => self::ITEXT, 'int' => self::INT, 'float' => self::FLOAT, 'bool' => self::BOOL, 'lookup' => self::LOOKUP, 'list' => self::ALIST, 'hash' => self::HASH, 'mixed' => self::MIXED ); /** * Lookup table of types that are string, and can have aliases or * allowed value lists. */ public static $stringTypes = array ( self::STRING => true, self::ISTRING => true, self::TEXT => true, self::ITEXT => true ); /** * Validate a variable according to type. * It may return NULL as a valid type if $allow_null is true. * * @param mixed $var * Variable to validate * @param int $type * Type of variable, see HTMLPurifier_VarParser->types * @param bool $allow_null * Whether or not to permit null as a value * @return string Validated and type-coerced variable * @throws HTMLPurifier_VarParserException */ final public function parse($var, $type, $allow_null = false) { if (is_string ( $type )) { if (! isset ( HTMLPurifier_VarParser::$types [$type] )) { throw new HTMLPurifier_VarParserException ( "Invalid type '$type'" ); } else { $type = HTMLPurifier_VarParser::$types [$type]; } } $var = $this->parseImplementation ( $var, $type, $allow_null ); if ($allow_null && $var === null) { return null; } // These are basic checks, to make sure nothing horribly wrong // happened in our implementations. switch ($type) { case (self::STRING) : case (self::ISTRING) : case (self::TEXT) : case (self::ITEXT) : if (! is_string ( $var )) { break; } if ($type == self::ISTRING || $type == self::ITEXT) { $var = strtolower ( $var ); } return $var; case (self::INT) : if (! is_int ( $var )) { break; } return $var; case (self::FLOAT) : if (! is_float ( $var )) { break; } return $var; case (self::BOOL) : if (! is_bool ( $var )) { break; } return $var; case (self::LOOKUP) : case (self::ALIST) : case (self::HASH) : if (! is_array ( $var )) { break; } if ($type === self::LOOKUP) { foreach ( $var as $k ) { if ($k !== true) { $this->error ( 'Lookup table contains value other than true' ); } } } elseif ($type === self::ALIST) { $keys = array_keys ( $var ); if (array_keys ( $keys ) !== $keys) { $this->error ( 'Indices for list are not uniform' ); } } return $var; case (self::MIXED) : return $var; default : $this->errorInconsistent ( get_class ( $this ), $type ); } $this->errorGeneric ( $var, $type ); } /** * Actually implements the parsing. * Base implementation does not * do anything to $var. Subclasses should overload this! * * @param mixed $var * @param int $type * @param bool $allow_null * @return string */ protected function parseImplementation($var, $type, $allow_null) { return $var; } /** * Throws an exception. * * @throws HTMLPurifier_VarParserException */ protected function error($msg) { throw new HTMLPurifier_VarParserException ( $msg ); } /** * Throws an inconsistency exception. * @note This should not ever be called. It would be called if we * extend the allowed values of HTMLPurifier_VarParser without * updating subclasses. * * @param string $class * @param int $type * @throws HTMLPurifier_Exception */ protected function errorInconsistent($class, $type) { throw new HTMLPurifier_Exception ( "Inconsistency in $class: " . HTMLPurifier_VarParser::getTypeName ( $type ) . " not implemented" ); } /** * Generic error for if a type didn't work. * * @param mixed $var * @param int $type */ protected function errorGeneric($var, $type) { $vtype = gettype ( $var ); $this->error ( "Expected type " . HTMLPurifier_VarParser::getTypeName ( $type ) . ", got $vtype" ); } /** * * @param int $type * @return string */ public static function getTypeName($type) { static $lookup; if (! $lookup) { // Lazy load the alternative lookup table $lookup = array_flip ( HTMLPurifier_VarParser::$types ); } if (! isset ( $lookup [$type] )) { return 'unknown'; } return $lookup [$type]; } } // vim: et sw=4 sts=4