diff options
Diffstat (limited to 'vendor/ipl/validator')
-rw-r--r-- | vendor/ipl/validator/LICENSE | 21 | ||||
-rw-r--r-- | vendor/ipl/validator/composer.json | 23 | ||||
-rw-r--r-- | vendor/ipl/validator/src/BaseValidator.php | 11 | ||||
-rw-r--r-- | vendor/ipl/validator/src/CallbackValidator.php | 45 | ||||
-rw-r--r-- | vendor/ipl/validator/src/DateTimeValidator.php | 65 | ||||
-rw-r--r-- | vendor/ipl/validator/src/PrivateKeyValidator.php | 33 | ||||
-rw-r--r-- | vendor/ipl/validator/src/ValidatorChain.php | 284 | ||||
-rw-r--r-- | vendor/ipl/validator/src/X509CertValidator.php | 33 |
8 files changed, 515 insertions, 0 deletions
diff --git a/vendor/ipl/validator/LICENSE b/vendor/ipl/validator/LICENSE new file mode 100644 index 0000000..b247ccf --- /dev/null +++ b/vendor/ipl/validator/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2020 Icinga GmbH https://www.icinga.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/ipl/validator/composer.json b/vendor/ipl/validator/composer.json new file mode 100644 index 0000000..0d66bee --- /dev/null +++ b/vendor/ipl/validator/composer.json @@ -0,0 +1,23 @@ +{ + "name": "ipl/validator", + "type": "library", + "description": "Icinga PHP Library - Common validators and validator chaining", + "homepage": "https://github.com/Icinga/ipl-validator", + "license": "MIT", + "require": { + "php": ">=7.2", + "ext-openssl": "*", + "ipl/stdlib": ">=0.12.0", + "ipl/i18n": ">=0.2.0" + }, + "autoload": { + "psr-4": { + "ipl\\Validator\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "ipl\\Tests\\Validator\\": "tests" + } + } +} diff --git a/vendor/ipl/validator/src/BaseValidator.php b/vendor/ipl/validator/src/BaseValidator.php new file mode 100644 index 0000000..8faa79b --- /dev/null +++ b/vendor/ipl/validator/src/BaseValidator.php @@ -0,0 +1,11 @@ +<?php + +namespace ipl\Validator; + +use ipl\Stdlib\Contract\Validator; +use ipl\Stdlib\Messages; + +abstract class BaseValidator implements Validator +{ + use Messages; +} diff --git a/vendor/ipl/validator/src/CallbackValidator.php b/vendor/ipl/validator/src/CallbackValidator.php new file mode 100644 index 0000000..611a45e --- /dev/null +++ b/vendor/ipl/validator/src/CallbackValidator.php @@ -0,0 +1,45 @@ +<?php + +namespace ipl\Validator; + +/** + * Validator that uses a callback for the actual validation + * + * # Example Usage + * ``` + * $dedup = new CallbackValidator(function ($value, CallbackValidator $validator) { + * if (already_exists_in_database($value)) { + * $validator->addMessage('Record already exists in database'); + * + * return false; + * } + * + * return true; + * }); + * + * $dedup->isValid($id); + * ``` + */ +class CallbackValidator extends BaseValidator +{ + /** @var callable Validation callback */ + protected $callback; + + /** + * Create a new callback validator + * + * @param callable $callback Validation callback + */ + public function __construct(callable $callback) + { + $this->callback = $callback; + } + + public function isValid($value) + { + // Multiple isValid() calls must not stack validation messages + $this->clearMessages(); + + return call_user_func($this->callback, $value, $this); + } +} diff --git a/vendor/ipl/validator/src/DateTimeValidator.php b/vendor/ipl/validator/src/DateTimeValidator.php new file mode 100644 index 0000000..1e35d61 --- /dev/null +++ b/vendor/ipl/validator/src/DateTimeValidator.php @@ -0,0 +1,65 @@ +<?php + +namespace ipl\Validator; + +use DateTime; +use ipl\I18n\Translation; + +/** + * Validator for date-and-time input controls + */ +class DateTimeValidator extends BaseValidator +{ + use Translation; + + /** @var string Default date time format */ + const FORMAT = 'Y-m-d\TH:i:s'; + + /** @var bool Whether to use the default date time format */ + protected $local; + + /** + * Create a new date-and-time input control validator + * + * @param bool $local + */ + public function __construct($local = true) + { + $this->local = (bool) $local; + } + + /** + * Check whether the given date time is valid + * + * @param string|DateTime $value + * + * @return bool + */ + public function isValid($value) + { + // Multiple isValid() calls must not stack validation messages + $this->clearMessages(); + + if (! $value instanceof DateTime && ! is_string($value)) { + $this->addMessage($this->translate('Invalid date/time given.')); + + return false; + } + + if (! $value instanceof DateTime) { + $format = $this->local === true ? static::FORMAT : DateTime::RFC3339; + $dateTime = DateTime::createFromFormat($format, $value); + + if ($dateTime === false || $dateTime->format($format) !== $value) { + $this->addMessage(sprintf( + $this->translate("Date/time string not in the expected format: %s"), + $format + )); + + return false; + } + } + + return true; + } +} diff --git a/vendor/ipl/validator/src/PrivateKeyValidator.php b/vendor/ipl/validator/src/PrivateKeyValidator.php new file mode 100644 index 0000000..b629398 --- /dev/null +++ b/vendor/ipl/validator/src/PrivateKeyValidator.php @@ -0,0 +1,33 @@ +<?php + +namespace ipl\Validator; + +use ipl\I18n\Translation; + +/** + * Validates a private key + */ +class PrivateKeyValidator extends BaseValidator +{ + use Translation; + + public function isValid($value) + { + // Multiple isValid() calls must not stack validation messages + $this->clearMessages(); + + if (preg_match('/\A\s*\w+:/', $value)) { + $this->addMessage($this->translate('URLs are not allowed')); + + return false; + } + + if (openssl_pkey_get_private($value) === false) { + $this->addMessage($this->translate('Not a valid PEM-encoded private key')); + + return false; + } + + return true; + } +} diff --git a/vendor/ipl/validator/src/ValidatorChain.php b/vendor/ipl/validator/src/ValidatorChain.php new file mode 100644 index 0000000..2860a12 --- /dev/null +++ b/vendor/ipl/validator/src/ValidatorChain.php @@ -0,0 +1,284 @@ +<?php + +namespace ipl\Validator; + +use Countable; +use InvalidArgumentException; +use ipl\Stdlib\Contract\Validator; +use ipl\Stdlib\Messages; +use ipl\Stdlib\Plugins; +use ipl\Stdlib\PriorityQueue; +use IteratorAggregate; +use SplObjectStorage; +use Traversable; +use UnexpectedValueException; + +use function ipl\Stdlib\get_php_type; + +class ValidatorChain implements Countable, IteratorAggregate, Validator +{ + use Messages; + use Plugins; + + /** Default priority at which validators are added */ + const DEFAULT_PRIORITY = 1; + + /** @var PriorityQueue Validator chain */ + protected $validators; + + /** @var SplObjectStorage Validators that break the chain on failure */ + protected $validatorsThatBreakTheChain; + + /** + * Create a new validator chain + */ + public function __construct() + { + $this->validators = new PriorityQueue(); + $this->validatorsThatBreakTheChain = new SplObjectStorage(); + + $this->addDefaultPluginLoader('validator', __NAMESPACE__, 'Validator'); + } + + /** + * Get the validators that break the chain + * + * @return SplObjectStorage + */ + public function getValidatorsThatBreakTheChain() + { + return $this->validatorsThatBreakTheChain; + } + + /** + * Add a validator to the chain + * + * If $breakChainOnFailure is true and the validator fails, subsequent validators won't be executed. + * + * @param Validator $validator + * @param bool $breakChainOnFailure + * @param int $priority Priority at which to add validator + * + * @return $this + * + */ + public function add(Validator $validator, $breakChainOnFailure = false, $priority = self::DEFAULT_PRIORITY) + { + $this->validators->insert($validator, $priority); + + if ($breakChainOnFailure) { + $this->validatorsThatBreakTheChain->attach($validator); + } + + return $this; + } + + /** + * Add the validators from the given validator specification to the chain + * + * @param iterable $validators + * + * @return $this + * + * @throws InvalidArgumentException If $validators is not iterable or if the validator specification is invalid + */ + public function addValidators($validators) + { + if ($validators instanceof static) { + return $this->merge($validators); + } + + if (! is_iterable($validators)) { + throw new InvalidArgumentException(sprintf( + '%s expects parameter one to be iterable, got %s instead', + __METHOD__, + get_php_type($validators) + )); + } + + foreach ($validators as $name => $validator) { + $breakChainOnFailure = false; + + if (! $validator instanceof Validator) { + if (is_int($name)) { + if (! is_array($validator)) { + $name = $validator; + $validator = null; + } else { + if (! isset($validator['name'])) { + throw new InvalidArgumentException( + 'Invalid validator array specification: Key "name" is missing' + ); + } + + $name = $validator['name']; + unset($validator['name']); + } + } + + if (is_array($validator)) { + if (isset($validator['options'])) { + $options = $validator['options']; + + unset($validator['options']); + + $validator = array_merge($validator, $options); + } + + if (isset($validator['break_chain_on_failure'])) { + $breakChainOnFailure = $validator['break_chain_on_failure']; + + unset($validator['break_chain_on_failure']); + } + } + + $validator = $this->createValidator($name, $validator); + } + + $this->add($validator, $breakChainOnFailure); + } + + return $this; + } + + /** + * Add a validator loader + * + * @param string $namespace Namespace of the validators + * @param string $postfix Validator name postfix, if any + * + * @return $this + */ + public function addValidatorLoader($namespace, $postfix = null) + { + $this->addPluginLoader('validator', $namespace, $postfix); + + return $this; + } + + /** + * Remove all validators from the chain + * + * @return $this + */ + public function clearValidators() + { + $this->validators = new PriorityQueue(); + $this->validatorsThatBreakTheChain = new SplObjectStorage(); + + return $this; + } + + /** + * Create a validator from the given name and options + * + * @param string $name + * @param mixed $options + * + * @return Validator + * + * @throws InvalidArgumentException If the validator to load is unknown + * @throws UnexpectedValueException If a validator loader did not return an instance of {@link Validator} + */ + public function createValidator($name, $options = null) + { + $class = $this->loadPlugin('validator', $name); + + if (! $class) { + throw new InvalidArgumentException(sprintf( + "Can't load validator '%s'. Validator unknown", + $name + )); + } + + if (empty($options)) { + $validator = new $class(); + } else { + $validator = new $class($options); + } + + if (! $validator instanceof Validator) { + throw new UnexpectedValueException(sprintf( + "%s expects loader to return an instance of %s for validator '%s', got %s instead", + __METHOD__, + Validator::class, + $name, + get_php_type($validator) + )); + } + + return $validator; + } + + /** + * Merge all validators from the given chain into this one + * + * @param ValidatorChain $validatorChain + * + * @return $this + */ + public function merge(ValidatorChain $validatorChain) + { + $validatorsThatBreakTheChain = $validatorChain->getValidatorsThatBreakTheChain(); + + foreach ($validatorChain->validators->yieldAll() as $priority => $validator) { + $this->add($validator, $validatorsThatBreakTheChain->contains($validator), $priority); + } + + return $this; + } + + public function __clone() + { + $this->validators = clone $this->validators; + } + + /** + * Export the chain as array + * + * @return array + */ + public function toArray() + { + return array_values(iterator_to_array($this)); + } + + public function count(): int + { + return count($this->validators); + } + + /** + * Get an iterator for traversing the validators + * + * @return Validator[]|PriorityQueue + */ + public function getIterator(): Traversable + { + // Clone validators because the PriorityQueue acts as a heap and thus items are removed upon iteration + return clone $this->validators; + } + + public function isValid($value) + { + $this->clearMessages(); + + $valid = true; + + foreach ($this as $validator) { + if ($validator->isValid($value)) { + continue; + } + + $valid = false; + + $this->addMessages($validator->getMessages()); + + if ($this->validatorsThatBreakTheChain->contains($validator)) { + break; + } + } + + return $valid; + } +} diff --git a/vendor/ipl/validator/src/X509CertValidator.php b/vendor/ipl/validator/src/X509CertValidator.php new file mode 100644 index 0000000..7dfc4f7 --- /dev/null +++ b/vendor/ipl/validator/src/X509CertValidator.php @@ -0,0 +1,33 @@ +<?php + +namespace ipl\Validator; + +use ipl\I18n\Translation; + +/** + * Validates an X.509 certificate + */ +class X509CertValidator extends BaseValidator +{ + use Translation; + + public function isValid($value) + { + // Multiple isValid() calls must not stack validation messages + $this->clearMessages(); + + if (preg_match('/\A\s*\w+:/', $value)) { + $this->addMessage($this->translate('URLs are not allowed')); + + return false; + } + + if (openssl_x509_parse($value) === false) { + $this->addMessage($this->translate('Not a valid PEM-encoded X.509 certificate')); + + return false; + } + + return true; + } +} |