/Library/Zend/Validate/Hash.php
PHP | 488 lines | 173 code | 55 blank | 260 comment | 17 complexity | 83fabad8bb77f85adf15cbae865c08e2 MD5 | raw file
- <?php
- /**
- * Contains the definition of the class: Zend_Validate_Hash
- *
- * LICENSE
- *
- * This source file is subject to the new BSD license that is bundled
- * with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://framework.zend.com/license/new-bsd
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@zend.com so we can send you a copy immediately.
- *
- * @category Zend
- * @package Zend_Validate
- * @copyright Lisantra Technologies, LLC 2009
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @author Michael Gatto <mgatto@lisantra.com>
- */
- /**
- * @see Zend_Validate_Abstract
- */
- require_once 'Zend/Validate/Abstract.php';
- /**
- * @see Zend_Validate__Exception
- */
- require_once 'Zend/Validate/Exception.php';
- /**
- * Checks if a given hash in hex format is indeed a correctly formatted hash.
- * The hash may be in either binary or hexadecimal formats. Various hashing
- * algorithms are supported.
- *
- * @category Zend
- * @package Zend_Validate
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @copyright 2009
- * @author Michael Gatto <mgatto@lisantra.com>
- *
- * Usage:
- * <code>
- * $options = array(
- * 'algorithm' => 'md5',
- * 'format' => 'hex',
- * );
- * $hasher = new Zend_Validate_Hash($options);
- * $result = $hasher->isValid('3be6306716ab9c505374d7cd72c63abd');
- * </code>
- *
- * Alternate Usage:
- * <code>
- * $hasher = new Zend_Validate_Hash('md5', 'binary');
- * $result = $hasher->isValid('3be6306716ab9c505374d7cd72c63abd');
- * </code>
- */
- class Zend_Validate_Hash extends Zend_Validate_Abstract
- {
- //@todo implement more hashes:
- /* This will require checking for Php's hash extension (it replaces mhash,
- * which is obsoleted). I should also check for mhash as a fallback, however.
- * Php best practice is _not_ to use dl() (deprecated), but rather to issue an
- * exception and halt processing.
- */
-
- //@todo add error codes to exceptions
- /**
- * Error type for when the value is not a correctly
- * formatted hash
- */
- const ERROR_NOT_HASH = 'notHash';
- /**
- * Error type for when the constructor options' format is invalid
- */
- const ERROR_OPTIONS_INVALID_FORMAT = 'invalidOptions';
-
- /**
- * Error type for when Zend_Config_Ini's config not properly formatted
- */
- const ERROR_OPTIONS_INVALID_INI = 'invalidIni';
-
- /**
- * Error type for when the options array does not have an algorithm key
- */
- const ERROR_OPTIONS_ALGORITHM_KEY_UNDEFINED = 'noAlgorithm';
-
- /**
- * Error type for when options array does not have a format key
- */
- const ERROR_OPTIONS_FORMAT_KEY_UNDEFINED = 'noFormat';
-
- /**
- * Error type for when the argument is not in the expected format
- */
- const ERROR_INPUT_INVALID_FORMAT = 'invalidInput';
- /**
- * Error type for when the hash is not provided
- */
- const ERROR_HASH_UNDEFINED = 'undefinedHash';
- /**
- * Error type for when the algorithm is not provided
- */
- const ERROR_ALGORITHM_UNDEFINED = 'undefinedAlgorithm';
- /**
- * Error type for when the algorithm is not a supported hash
- */
- const ERROR_ALGORITHM_UNSUPPORTED = 'unsupportedAlgorithm';
-
- /**
- * Error type for when the format is not provided
- */
- const ERROR_FORMAT_UNDEFINED = 'undefinedFormat';
- /**
- * Error type for when the algorithm is not a supported hash
- */
- const ERROR_FORMAT_UNSUPPORTED = 'unsupportedFormat';
- /**
- * Currently supported hashes that can be validated.
- *
- * Currently md5 and sha1, because these functions are in the Php core.
- *
- * @var array
- */
- protected $_algorithms = array('md5', 'sha1');
- /**
- * The hashing algorithm by which the value was generated.
- *
- * @var string
- * @see $_algorithms
- */
- protected $_algorithm;
- /**
- * Alternative natural language designations for binary formats.
- *
- * @var array
- */
- protected $_binary_formats = array('bin', 'binary');
-
- /**
- * Alternative natural language designations for hexadecimal formats.
- *
- * @var array
- */
- protected $_hex_formats = array('hex', 'hexadecimal');
-
- /**
- * The format of the hash, either binary or hexadecimal
- *
- * @var string
- */
- protected $_format;
-
- /**
- * The value to be validated
- *
- * Essentially, I am redeclaring it since this variable also appears in
- * Zend_Validate_Abstract.
- *
- * @var string|binary
- */
- protected $_value;
- /**
- * The hash to be evaluated as having a valid format.
- *
- * Format is not specified. We could specify it by making
- * an option to specify binary | hex and / or make hex the default.
- *
- * @var string|binary
- */
- protected $_hash;
- /**
- * Not sure what options one would pass at this point...
- *
- * @var array
- */
- protected $_options = array();
- /**
- * Validation failure message template definitions
- *
- * @var array is originally defined in Zend_Validate_Hash
- * @todo add error templates for when hash too short / chars out of range
- */
- protected $_messageTemplates = array(
- self::ERROR_NOT_HASH => "'%value%' is not a correctly formatted hash",
- self::ERROR_OPTIONS_INVALID_FORMAT =>
- "The options must be an array",
- self::ERROR_OPTIONS_INVALID_INI =>
- "The ini options must be within a 'hash.' grouping",
- self::ERROR_OPTIONS_FORMAT_KEY_UNDEFINED =>
- "The key 'format' was not defined in the options array",
- self::ERROR_OPTIONS_ALGORITHM_KEY_UNDEFINED =>
- "The key 'algorithm' was not defined in the options array",
- self::ERROR_HASH_UNDEFINED => "The hash was not defined",
- self::ERROR_ALGORITHM_UNDEFINED => "The algorithm was not defined",
- self::ERROR_ALGORITHM_UNSUPPORTED => "This algorithm is unsupported",
- self::ERROR_FORMAT_UNDEFINED => "The format was not defined",
- self::ERROR_FORMAT_UNSUPPORTED => "This format is unsupported",
- self::ERROR_INPUT_INVALID_FORMAT =>
- "The hash to validate must be a string",
- );
- /**
- * Class constructor
- *
- *
- *
- * @param array $options with keys: 'algorithm' and 'format'
- * @return void
- */
- function __construct($options = null)
- {
- $this->setOptions($options);
- }
- /**
- * Validate the inputs.
- *
- * @param string $value
- * @return boolean
- */
- public function isValid($value)
- {
- /* default value initialized reduces code and possible errors */
- $validity = (bool) false;
-
- $this->setHash($value);
-
- /* set the function to validate with, to support many algorithms */
- $function = "is_" . $this->getAlgorithm();
- if ( ! $this->$function($this->getHash()) ) {
- //alternative: if ( ! $validity = $this->$function($this->getHash()) )
- /* @see Zend_Validate_Abstract */
- $this->_error(self::ERROR_NOT_HASH, $this->getHash());
- } else {
- $validity = (bool) true;
- }
- return $validity;
- }
- /**
- * Is the passed value a correctly formatted md5 hash?
- *
- * @param $hash string which we hope is in md5 format (hexadecimal)
- * @return boolean
- */
- protected function is_md5($hash)
- {
- /* use a variable so function only has one exit point per Dijkstra */
- $result = false;
- /* @todo make 2 regexs: one for chars and another to check length
- * so we can give more precise error messages.
- */
- if ( preg_match('/^[0-9a-f]{32}$/', $hash) ) {
- $result = true;
- }
- return (bool) $result;
- }
- /**
- * Is the passed value a correctly formatted sha1 hash?
- *
- * @param $hash string which we hope is in sha1 format (hexadecimal)
- * @return boolean
- */
- protected function is_sha1($hash)
- {
- /* use a variable so function only has one exit point per Dijkstra */
- $result = false;
- /* @todo make 2 regexs: one for chars and another to check length
- * so we can give more precise error messages.
- */
- if ( preg_match('/^[0-9a-f]{40}$/', $hash) ) {
- $result = true;
- }
- return (bool) $result;
- }
- /**
- * Mutator for the algorithm
- *
- * @param $algorithm string
- * @return void
- * @see $_algorithm
- */
- public function setAlgorithm($algorithm)
- {
- if ( empty($algorithm) ) {
- throw new Zend_Validate_Exception(
- $this->_messageTemplates[self::ERROR_ALGORITHM_UNDEFINED]
- );
- }
- if ( ! in_array($algorithm, $this->_algorithms) ) {
- throw new Zend_Validate_Exception(
- $this->_messageTemplates[self::ERROR_ALGORITHM_UNSUPPORTED]
- );
- }
- $this->_algorithm = $algorithm;
- }
- /**
- * Accessor for the hashing algorithm
- *
- * @return string
- * @see $_algorithm
- */
- public function getAlgorithm()
- {
- return $this->_algorithm;
- }
- /**
- * Mutator for the options
- *
- * the 'hash' array must be defined in the ini file;
- * Usage:
- * <code>
- * hash.algorithm = 'md5
- * hash.format = 'binary'
- *</code>
- * @param $options array, scalar or object
- * @return void
- * @see $_options
- */
- public function setOptions($options)
- {
- /* this looks cleaner to me than if/elseif/elseif... */
- switch ( true ) {
- case $options instanceof Zend_Config:
- /* We could say, is_a($options, 'Zend_Config') since is_a() is
- * no longer deprecated in Php 5.3
- */
- if ( ! $options->get('hash') ) {
- throw new Zend_Validate_Exception(
- $this->_messageTemplates[self::ERROR_OPTIONS_INVALID_INI]
- );
- }
-
- $this->_options = $options->hash->toArray();
- break;
- case is_array($options):
- $this->_options = $options;
- break;
- default:
- throw new Zend_Validate_Exception(
- $this->_messageTemplates[self::ERROR_OPTIONS_INVALID_FORMAT]
- );
- break;
- }
-
- /* algorithm is mandatory */
- if ( ! array_key_exists('algorithm', $this->_options) ) {
- throw new Zend_Validate_Exception(
- $this->_messageTemplates[self::ERROR_OPTIONS_ALGORITHM_KEY_UNDEFINED]
- );
- }
- $this->setAlgorithm($this->_options['algorithm']);
-
- /* format key is mandatory */
- if ( ! array_key_exists('format', $this->_options) ) {
- throw new Zend_Validate_Exception(
- $this->_messageTemplates[self::ERROR_OPTIONS_FORMAT_KEY_UNDEFINED]
- );
- }
- $this->setFormat($this->_options['format']);
-
- }
- /**
- * Accessor for the options
- *
- * @return array
- * @see $_options
- */
- public function getOptions()
- {
- return $this->_options;
- }
-
- /**
- * Mutator for the format of the hash
- *
- * @param $format string
- * @return void
- * @see $_format
- */
- public function setFormat($format)
- {
- if ( empty($format) ) {
- throw new Zend_Validate_Exception(
- $this->_messageTemplates[self::ERROR_FORMAT_UNDEFINED]
- );
- }
- /* set the strict option to true to check for types also */
- if ( in_array($format, $this->_hex_formats, true) ) {
- $this->_format = 'hexadecimal';
- } elseif (in_array($format, $this->_binary_formats, true) ) {
- $this->_format = 'binary';
- } else {
- /* assume nothing; throw an exception */
- throw new Zend_Validate_Exception(
- $this->_messageTemplates[self::ERROR_FORMAT_UNSUPPORTED]
- );
- }
- }
-
- /**
- * Accessor for the format of the hash.
- *
- * @return string
- * @see $_format
- */
- public function getFormat()
- {
- return $this->_format;
- }
-
- /**
- * Mutator for the hash itself
- *
- * Handles binary hashes by converting to hex before setting it
- *
- * @param $hash string
- * @return void
- * @see $_algorithm
- */
- protected function setHash($hash)
- {
- //@todo refactor to setValue()
-
- if ( empty($hash) ) {
- throw new Zend_Validate_Exception(
- $this->_messageTemplates[self::ERROR_HASH_UNDEFINED]
- );
- }
-
- /* validate the value's type */
- if ( ! is_string($hash) ) {
- throw new Zend_Validate_Exception(
- $this->_messageTemplates[self::ERROR_INPUT_INVALID_FORMAT]
- );
- }
-
- /* @todo
- * I would prefer to use a function to discover its format instead of
- * forcing developers to specify it. Php 6.0 has is_binary(), but
- * I will otherwise write/copy a user-defined function to this class.
- */
- if ( $this->getFormat() === 'binary' ) {
- $this->_hash = bin2hex($hash);
- } else {
- $this->_hash = $hash;
- }
- }
- /**
- * Returns the hash calculated in the class
- *
- * @return string|null
- */
- public function getHash()
- {
- return $this->_hash;
- }
- }