| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 | <?php/** * Parses string representations into their corresponding native PHP * variable type. The base implementation does a simple type-check. */class HTMLPurifier_VarParser{    const C_STRING = 1;    const ISTRING = 2;    const TEXT = 3;    const ITEXT = 4;    const C_INT = 5;    const C_FLOAT = 6;    const C_BOOL = 7;    const LOOKUP = 8;    const ALIST = 9;    const HASH = 10;    const C_MIXED = 11;    /**     * Lookup table of allowed types. Mainly for backwards compatibility, but     * also convenient for transforming string type names to the integer constants.     */    public static $types = array(        'string' => self::C_STRING,        'istring' => self::ISTRING,        'text' => self::TEXT,        'itext' => self::ITEXT,        'int' => self::C_INT,        'float' => self::C_FLOAT,        'bool' => self::C_BOOL,        'lookup' => self::LOOKUP,        'list' => self::ALIST,        'hash' => self::HASH,        'mixed' => self::C_MIXED    );    /**     * Lookup table of types that are string, and can have aliases or     * allowed value lists.     */    public static $stringTypes = array(        self::C_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::C_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::C_INT):                if (!is_int($var)) {                    break;                }                return $var;            case (self::C_FLOAT):                if (!is_float($var)) {                    break;                }                return $var;            case (self::C_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::C_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
 |