Your IP : 216.73.216.170


Current Path : /var/www/iplanru/data/www/i-plan.ru/administrator/components/com_zoo/classes/
Upload File :
Current File : /var/www/iplanru/data/www/i-plan.ru/administrator/components/com_zoo/classes/validator.php

<?php
/**
* @package   com_zoo
* @author    YOOtheme http://www.yootheme.com
* @copyright Copyright (C) YOOtheme GmbH
* @license   http://www.gnu.org/licenses/gpl.html GNU/GPL
*/

/**
 * Validator Class
 *
 * @package Component.Classes.Validators
 */
class AppValidator {

    /**
     * Reference to the global App object
     *
     * @var App
     * @since 2.0
     */
	public $app;

	const ERROR_CODE_REQUIRED = 100;

    /**
     * List of messages to return for the validation
     *
     * @var array
     * @since 2.0
     */
    protected $_messages = array();

    /**
     * List of options for the validation
     *
     * @var array
     * @since 2.0
     */
    protected $_options  = array();

    /**
     * Class Constructor
     *
     * @param array $options  The list of options to use for the validation (array('requred' , 'trim', 'empty_value'))
     * @param array $messages Associative array of text messages for the validation (array('requred' , 'invalid'))
     */
    public function __construct($options = array(), $messages = array()) {

		$this->app = App::getInstance('zoo');

        $this->_options  = array_merge(array('required' => true, 'trim' => false, 'empty_value' => null), $this->_options);
        $this->_messages = array_merge(array('required' => 'This field is required', 'invalid' => 'Invalid'), $this->_messages);

        $this->_configure($this->_options, $this->_messages);

 	    $this->_options  = array_merge($this->_options, $options);
 	    $this->_messages = array_merge($this->_messages, $messages);

    }

    /**
     * Configure the validation
     *
     * @param  array  $options  The list of options
     * @param  array  $messages The list of messages
     *
     * @see AppValidator::__construct()
     *
     * @since 2.0
     */
    protected function _configure($options = array(), $messages = array()) {
        $this->addOption('invalid',  'Invalid');
    }

    /**
     * Clean a value using the options set in the validator
     *
     * @param  mixed $value The value to clean
     *
     * @return mixed        The cleaned value
     *
     * @since 2.0
     */
    public function clean($value) {
        $clean = $value;

        if ($this->getOption('trim') && is_string($clean)) {
            $clean = JString::trim($clean);
        }

        if ($this->isEmpty($clean)) {
            if ($this->getOption('required')) {
                throw new AppValidatorException($this->getMessage('required'), self::ERROR_CODE_REQUIRED);
            }

            return $this->getEmptyValue();
        }

        return $this->_doClean($clean);
    }

    /**
     * Add a message
     *
     * @param string $name  The key of the message
     * @param string $value The message
     *
     * @return AppValidator $this for chaining support
     *
     * @see AppValidator::__construct()
     *
     * @since 2.0
     */
    public function addMessage($name, $value = null) {
        $this->_messages[$name] = $value;

        return $this;
    }

    /**
     * Get a message string
     *
     * @param  string $name The key of the message
     *
     * @return string       The message
     *
     * @see AppValidator::__construct()
     *
     * @since 2.0
     */
    public function getMessage($name) {
        return isset($this->_messages[$name]) ? $this->_messages[$name] : '';
    }

    /**
     * Check if a value is empty (either null, an empty array or an emtpy string)
     *
     * @param  mixed  $value A value to check
     *
     * @return boolean        If the value is empty
     *
     * @since 2.0
     */
    protected function isEmpty($value) {
        return in_array($value, array(null, '', array()), true);
    }

    /**
     * If the validator has a given option
     *
     * @param  string  $name The option key
     *
     * @return boolean       True if that option is set
     *
     * @since 2.0
     */
    public function hasOption($name) {
        return isset($this->_options[$name]);
    }

    /**
     * Get an option valu
     *
     * @param  string $name The option key
     *
     * @return mixed       The option value
     *
     * @since 2.0
     */
    public function getOption($name) {
        if ($this->hasOption($name)) {
            return $this->_options[$name];
        }
        return null;
    }

    /**
     * Add an option to the validator
     *
     * @param string $name  The option key
     * @param mixed  $value The option value
     *
     * @return  AppValidator    $this for chaining support
     *
     * @see AppValidator::__construct()
     *
     * @since 2.0
     */
    public function addOption($name, $value = null) {
        $this->_options[$name] = $value;
        return $this;
    }

    /**
     * Set a a list of options
     *
     * @param array $options The list of options to set
     *
     * @see AppValidator::__construct()
     *
     * @since 2.0
     */
    public function setOptions($options = array()) {
        $this->_options = $options;
        return $this;
    }

    /**
     * Remove an option
     *
     * @param  string $name The option key
     *
     * @see AppValidator::__construct()
     *
     * @since 2.0
     */
	public function removeOption($name) {
		if (isset($this->_options[$name])) {
			unset($this->_options);
		}
	}

    /**
     * Get the "empty_value" option status
     *
     * @return boolean  If the "empty_value" option is set
     *
     * @since 2.0
     */
    public function getEmptyValue() {
        return $this->getOption('empty_value');
    }

    /**
     * perform a clean operation
     *
     * @param  mixed $value The value to clean
     *
     * @return mixed        the cleaned value
     *
     * @since 2.0
     */
    protected function _doClean($value) {
        return $value;
    }

}

/**
 * Password Validator
 *
 * @package Component.Classes.Validators
 */
class AppValidatorPass extends AppValidator {

    /**
     * Clean the value
     *
     * @param  mixed $value The value to clean
     *
     * @return mixed        The cleaned value
     *
     * @see AppValidator::clean()
     *
     * @since 2.0
     */
    public function clean($value) {
        return $this->_doClean($value);
    }

    /**
     * Perform the actual clean operation
     *
     * @param  mixed $value the value to clean
     *
     * @return mixed        The cleaned value
     *
     * @since 2.0
     */
    protected function _doClean($value) {
        return $value;
    }
}

/**
 * String Validator
 *
 * @package Component.Classes.Validators
 */
class AppValidatorString extends AppValidator {

    /**
     * Clean a value, forcing it to be a string
     *
     * @param  mixed $value the value to clean
     *
     * @return string        the clean value as a string
     *
     * @see AppValidator::clean()
     *
     * @since 2.0
     */
    protected function _doClean($value) {
        $clean = (string) $value;

        return $clean;
    }

    /**
     * Get the string emtpy value
     *
     * @return string the empty string
     *
     * @since 2.0
     */
    public function getEmptyValue() {
        return '';
    }

}

/**
 * TextFilter Validator
 *
 * @package Component.Classes.Validators
 */
class AppValidatorTextFilter extends AppValidatorString {

    /**
     * Clean a value, using joomla's textfilters options
     *
     * @param  mixed $value the value to clean
     *
     * @return string        the clean value as a string
     *
     * @see AppValidator::clean()
     *
     * @since 2.0
     */
    protected function _doClean($value) {
        $clean = parent::_doClean($value);
        $clean = $this->app->string->applyTextFilters($clean);

        return $clean;
    }
}

/**
 * Integer Validator
 *
 * @package Component.Classes.Validators
 */
class AppValidatorInteger extends AppValidator {

    /**
     * Configure the validator, adding the "number" Message
     *
     * @param  array  $options  The list of options to add
     * @param  array  $messages The list of messages to add
     *
     * @since 2.0
     */
    protected function _configure($options = array(), $messages = array()) {
        $this->addMessage('number', 'This is not an integer.');
    }

    /**
     * Performs the clean operation, forcing the value to be an integer
     *
     * @param  mixed $value The value to clean
     *
     * @return int        The clean value as an integer
     *
     * @since 2.0
     */
    protected function _doClean($value) {

        $clean = intval($value);

        if (strval($clean) != $value) {
            throw new AppValidatorException($this->getMessage('number'));
        }

        return $clean;
    }

    /**
     * Get the integer empty value, 0
     *
     * @return int Returns 0
     *
     * @since 2.0
     */
    public function getEmptyValue() {
        return 0;
    }

}

/**
 * Number validator
 *
 * @package Component.Classes.Validators
 */
class AppValidatorNumber extends AppValidator {

    /**
     * Configure the validator, adding the "number" message
     *
     * @param  array  $options  The list of options to add
     * @param  array  $messages The list of messages to add
     *
     * @since 2.0
     */
    protected function _configure($options = array(), $messages = array()) {
        $this->addMessage('number', 'This is not a number.');
    }

    /**
     * Perform the actual clean, forcing it to be a float number
     *
     * @param  mixed $value The value to clean
     *
     * @return float        The value to clean, as a float
     *
     * @since 2.0
     */
    protected function _doClean($value) {

        if (!is_numeric($value)) {
            throw new AppValidatorException($this->getMessage('number'));
        }

        $clean = floatval($value);

        return $clean;
    }

    /**
     * Get the empty value as a float, 0.0
     *
     * @return float Returns 0.0
     *
     * @since 2.0
     */
    public function getEmptyValue() {
        return 0.0;
    }

}

/**
 * File validator
 *
 * @package Component.Classes.Validators
 */
class AppValidatorFile extends AppValidator {

    /**
     * Configure the Validator, adding options and messages regarding file validation
     *
     * @param  array  $options  The list of options to add
     * @param  array  $messages The list of messages to add
     *
     * @throws AppValidatorException    If file uploads are disabled
     *
     * @since 2.0
     */
    protected function _configure($options = array(), $messages = array()) {
        if (!ini_get('file_uploads')) {
            throw new AppValidatorException('File uploads are disabled.');
        }

		$this->addOption('max_size');
        $this->addOption('mime_types');
		$this->addOption('mime_type_group');
		$this->addOption('extension');

		$this->addMessage('extension', 'This is not a valid extension.');
        $this->addMessage('max_size', 'File is too large (max %s KB).');
        $this->addMessage('mime_types', 'Invalid mime type.');
		$this->addMessage('mime_type_group', 'Invalid mime type.');
        $this->addMessage('partial', 'The uploaded file was only partially uploaded.');
        $this->addMessage('no_file', 'No file was uploaded.');
        $this->addMessage('no_tmp_dir', 'Missing a temporary folder.');
        $this->addMessage('cant_write', 'Failed to write file to disk.');
        $this->addMessage('err_extension', 'File upload stopped by extension.');

    }

    /**
     * Clean the file value
     *
     * @param  mixed $value The value to clean
     *
     * @return mixed        The cleaned value
     *
     * @see AppValidator::clean()
     *
     * @since 2.0
     */
    public function clean($value) {
        if (!is_array($value) || !isset($value['tmp_name'])) {
			throw new AppValidatorException($this->getMessage('invalid'));
        }

        if (!isset($value['name'])) {
			$value['name'] = '';
        }

        $value['name'] = JFile::makeSafe($value['name']);

        if (!isset($value['error'])) {
			$value['error'] = UPLOAD_ERR_OK;
        }

        if (!isset($value['size'])) {
			$value['size'] = filesize($value['tmp_name']);
        }

        if (!isset($value['type'])) {
            $value['type'] = 'application/octet-stream';
        }

        switch ($value['error']) {
			case UPLOAD_ERR_INI_SIZE:
				throw new AppValidatorException(sprintf($this->getMessage('max_size'), $this->returnBytes(@ini_get('upload_max_filesize')) / 1024), UPLOAD_ERR_INI_SIZE);
			case UPLOAD_ERR_FORM_SIZE:
				throw new AppValidatorException($this->getMessage('max_size'), UPLOAD_ERR_FORM_SIZE);
			case UPLOAD_ERR_PARTIAL:
				throw new AppValidatorException($this->getMessage('partial'), UPLOAD_ERR_PARTIAL);
			case UPLOAD_ERR_NO_FILE:
				throw new AppValidatorException($this->getMessage('no_file'), UPLOAD_ERR_NO_FILE);
			case UPLOAD_ERR_NO_TMP_DIR:
				throw new AppValidatorException($this->getMessage('no_tmp_dir'), UPLOAD_ERR_NO_TMP_DIR);
			case UPLOAD_ERR_CANT_WRITE:
				throw new AppValidatorException($this->getMessage('cant_write'), UPLOAD_ERR_CANT_WRITE);
			case UPLOAD_ERR_EXTENSION:
				throw new AppValidatorException($this->getMessage('err_extension'), UPLOAD_ERR_EXTENSION);
        }

        // check mime type
        if ($this->hasOption('mime_types')) {
            $mime_types = $this->getOption('mime_types') ? $this->getOption('mime_types') : array();
            if (!in_array($value['type'], array_map('strtolower', $mime_types))) {
                throw new AppValidatorException($this->getMessage('mime_types'));
            }
        }

		// check mime type group
		if ($this->hasOption('mime_type_group')) {
			if (!in_array($value['type'], $this->_getGroupMimeTypes($this->getOption('mime_type_group')))) {
                throw new AppValidatorException($this->getMessage('mime_type_group'));
            }
		}

        // check file size
        if ($this->hasOption('max_size') && $this->getOption('max_size') < (int) $value['size']) {
			throw new AppValidatorException(sprintf(JText::_($this->getMessage('max_size')), ($this->getOption('max_size') / 1024)));
        }

		// check extension
		if ($this->hasOption('extension') && !in_array($this->app->filesystem->getExtension($value['name']), $this->getOption('extension'))) {
			throw new AppValidatorException($this->getMessage('extension'));
        }

        return $value;
    }

    /**
     * Get the mime type for a group
     *
     * @param  string $group The group
     *
     * @return array        The list of mime types
     *
     * @see FilesystemHelper::getMimeMapping()
     *
     * @since 2.0
     */
	protected function _getGroupMimeTypes($group) {
		$mime_types = $this->app->data->create($this->app->filesystem->getMimeMapping());
		$mime_types = $mime_types->flattenRecursive();
		$mime_types = array_filter($mime_types, create_function('$a', 'return preg_match("/^'.$group.'\//i", $a);'));
		return array_map('strtolower', $mime_types);
	}

    /**
     * Get the size string in bytes
     *
     * @param  string $size_str The size to convert (Mb, GB, KB)
     *
     * @return int           The size in bytes
     *
     * @since 2.0
     */
	protected function returnBytes ($size_str) {
	    switch (substr ($size_str, -1)) {
	        case 'M': case 'm': return (int) $size_str * 1048576;
	        case 'K': case 'k': return (int) $size_str * 1024;
	        case 'G': case 'g': return (int) $size_str * 1073741824;
	        default: return $size_str;
	    }
	}

}

/**
 * Date Validator
 *
 * @package Component.Classes.Validators
 */
class AppValidatorDate extends AppValidatorString {

    /**
     * Configure the validator, adding options and messages for the date validation
     *
     * @param  array  $options  The list of options
     * @param  array  $messages The list of messages
     *
     * @since 2.0
     */
    protected function _configure($options = array(), $messages = array()) {
		$this->addOption('date_format_regex', '/^((\d{2}|\d{4}))-(\d{1,2})-(\d{1,2})(\s(\d{1,2}):(\d{1,2}):(\d{1,2}))?$/');
		$this->addOption('date_format', '%Y-%m-%d %H:%M:%S');
		$this->addOption('allow_db_null_date', false);
		$this->addOption('db_null_date', $this->app->database->getNullDate());
		$this->addMessage('bad_format', '"%s" is not a valid date.');
	}

    /**
     * Performs the real clean, convering the value to the configured date format
     *
     * @param  mixed $value The value to clean
     *
     * @return string        The cleaned value
     *
     * @throws AppValidatorException If the format is not configured or the date is not in a recognized format
     *
     * @since 2.0
     */
    protected function _doClean($value) {

		// init vars
		$value = parent::_doClean($value);

		if (!preg_match($this->getOption('date_format_regex'), $value)) {
			throw new AppValidatorException(sprintf($this->getMessage('bad_format'), $value));
		}

		if ($this->getOption('allow_db_null_date') && $value == $this->getOption('db_null_date')) {
			return $value;
		}

		$clean = strtotime($value);

		if (empty($clean)) {
			throw new AppValidatorException(sprintf($this->getMessage('bad_format'), $value));
		}

		$clean = strftime($this->getOption('date_format'), $clean);
		return $clean;

    }

}

/**
 * Base class for validating regular expression based strings
 *
 * @package Component.Classes.Validators
 */
abstract class AppValidatorRegex extends AppValidatorString {

    /**
     * Performs the real clean, checking the pattern
     *
     * @param  mixed $value The value to clean
     *
     * @return string        The cleaned regexp
     *
     * @throws AppValidatorException If no pattern is configured
     *
     * @since 2.0
     */
    protected function _doClean($value) {

        $clean = parent::_doClean($value);

        if ($pattern = $this->getPattern()) {
            if (!preg_match($pattern, $clean)) {
                throw new AppValidatorException($this->getMessage('pattern'));
            }
        }

        return $clean;
    }

    /**
     * Set a pattern for the regular expression
     *
     * @param string $pattern The regular expression pattern
     *
     * @return AppValidatorRegex $this for chaining support
     *
     * @since 2.0
     */
    public function setPattern($pattern) {
        $this->addOption('pattern', $pattern);
        return $this;
    }

    /**
     * Get the regular expression pattern
     *
     * @return string The regular expression pattern
     *
     * @since 2.0
     */
    public function getPattern() {
        return $this->getOption('pattern');
    }

}

/**
 * Email validator
 *
 * @package Component.Classes.Validators
 */
class AppValidatorEmail extends AppValidatorRegex {

    const REGEX_EMAIL = '/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i';

    /**
     * Configure the validator, adding the email regexp and the message for an invalid email
     *
     * @param  array  $options  The list of options
     * @param  array  $messages The list of messages
     *
     * @since 2.0
     */
    protected function _configure($options = array(), $messages = array()) {
        $this->setPattern(self::REGEX_EMAIL);
        $this->addMessage('pattern', 'Please enter a valid email address.');
    }

}

/**
 * Url Validator
 *
 * @package Component.Classes.Validators
 */
class AppValidatorUrl extends AppValidatorRegex {

    const REGEX_URL ='/^(%s):\/\/(([a-z0-9-\\x80-\\xff]+\.)+[a-z]{2,6}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(:[0-9]+)?(\/?|\/\S+)$/i';

    /**
     * Configure the validator, adding the protocol options, the url regexp and the message
     *
     * @param  array  $options  The list of options
     * @param  array  $messages The list of messages
     *
     * @since 2.0
     */
    protected function _configure($options = array(), $messages = array()) {
        $this->addOption('protocols', array('http', 'https', 'ftp', 'ftps'));
        $this->setPattern(sprintf(self::REGEX_URL, implode('|', $this->getOption('protocols'))));
        $this->addMessage('pattern', 'Please enter a valid URL.');
    }

}

/**
 * Validator to clean multiple values
 *
 * @package Component.Classes.Validators
 */
class AppValidatorForeach extends AppValidator {

    /**
     * The validator to use to validate each item in the lsit
     *
     * @var AppValidator
     * @since 2.0
     */
    protected $_validator;

    /**
     * Class Constructor
     *
     * @param AppValidator $validator The validator to use
     * @param array  $options   The list of options
     * @param array  $messages  The list of messages
     */
    public function __construct($validator, $options = array(), $messages = array()) {

        parent::__construct($options, $messages);

        $this->_validator = $validator;

    }

    /**
     * Get the validator we're using for validating the single items
     *
     * @return AppValidator The validator
     *
     * @since 2.0
     */
    public function getValidator() {

        if (!$this->_validator) {
            $this->_validator = new AppValidatorPass();
        }

        return $this->_validator;

    }

    /**
     * Performs the cleaning on each item
     *
     * @param  mixed $value The value to clean
     *
     * @return mixed        The cleaned value
     *
     * @since 2.0
     */
    protected function _doClean($value) {
        $clean = array();

        if (is_array($value)) {

            foreach ($value as $key => $single_value) {
                $clean[$key] = $this->getValidator()->clean($single_value);
            }

        } else {
            throw new AppValidatorException($this->getMessage('invalid'));
        }

        return $clean;

    }

    /**
     * Get the empty value, i.e.: an empty array
     *
     * @return array The empty array
     *
     * @since 2.0
     */
    public function getEmptyValue() {
        return array();
    }

}

/**
 * Exception for the validator classes
 *
 * @see AppValidator
 */
class AppValidatorException extends AppException {

    /**
     * Converts the exception to string using the error string
     *
     * @return string The error message
     */
	public function __toString() {
		return JText::_($this->getMessage());
	}

}