File: /home/boxelikax/public_html/demoltec.com/laminas.tar
laminas-validator/src/Iban.php 0000644 00000024366 15240152633 0012340 0 ustar 00 <?php
namespace Laminas\Validator;
use Laminas\Stdlib\ArrayUtils;
use Traversable;
use function array_key_exists;
use function in_array;
use function intval;
use function is_string;
use function preg_match;
use function str_replace;
use function strlen;
use function strtoupper;
use function substr;
/**
* Validates IBAN Numbers (International Bank Account Numbers)
*/
class Iban extends AbstractValidator
{
public const NOTSUPPORTED = 'ibanNotSupported';
public const SEPANOTSUPPORTED = 'ibanSepaNotSupported';
public const FALSEFORMAT = 'ibanFalseFormat';
public const CHECKFAILED = 'ibanCheckFailed';
/**
* Validation failure message template definitions
*
* @var array<string, string>
*/
protected $messageTemplates = [
self::NOTSUPPORTED => 'Unknown country within the IBAN',
self::SEPANOTSUPPORTED => 'Countries outside the Single Euro Payments Area (SEPA) are not supported',
self::FALSEFORMAT => 'The input has a false IBAN format',
self::CHECKFAILED => 'The input has failed the IBAN check',
];
/**
* Optional country code by ISO 3166-1
*
* @var string|null
*/
protected $countryCode;
/**
* Optionally allow IBAN codes from non-SEPA countries. Defaults to true
*
* @var bool
*/
protected $allowNonSepa = true;
/**
* The SEPA country codes
*
* @var string[] ISO 3166-1 codes
*/
protected static $sepaCountries = [
'AT',
'BE',
'BG',
'CY',
'CZ',
'DK',
'FO',
'GL',
'EE',
'FI',
'FR',
'DE',
'GI',
'GR',
'HU',
'IS',
'IE',
'IT',
'LV',
'LI',
'LT',
'LU',
'MT',
'MC',
'NL',
'NO',
'PL',
'PT',
'RO',
'SK',
'SI',
'ES',
'SE',
'CH',
'GB',
'SM',
'HR',
];
/**
* IBAN regexes by country code
*
* @var array
*/
protected static $ibanRegex = [
'AD' => 'AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}',
'AE' => 'AE[0-9]{2}[0-9]{3}[0-9]{16}',
'AL' => 'AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}',
'AT' => 'AT[0-9]{2}[0-9]{5}[0-9]{11}',
'AZ' => 'AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}',
'BA' => 'BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}',
'BE' => 'BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}',
'BG' => 'BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}',
'BH' => 'BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}',
'BR' => 'BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z][A-Z0-9]',
'BY' => 'BY[0-9]{2}[A-Z0-9]{4}[0-9]{4}[A-Z0-9]{16}',
'CH' => 'CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}',
'CR' => 'CR[0-9]{2}[0-9]{3}[0-9]{14}',
'CY' => 'CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}',
'CZ' => 'CZ[0-9]{2}[0-9]{20}',
'DE' => 'DE[0-9]{2}[0-9]{8}[0-9]{10}',
'DO' => 'DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}',
'DK' => 'DK[0-9]{2}[0-9]{14}',
'EE' => 'EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}',
'ES' => 'ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}',
'FI' => 'FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}',
'FO' => 'FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}',
'FR' => 'FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}',
'GB' => 'GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}',
'GE' => 'GE[0-9]{2}[A-Z]{2}[0-9]{16}',
'GI' => 'GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}',
'GL' => 'GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}',
'GR' => 'GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}',
'GT' => 'GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}',
'HR' => 'HR[0-9]{2}[0-9]{7}[0-9]{10}',
'HU' => 'HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}',
'IE' => 'IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}',
'IL' => 'IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}',
'IS' => 'IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}',
'IT' => 'IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}',
'KW' => 'KW[0-9]{2}[A-Z]{4}[0-9]{22}',
'KZ' => 'KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}',
'LB' => 'LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}',
'LI' => 'LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}',
'LT' => 'LT[0-9]{2}[0-9]{5}[0-9]{11}',
'LU' => 'LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}',
'LV' => 'LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}',
'MC' => 'MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}',
'MD' => 'MD[0-9]{2}[A-Z0-9]{20}',
'ME' => 'ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}',
'MK' => 'MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}',
'MR' => 'MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}',
'MT' => 'MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}',
'MU' => 'MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}',
'NL' => 'NL[0-9]{2}[A-Z]{4}[0-9]{10}',
'NO' => 'NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}',
'UA' => 'UA[0-9]{2}[0-9]{6}[0-9]{19}',
'PK' => 'PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}',
'PL' => 'PL[0-9]{2}[0-9]{8}[0-9]{16}',
'PS' => 'PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}',
'PT' => 'PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}',
'RO' => 'RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}',
'RS' => 'RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}',
'SA' => 'SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}',
'SE' => 'SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}',
'SI' => 'SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}',
'SK' => 'SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}',
'SM' => 'SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}',
'TN' => 'TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}',
'TR' => 'TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}',
'VG' => 'VG[0-9]{2}[A-Z]{4}[0-9]{16}',
];
/**
* Sets validator options
*
* @param array|Traversable $options OPTIONAL
*/
public function __construct($options = [])
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (array_key_exists('country_code', $options)) {
$this->setCountryCode($options['country_code']);
}
if (array_key_exists('allow_non_sepa', $options)) {
$this->setAllowNonSepa($options['allow_non_sepa']);
}
parent::__construct($options);
}
/**
* Returns the optional country code by ISO 3166-1
*
* @return string|null
*/
public function getCountryCode()
{
return $this->countryCode;
}
/**
* Sets an optional country code by ISO 3166-1
*
* @param string|null $countryCode
* @return $this provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setCountryCode($countryCode = null)
{
if ($countryCode !== null) {
$countryCode = (string) $countryCode;
if (! isset(static::$ibanRegex[$countryCode])) {
throw new Exception\InvalidArgumentException(
"Country code '{$countryCode}' invalid by ISO 3166-1 or not supported"
);
}
}
$this->countryCode = $countryCode;
return $this;
}
/**
* Returns the optional allow non-sepa countries setting
*
* @return bool
*/
public function allowNonSepa()
{
return $this->allowNonSepa;
}
/**
* Sets the optional allow non-sepa countries setting
*
* @param bool $allowNonSepa
* @return $this provides a fluent interface
*/
public function setAllowNonSepa($allowNonSepa)
{
$this->allowNonSepa = (bool) $allowNonSepa;
return $this;
}
/**
* Returns true if $value is a valid IBAN
*
* @param string $value
* @return bool
*/
public function isValid($value)
{
if (! is_string($value)) {
$this->error(self::FALSEFORMAT);
return false;
}
$value = str_replace(' ', '', strtoupper($value));
$this->setValue($value);
$countryCode = $this->getCountryCode();
if ($countryCode === null) {
$countryCode = substr($value, 0, 2);
}
if (! array_key_exists($countryCode, static::$ibanRegex)) {
$this->setValue($countryCode);
$this->error(self::NOTSUPPORTED);
return false;
}
if (! $this->allowNonSepa && ! in_array($countryCode, static::$sepaCountries)) {
$this->setValue($countryCode);
$this->error(self::SEPANOTSUPPORTED);
return false;
}
if (! preg_match('/^' . static::$ibanRegex[$countryCode] . '$/', $value)) {
$this->error(self::FALSEFORMAT);
return false;
}
$format = substr($value, 4) . substr($value, 0, 4);
$format = str_replace(
[
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
],
[
'10',
'11',
'12',
'13',
'14',
'15',
'16',
'17',
'18',
'19',
'20',
'21',
'22',
'23',
'24',
'25',
'26',
'27',
'28',
'29',
'30',
'31',
'32',
'33',
'34',
'35',
],
$format
);
$temp = intval(substr($format, 0, 1));
$len = strlen($format);
for ($x = 1; $x < $len; ++$x) {
$temp *= 10;
$temp += intval(substr($format, $x, 1));
$temp %= 97;
}
if ($temp !== 1) {
$this->error(self::CHECKFAILED);
return false;
}
return true;
}
}
laminas-validator/src/ValidatorProviderInterface.php 0000644 00000001327 15240152633 0016740 0 ustar 00 <?php
namespace Laminas\Validator;
/**
* Hint to the laminas-modulemanager ServiceListener that a module provides validators.
*
* Module classes implementing this interface hint to
* Laminas\ModuleManager\ServiceListener that they provide validators for the
* ValidatorPluginManager.
*
* For users of laminas-mvc/laminas-modulemanager v2, this poses no backwards-compatibility
* break as the method getValidatorConfig is still duck-typed within Laminas\Validator\Module
* when providing configuration to the ServiceListener.
*/
interface ValidatorProviderInterface
{
/**
* Provide plugin manager configuration for validators.
*
* @return array
*/
public function getValidatorConfig();
}
laminas-validator/src/File/NotExists.php 0000644 00000003404 15240152633 0014274 0 ustar 00 <?php
namespace Laminas\Validator\File;
use function file_exists;
use const DIRECTORY_SEPARATOR;
/**
* Validator which checks if the destination file does not exist
*/
class NotExists extends Exists
{
use FileInformationTrait;
/**
* @const string Error constants
*/
public const DOES_EXIST = 'fileNotExistsDoesExist';
/** @var array Error message templates */
protected $messageTemplates = [
self::DOES_EXIST => 'File exists',
];
/**
* Returns true if and only if the file does not exist in the set destinations
*
* @param string|array $value Real file to check for existence
* @param array $file File data from \Laminas\File\Transfer\Transfer (optional)
* @return bool
*/
public function isValid($value, $file = null)
{
$fileInfo = $this->getFileInfo($value, $file, false, true);
$this->setValue($fileInfo['filename']);
$check = false;
$directories = $this->getDirectory(true);
if (! isset($directories)) {
$check = true;
if (file_exists($fileInfo['file'])) {
$this->error(self::DOES_EXIST);
return false;
}
} else {
foreach ($directories as $directory) {
if (! isset($directory) || '' === $directory) {
continue;
}
$check = true;
if (file_exists($directory . DIRECTORY_SEPARATOR . $fileInfo['basename'])) {
$this->error(self::DOES_EXIST);
return false;
}
}
}
if (! $check) {
$this->error(self::DOES_EXIST);
return false;
}
return true;
}
}
laminas-validator/src/File/Size.php 0000644 00000023461 15240152633 0013253 0 ustar 00 <?php
namespace Laminas\Validator\File;
use Laminas\Stdlib\ErrorHandler;
use Laminas\Validator\AbstractValidator;
use Laminas\Validator\Exception;
use Traversable;
use function array_shift;
use function filesize;
use function func_get_args;
use function func_num_args;
use function is_numeric;
use function is_readable;
use function is_string;
use function round;
use function sprintf;
use function strtoupper;
use function substr;
use function trim;
/**
* Validator for the maximum size of a file up to a max of 2GB
*/
class Size extends AbstractValidator
{
use FileInformationTrait;
/**
* @const string Error constants
*/
public const TOO_BIG = 'fileSizeTooBig';
public const TOO_SMALL = 'fileSizeTooSmall';
public const NOT_FOUND = 'fileSizeNotFound';
/** @var array Error message templates */
protected $messageTemplates = [
self::TOO_BIG => "Maximum allowed size for file is '%max%' but '%size%' detected",
self::TOO_SMALL => "Minimum expected size for file is '%min%' but '%size%' detected",
self::NOT_FOUND => 'File is not readable or does not exist',
];
/** @var array Error message template variables */
protected $messageVariables = [
'min' => ['options' => 'min'],
'max' => ['options' => 'max'],
'size' => 'size',
];
/**
* Detected size
*
* @var int
*/
protected $size;
/**
* Options for this validator
*
* @var array
*/
protected $options = [
'min' => null, // Minimum file size, if null there is no minimum
'max' => null, // Maximum file size, if null there is no maximum
'useByteString' => true, // Use byte string?
];
/**
* Sets validator options
*
* If $options is an integer, it will be used as maximum file size
* As Array is accepts the following keys:
* 'min': Minimum file size
* 'max': Maximum file size
* 'useByteString': Use bytestring or real size for messages
*
* @param int|array|Traversable $options Options for the adapter
*/
public function __construct($options = null)
{
if (is_string($options) || is_numeric($options)) {
$options = ['max' => $options];
}
if (1 < func_num_args()) {
$argv = func_get_args();
array_shift($argv);
$options['max'] = array_shift($argv);
if (! empty($argv)) {
$options['useByteString'] = array_shift($argv);
}
}
parent::__construct($options);
}
/**
* Should messages return bytes as integer or as string in SI notation
*
* @param bool $byteString Use bytestring ?
* @return self
*/
public function useByteString($byteString = true)
{
$this->options['useByteString'] = (bool) $byteString;
return $this;
}
/**
* Will bytestring be used?
*
* @return bool
*/
public function getByteString()
{
return $this->options['useByteString'];
}
/**
* Returns the minimum file size
*
* @param bool $raw Whether or not to force return of the raw value (defaults off)
* @return int|string
*/
public function getMin($raw = false)
{
$min = $this->options['min'];
if (! $raw && $this->getByteString()) {
$min = $this->toByteString($min);
}
return $min;
}
/**
* Sets the minimum file size
*
* File size can be an integer or a byte string
* This includes 'B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'
* For example: 2000, 2MB, 0.2GB
*
* @param int|string $min The minimum file size
* @return $this Provides a fluent interface
* @throws Exception\InvalidArgumentException When min is greater than max.
*/
public function setMin($min)
{
if (! is_string($min) && ! is_numeric($min)) {
throw new Exception\InvalidArgumentException('Invalid options to validator provided');
}
$min = (int) $this->fromByteString($min);
$max = $this->getMax(true);
if (($max !== null) && ($min > $max)) {
throw new Exception\InvalidArgumentException(
"The minimum must be less than or equal to the maximum file size, but $min > $max"
);
}
$this->options['min'] = $min;
return $this;
}
/**
* Returns the maximum file size
*
* @param bool $raw Whether or not to force return of the raw value (defaults off)
* @return int|string
*/
public function getMax($raw = false)
{
$max = $this->options['max'];
if (! $raw && $this->getByteString()) {
$max = $this->toByteString($max);
}
return $max;
}
/**
* Sets the maximum file size
*
* File size can be an integer or a byte string
* This includes 'B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'
* For example: 2000, 2MB, 0.2GB
*
* @param int|string $max The maximum file size
* @return $this Provides a fluent interface
* @throws Exception\InvalidArgumentException When max is smaller than min.
*/
public function setMax($max)
{
if (! is_string($max) && ! is_numeric($max)) {
throw new Exception\InvalidArgumentException('Invalid options to validator provided');
}
$max = (int) $this->fromByteString($max);
$min = $this->getMin(true);
if (($min !== null) && ($max < $min)) {
throw new Exception\InvalidArgumentException(
"The maximum must be greater than or equal to the minimum file size, but $max < $min"
);
}
$this->options['max'] = $max;
return $this;
}
/**
* Retrieve current detected file size
*
* @return int
*/
protected function getSize()
{
return $this->size;
}
/**
* Set current size
*
* @param int $size
* @return $this
*/
protected function setSize($size)
{
$this->size = $size;
return $this;
}
/**
* Returns true if and only if the file size of $value is at least min and
* not bigger than max (when max is not null).
*
* @param string|array $value File to check for size
* @param array $file File data from \Laminas\File\Transfer\Transfer (optional)
* @return bool
*/
public function isValid($value, $file = null)
{
$fileInfo = $this->getFileInfo($value, $file);
$this->setValue($fileInfo['filename']);
// Is file readable ?
if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) {
$this->error(self::NOT_FOUND);
return false;
}
// limited to 4GB files
ErrorHandler::start();
$size = sprintf('%u', filesize($fileInfo['file']));
ErrorHandler::stop();
$this->size = $size;
// Check to see if it's smaller than min size
$min = $this->getMin(true);
$max = $this->getMax(true);
if (($min !== null) && ($size < $min)) {
if ($this->getByteString()) {
$this->options['min'] = $this->toByteString($min);
$this->size = $this->toByteString($size);
$this->error(self::TOO_SMALL);
$this->options['min'] = $min;
$this->size = $size;
} else {
$this->error(self::TOO_SMALL);
}
}
// Check to see if it's larger than max size
if (($max !== null) && ($max < $size)) {
if ($this->getByteString()) {
$this->options['max'] = $this->toByteString($max);
$this->size = $this->toByteString($size);
$this->error(self::TOO_BIG);
$this->options['max'] = $max;
$this->size = $size;
} else {
$this->error(self::TOO_BIG);
}
}
if ($this->getMessages()) {
return false;
}
return true;
}
/**
* Returns the formatted size
*
* @param int $size
* @return string
*/
protected function toByteString($size)
{
$sizes = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
for ($i = 0; $size >= 1024 && $i < 9; $i++) {
$size /= 1024;
}
return round($size, 2) . $sizes[$i];
}
/**
* Returns the unformatted size
*
* @param string $size
* @return float|int|string
*/
protected function fromByteString($size)
{
if (is_numeric($size)) {
return (int) $size;
}
$type = trim(substr($size, -2, 1));
$value = substr($size, 0, -1);
if (! is_numeric($value)) {
$value = trim(substr($value, 0, -1));
}
switch (strtoupper($type)) {
case 'Y':
$value *= 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024;
break;
case 'Z':
$value *= 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024;
break;
case 'E':
$value *= 1024 * 1024 * 1024 * 1024 * 1024 * 1024;
break;
case 'P':
$value *= 1024 * 1024 * 1024 * 1024 * 1024;
break;
case 'T':
$value *= 1024 * 1024 * 1024 * 1024;
break;
case 'G':
$value *= 1024 * 1024 * 1024;
break;
case 'M':
$value *= 1024 * 1024;
break;
case 'K':
$value *= 1024;
break;
default:
break;
}
return $value;
}
}
laminas-validator/src/File/Hash.php 0000644 00000011136 15240152633 0013220 0 ustar 00 <?php
namespace Laminas\Validator\File;
use Laminas\Validator\AbstractValidator;
use Laminas\Validator\Exception;
use function array_key_exists;
use function array_unique;
use function array_values;
use function func_get_arg;
use function func_num_args;
use function get_debug_type;
use function hash_algos;
use function hash_file;
use function in_array;
use function is_array;
use function is_readable;
use function is_scalar;
use function is_string;
use function sprintf;
/**
* Validator for the hash of given files
*/
class Hash extends AbstractValidator
{
use FileInformationTrait;
/**
* @const string Error constants
*/
public const DOES_NOT_MATCH = 'fileHashDoesNotMatch';
public const NOT_DETECTED = 'fileHashHashNotDetected';
public const NOT_FOUND = 'fileHashNotFound';
/** @var array Error message templates */
protected $messageTemplates = [
self::DOES_NOT_MATCH => 'File does not match the given hashes',
self::NOT_DETECTED => 'A hash could not be evaluated for the given file',
self::NOT_FOUND => 'File is not readable or does not exist',
];
/**
* Options for this validator
*
* @var string
*/
protected $options = [
'algorithm' => 'crc32',
'hash' => null,
];
/**
* Sets validator options
*
* @param string|array $options
*/
public function __construct($options = null)
{
if (
is_scalar($options) ||
(is_array($options) && ! array_key_exists('hash', $options))
) {
$options = ['hash' => $options];
}
if (1 < func_num_args()) {
$options['algorithm'] = func_get_arg(1);
}
parent::__construct($options);
}
/**
* Returns the set hash values as array, the hash as key and the algorithm the value
*
* @return array
*/
public function getHash()
{
return $this->options['hash'];
}
/**
* Sets the hash for one or multiple files
*
* @param string|array $options
* @return $this Provides a fluent interface
*/
public function setHash($options)
{
$this->options['hash'] = null;
$this->addHash($options);
return $this;
}
/**
* Adds the hash for one or multiple files
*
* @param string|array $options
* @throws Exception\InvalidArgumentException
* @return $this Provides a fluent interface
*/
public function addHash($options)
{
if (is_string($options)) {
$options = [$options];
} elseif (! is_array($options)) {
throw new Exception\InvalidArgumentException('False parameter given');
}
$known = hash_algos();
if (! isset($options['algorithm'])) {
$algorithm = $this->options['algorithm'];
} else {
$algorithm = $options['algorithm'];
unset($options['algorithm']);
}
if (! in_array($algorithm, $known)) {
throw new Exception\InvalidArgumentException("Unknown algorithm '{$algorithm}'");
}
foreach ($options as $value) {
if (! is_string($value)) {
throw new Exception\InvalidArgumentException(sprintf(
'Hash must be a string, %s received',
get_debug_type($value)
));
}
$this->options['hash'][$value] = $algorithm;
}
return $this;
}
/**
* Returns true if and only if the given file confirms the set hash
*
* @param string|array $value File to check for hash
* @param array $file File data from \Laminas\File\Transfer\Transfer (optional)
* @return bool
*/
public function isValid($value, $file = null)
{
$fileInfo = $this->getFileInfo($value, $file);
$this->setValue($fileInfo['filename']);
// Is file readable ?
if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) {
$this->error(self::NOT_FOUND);
return false;
}
$algos = array_unique(array_values($this->getHash()));
foreach ($algos as $algorithm) {
$filehash = hash_file($algorithm, $fileInfo['file']);
if ($filehash === false) {
$this->error(self::NOT_DETECTED);
return false;
}
if (isset($this->getHash()[$filehash]) && $this->getHash()[$filehash] === $algorithm) {
return true;
}
}
$this->error(self::DOES_NOT_MATCH);
return false;
}
}
laminas-validator/src/File/UploadFile.php 0000644 00000012750 15240152633 0014364 0 ustar 00 <?php
namespace Laminas\Validator\File;
use Laminas\Validator\AbstractValidator;
use Laminas\Validator\Exception;
use Psr\Http\Message\UploadedFileInterface;
use function basename;
use function is_array;
use function is_file;
use function is_string;
use function is_uploaded_file;
use const UPLOAD_ERR_CANT_WRITE;
use const UPLOAD_ERR_EXTENSION;
use const UPLOAD_ERR_FORM_SIZE;
use const UPLOAD_ERR_INI_SIZE;
use const UPLOAD_ERR_NO_FILE;
use const UPLOAD_ERR_NO_TMP_DIR;
use const UPLOAD_ERR_OK;
use const UPLOAD_ERR_PARTIAL;
/**
* Validator for the maximum size of a file up to a max of 2GB
*/
class UploadFile extends AbstractValidator
{
/**
* @const string Error constants
*/
public const INI_SIZE = 'fileUploadFileErrorIniSize';
public const FORM_SIZE = 'fileUploadFileErrorFormSize';
public const PARTIAL = 'fileUploadFileErrorPartial';
public const NO_FILE = 'fileUploadFileErrorNoFile';
public const NO_TMP_DIR = 'fileUploadFileErrorNoTmpDir';
public const CANT_WRITE = 'fileUploadFileErrorCantWrite';
public const EXTENSION = 'fileUploadFileErrorExtension';
public const ATTACK = 'fileUploadFileErrorAttack';
public const FILE_NOT_FOUND = 'fileUploadFileErrorFileNotFound';
public const UNKNOWN = 'fileUploadFileErrorUnknown';
/** @var array Error message templates */
protected $messageTemplates = [
self::INI_SIZE => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
self::FORM_SIZE => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was '
. 'specified in the HTML form',
self::PARTIAL => 'The uploaded file was only partially uploaded',
self::NO_FILE => 'No file was uploaded',
self::NO_TMP_DIR => 'Missing a temporary folder',
self::CANT_WRITE => 'Failed to write file to disk',
self::EXTENSION => 'A PHP extension stopped the file upload',
self::ATTACK => 'File was illegally uploaded. This could be a possible attack',
self::FILE_NOT_FOUND => 'File was not found',
self::UNKNOWN => 'Unknown error while uploading file',
];
/**
* Returns true if and only if the file was uploaded without errors
*
* @param string|array|UploadedFileInterface $value File to check for upload errors
* @return bool
* @throws Exception\InvalidArgumentException
*/
public function isValid($value)
{
if (is_array($value)) {
if (! isset($value['tmp_name']) || ! isset($value['name']) || ! isset($value['error'])) {
throw new Exception\InvalidArgumentException(
'Value array must be in $_FILES format'
);
}
return $this->validateUploadedFile(
$value['error'],
$value['name'],
$value['tmp_name']
);
}
if ($value instanceof UploadedFileInterface) {
return $this->validatePsr7UploadedFile($value);
}
if (is_string($value)) {
return $this->validateUploadedFile(0, basename($value), $value);
}
$this->error(self::UNKNOWN);
return false;
}
/**
* @param int $error UPLOAD_ERR_* constant value
* @return bool
*/
private function validateFileFromErrorCode($error)
{
switch ($error) {
case UPLOAD_ERR_OK:
return true;
case UPLOAD_ERR_INI_SIZE:
$this->error(self::INI_SIZE);
return false;
case UPLOAD_ERR_FORM_SIZE:
$this->error(self::FORM_SIZE);
return false;
case UPLOAD_ERR_PARTIAL:
$this->error(self::PARTIAL);
return false;
case UPLOAD_ERR_NO_FILE:
$this->error(self::NO_FILE);
return false;
case UPLOAD_ERR_NO_TMP_DIR:
$this->error(self::NO_TMP_DIR);
return false;
case UPLOAD_ERR_CANT_WRITE:
$this->error(self::CANT_WRITE);
return false;
case UPLOAD_ERR_EXTENSION:
$this->error(self::EXTENSION);
return false;
default:
$this->error(self::UNKNOWN);
return false;
}
}
/**
* @param int $error UPLOAD_ERR_* constant
* @param string $filename
* @param string $uploadedFile Name of uploaded file (gen tmp_name)
* @return bool
*/
private function validateUploadedFile($error, $filename, $uploadedFile)
{
$this->setValue($filename);
// Normal errors can be validated normally
if ($error !== UPLOAD_ERR_OK) {
return $this->validateFileFromErrorCode($error);
}
// Did we get no name? Is the file missing?
if (empty($uploadedFile) || false === is_file($uploadedFile)) {
$this->error(self::FILE_NOT_FOUND);
return false;
}
// Do we have an invalid upload?
if (! is_uploaded_file($uploadedFile)) {
$this->error(self::ATTACK);
return false;
}
return true;
}
/**
* @return bool
*/
private function validatePsr7UploadedFile(UploadedFileInterface $uploadedFile)
{
$this->setValue($uploadedFile);
return $this->validateFileFromErrorCode($uploadedFile->getError());
}
}
laminas-validator/src/File/Extension.php 0000644 00000014240 15240152633 0014310 0 ustar 00 <?php
namespace Laminas\Validator\File;
use Laminas\Stdlib\ArrayUtils;
use Laminas\Validator\AbstractValidator;
use Traversable;
use function array_key_exists;
use function array_unique;
use function explode;
use function func_get_arg;
use function func_num_args;
use function implode;
use function in_array;
use function is_array;
use function is_readable;
use function is_string;
use function strrpos;
use function strtolower;
use function substr;
use function trim;
/**
* Validator for the file extension of a file
*/
class Extension extends AbstractValidator
{
use FileInformationTrait;
/**
* @const string Error constants
*/
public const FALSE_EXTENSION = 'fileExtensionFalse';
public const NOT_FOUND = 'fileExtensionNotFound';
/** @var array<string, string> Error message templates */
protected $messageTemplates = [
self::FALSE_EXTENSION => 'File has an incorrect extension',
self::NOT_FOUND => 'File is not readable or does not exist',
];
/**
* Options for this validator
*
* @var array
*/
protected $options = [
'case' => false, // Validate case sensitive
'extension' => '', // List of extensions
'allowNonExistentFile' => false, // Allow validation even if file does not exist
];
/** @var array Error message template variables */
protected $messageVariables = [
'extension' => ['options' => 'extension'],
];
/**
* Sets validator options
*
* @param string|array|Traversable $options
*/
public function __construct($options = null)
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
$case = null;
if (1 < func_num_args()) {
$case = func_get_arg(1);
}
if (is_array($options)) {
if (isset($options['case'])) {
$case = $options['case'];
unset($options['case']);
}
if (! array_key_exists('extension', $options)) {
$options = ['extension' => $options];
}
} else {
$options = ['extension' => $options];
}
if ($case !== null) {
$options['case'] = $case;
}
parent::__construct($options);
}
/**
* Returns the case option
*
* @return bool
*/
public function getCase()
{
return $this->options['case'];
}
/**
* Sets the case to use
*
* @param bool $case
* @return $this Provides a fluent interface
*/
public function setCase($case)
{
$this->options['case'] = (bool) $case;
return $this;
}
/**
* Returns the set file extension
*
* @return array
*/
public function getExtension()
{
if (
! array_key_exists('extension', $this->options)
|| ! is_string($this->options['extension'])
) {
return [];
}
return explode(',', $this->options['extension']);
}
/**
* Sets the file extensions
*
* @param string|array $extension The extensions to validate
* @return $this Provides a fluent interface
*/
public function setExtension($extension)
{
$this->options['extension'] = null;
$this->addExtension($extension);
return $this;
}
/**
* Adds the file extensions
*
* @param string|array $extension The extensions to add for validation
* @return $this Provides a fluent interface
*/
public function addExtension($extension)
{
$extensions = $this->getExtension();
if (is_string($extension)) {
$extension = explode(',', $extension);
}
foreach ($extension as $content) {
if (empty($content) || ! is_string($content)) {
continue;
}
$extensions[] = trim($content);
}
$extensions = array_unique($extensions);
// Sanity check to ensure no empty values
foreach ($extensions as $key => $ext) {
if (empty($ext)) {
unset($extensions[$key]);
}
}
$this->options['extension'] = implode(',', $extensions);
return $this;
}
/**
* Returns whether or not to allow validation of non-existent files.
*
* @return bool
*/
public function getAllowNonExistentFile()
{
return $this->options['allowNonExistentFile'];
}
/**
* Sets the flag indicating whether or not to allow validation of non-existent files.
*
* @param bool $flag Whether or not to allow validation of non-existent files.
* @return $this Provides a fluent interface
*/
public function setAllowNonExistentFile($flag)
{
$this->options['allowNonExistentFile'] = (bool) $flag;
return $this;
}
/**
* Returns true if and only if the file extension of $value is included in the
* set extension list
*
* @param string|array $value Real file to check for extension
* @param array $file File data from \Laminas\File\Transfer\Transfer (optional)
* @return bool
*/
public function isValid($value, $file = null)
{
$fileInfo = $this->getFileInfo($value, $file);
// Is file readable ?
if (
! $this->getAllowNonExistentFile()
&& (empty($fileInfo['file']) || false === is_readable($fileInfo['file']))
) {
$this->error(self::NOT_FOUND);
return false;
}
$this->setValue($fileInfo['filename']);
$extension = substr($fileInfo['filename'], strrpos($fileInfo['filename'], '.') + 1);
$extensions = $this->getExtension();
if ($this->getCase() && (in_array($extension, $extensions))) {
return true;
} elseif (! $this->getCase()) {
foreach ($extensions as $ext) {
if (strtolower($ext) === strtolower($extension)) {
return true;
}
}
}
$this->error(self::FALSE_EXTENSION);
return false;
}
}
laminas-validator/src/File/Count.php 0000644 00000017072 15240152633 0013432 0 ustar 00 <?php
namespace Laminas\Validator\File;
use Laminas\Validator\AbstractValidator;
use Laminas\Validator\Exception;
use Psr\Http\Message\UploadedFileInterface;
use Traversable;
use function array_key_exists;
use function array_shift;
use function count;
use function dirname;
use function func_get_args;
use function func_num_args;
use function is_array;
use function is_numeric;
use function is_string;
use const DIRECTORY_SEPARATOR;
/**
* Validator for counting all given files
*/
class Count extends AbstractValidator
{
/**#@+
*
* @const string Error constants
*/
public const TOO_MANY = 'fileCountTooMany';
public const TOO_FEW = 'fileCountTooFew';
/**#@-*/
/** @var array Error message templates */
protected $messageTemplates = [
self::TOO_MANY => "Too many files, maximum '%max%' are allowed but '%count%' are given",
self::TOO_FEW => "Too few files, minimum '%min%' are expected but '%count%' are given",
];
/** @var array Error message template variables */
protected $messageVariables = [
'min' => ['options' => 'min'],
'max' => ['options' => 'max'],
'count' => 'count',
];
/**
* Actual filecount
*
* @var int
*/
protected $count;
/**
* Internal file array
*
* @var array
*/
protected $files;
/**
* Options for this validator
*
* @var array
*/
protected $options = [
'min' => null, // Minimum file count, if null there is no minimum file count
'max' => null, // Maximum file count, if null there is no maximum file count
];
/**
* Sets validator options
*
* Min limits the file count, when used with max=null it is the maximum file count
* It also accepts an array with the keys 'min' and 'max'
*
* If $options is an integer, it will be used as maximum file count
* As Array is accepts the following keys:
* 'min': Minimum filecount
* 'max': Maximum filecount
*
* @param int|array|Traversable $options Options for the adapter
*/
public function __construct($options = null)
{
if (1 < func_num_args()) {
$args = func_get_args();
$options = [
'min' => array_shift($args),
'max' => array_shift($args),
];
}
if (is_string($options) || is_numeric($options)) {
$options = ['max' => $options];
}
parent::__construct($options);
}
/**
* Returns the minimum file count
*
* @return int
*/
public function getMin()
{
return $this->options['min'];
}
/**
* Sets the minimum file count
*
* @param int|array $min The minimum file count
* @return $this Provides a fluent interface
* @throws Exception\InvalidArgumentException When min is greater than max.
*/
public function setMin($min)
{
if (is_array($min) && isset($min['min'])) {
$min = $min['min'];
}
if (! is_numeric($min)) {
throw new Exception\InvalidArgumentException('Invalid options to validator provided');
}
$min = (int) $min;
if (($this->getMax() !== null) && ($min > $this->getMax())) {
throw new Exception\InvalidArgumentException(
"The minimum must be less than or equal to the maximum file count, but {$min} > {$this->getMax()}"
);
}
$this->options['min'] = $min;
return $this;
}
/**
* Returns the maximum file count
*
* @return int
*/
public function getMax()
{
return $this->options['max'];
}
/**
* Sets the maximum file count
*
* @param int|array $max The maximum file count
* @return $this Provides a fluent interface
* @throws Exception\InvalidArgumentException When max is smaller than min.
*/
public function setMax($max)
{
if (is_array($max) && isset($max['max'])) {
$max = $max['max'];
}
if (! is_numeric($max)) {
throw new Exception\InvalidArgumentException('Invalid options to validator provided');
}
$max = (int) $max;
if (($this->getMin() !== null) && ($max < $this->getMin())) {
throw new Exception\InvalidArgumentException(
"The maximum must be greater than or equal to the minimum file count, but {$max} < {$this->getMin()}"
);
}
$this->options['max'] = $max;
return $this;
}
/**
* Adds a file for validation
*
* @param string|array|UploadedFileInterface $file
* @return $this
*/
public function addFile($file)
{
if (is_string($file)) {
$file = [$file];
}
if (is_array($file)) {
foreach ($file as $name) {
if (! isset($this->files[$name]) && ! empty($name)) {
$this->files[$name] = $name;
}
}
}
if ($file instanceof UploadedFileInterface && is_string($file->getClientFilename())) {
$this->files[(string) $file->getClientFilename()] = $file->getClientFilename();
}
return $this;
}
/**
* Returns true if and only if the file count of all checked files is at least min and
* not bigger than max (when max is not null). Attention: When checking with set min you
* must give all files with the first call, otherwise you will get a false.
*
* @param string|array|UploadedFileInterface $value Filenames to check for count
* @param array $file File data from \Laminas\File\Transfer\Transfer
* @return bool
*/
public function isValid($value, $file = null)
{
if ($this->isUploadedFilterInterface($value)) {
$this->addFile($value);
} elseif ($file !== null) {
if (! array_key_exists('destination', $file)) {
$file['destination'] = dirname($value);
}
if (array_key_exists('tmp_name', $file)) {
$value = $file['destination'] . DIRECTORY_SEPARATOR . $file['name'];
}
}
if (($file === null) || ! empty($file['tmp_name'])) {
$this->addFile($value);
}
$this->count = count($this->files);
if (($this->getMax() !== null) && ($this->count > $this->getMax())) {
return $this->throwError($file, self::TOO_MANY);
}
if (($this->getMin() !== null) && ($this->count < $this->getMin())) {
return $this->throwError($file, self::TOO_FEW);
}
return true;
}
/**
* Throws an error of the given type
*
* @param string $file
* @param string $errorType
* @return false
*/
protected function throwError($file, $errorType)
{
if ($file !== null) {
if (is_array($file)) {
if (array_key_exists('name', $file)) {
$this->value = $file['name'];
}
} elseif (is_string($file)) {
$this->value = $file;
}
}
$this->error($errorType);
return false;
}
/**
* Checks if the type of uploaded file is UploadedFileInterface.
*
* @param string|array|UploadedFileInterface $value Filenames to check for count
* @return bool
*/
private function isUploadedFilterInterface($value)
{
if ($value instanceof UploadedFileInterface) {
return true;
}
return false;
}
}
laminas-validator/src/File/Upload.php 0000644 00000021436 15240152633 0013565 0 ustar 00 <?php
namespace Laminas\Validator\File;
use Laminas\Validator\AbstractValidator;
use Laminas\Validator\Exception;
use Psr\Http\Message\UploadedFileInterface;
use Traversable;
use function array_key_exists;
use function array_merge;
use function count;
use function is_array;
use function is_countable;
use function is_string;
use function is_uploaded_file;
/**
* Validator for the maximum size of a file up to a max of 2GB
*/
class Upload extends AbstractValidator
{
/**
* @const string Error constants
*/
public const INI_SIZE = 'fileUploadErrorIniSize';
public const FORM_SIZE = 'fileUploadErrorFormSize';
public const PARTIAL = 'fileUploadErrorPartial';
public const NO_FILE = 'fileUploadErrorNoFile';
public const NO_TMP_DIR = 'fileUploadErrorNoTmpDir';
public const CANT_WRITE = 'fileUploadErrorCantWrite';
public const EXTENSION = 'fileUploadErrorExtension';
public const ATTACK = 'fileUploadErrorAttack';
public const FILE_NOT_FOUND = 'fileUploadErrorFileNotFound';
public const UNKNOWN = 'fileUploadErrorUnknown';
/** @var array<string, string> Error message templates */
protected $messageTemplates = [
self::INI_SIZE => "File '%value%' exceeds upload_max_filesize directive in php.ini",
self::FORM_SIZE => "File '%value%' exceeds the MAX_FILE_SIZE directive that was "
. 'specified in the HTML form',
self::PARTIAL => "File '%value%' was only partially uploaded",
self::NO_FILE => "File '%value%' was not uploaded",
self::NO_TMP_DIR => "Missing a temporary folder to store '%value%'",
self::CANT_WRITE => "Failed to write file '%value%' to disk",
self::EXTENSION => "A PHP extension stopped uploading the file '%value%'",
self::ATTACK => "File '%value%' was illegally uploaded. This could be a possible attack",
self::FILE_NOT_FOUND => "File '%value%' was not found",
self::UNKNOWN => "Unknown error while uploading file '%value%'",
];
/** @var array<string, mixed> */
protected $options = [
'files' => [],
];
/**
* Sets validator options
*
* The array $files must be given in syntax of Laminas\File\Transfer\Transfer to be checked
* If no files are given the $_FILES array will be used automatically.
* NOTE: This validator will only work with HTTP POST uploads!
*
* @param array|Traversable $options Array of files in syntax of \Laminas\File\Transfer\Transfer
*/
public function __construct($options = [])
{
if (is_array($options) && ! array_key_exists('files', $options)) {
$options = ['files' => $options];
}
parent::__construct($options);
}
/**
* Returns the array of set files
*
* @param string $file (Optional) The file to return in detail
* @return array
* @throws Exception\InvalidArgumentException If file is not found.
*/
public function getFiles($file = null)
{
if ($file !== null) {
$return = [];
foreach ($this->options['files'] as $name => $content) {
if ($name === $file) {
$return[$file] = $this->options['files'][$name];
}
if ($content instanceof UploadedFileInterface) {
if ($content->getClientFilename() === $file) {
$return[$name] = $this->options['files'][$name];
}
} elseif ($content['name'] === $file) {
$return[$name] = $this->options['files'][$name];
}
}
if (! $return) {
throw new Exception\InvalidArgumentException("The file '$file' was not found");
}
return $return;
}
return $this->options['files'];
}
/**
* Sets the files to be checked
*
* @param array $files The files to check in syntax of \Laminas\File\Transfer\Transfer
* @return $this Provides a fluent interface
*/
public function setFiles($files = [])
{
if (
null === $files
|| ((is_countable($files))
&& count($files) === 0)
) {
$this->options['files'] = $_FILES;
} else {
$this->options['files'] = $files;
}
if ($this->options['files'] === null) {
$this->options['files'] = [];
}
foreach ($this->options['files'] as $file => $content) {
if (
! $content instanceof UploadedFileInterface
&& ! isset($content['error'])
) {
unset($this->options['files'][$file]);
}
}
return $this;
}
/**
* Returns true if and only if the file was uploaded without errors
*
* @param string $value Single file to check for upload errors, when giving null the $_FILES array
* from initialization will be used
* @param mixed $file
* @return bool
*/
public function isValid($value, $file = null)
{
$files = [];
$this->setValue($value);
if (array_key_exists($value, $this->getFiles())) {
$files = array_merge($files, $this->getFiles($value));
} else {
foreach ($this->getFiles() as $file => $content) {
if ($content instanceof UploadedFileInterface) {
if ($content->getClientFilename() === $value) {
$files = array_merge($files, $this->getFiles($file));
}
// PSR cannot search by tmp_name because it does not have
// a public interface to get it, only user defined name
// from form field.
continue;
}
if (isset($content['name']) && ($content['name'] === $value)) {
$files = array_merge($files, $this->getFiles($file));
}
if (isset($content['tmp_name']) && ($content['tmp_name'] === $value)) {
$files = array_merge($files, $this->getFiles($file));
}
}
}
if (empty($files)) {
return $this->throwError($file, self::FILE_NOT_FOUND);
}
foreach ($files as $file => $content) {
$this->value = $file;
$error = $content instanceof UploadedFileInterface
? $content->getError()
: $content['error'];
switch ($error) {
case 0:
if ($content instanceof UploadedFileInterface) {
// done!
break;
}
// For standard SAPI environments, check that the upload
// was valid
if (! is_uploaded_file($content['tmp_name'])) {
$this->throwError($content, self::ATTACK);
}
break;
case 1:
$this->throwError($content, self::INI_SIZE);
break;
case 2:
$this->throwError($content, self::FORM_SIZE);
break;
case 3:
$this->throwError($content, self::PARTIAL);
break;
case 4:
$this->throwError($content, self::NO_FILE);
break;
case 6:
$this->throwError($content, self::NO_TMP_DIR);
break;
case 7:
$this->throwError($content, self::CANT_WRITE);
break;
case 8:
$this->throwError($content, self::EXTENSION);
break;
default:
$this->throwError($content, self::UNKNOWN);
break;
}
}
if ($this->getMessages()) {
return false;
}
return true;
}
/**
* Throws an error of the given type
*
* @param array|string|UploadedFileInterface $file
* @param string $errorType
* @return false
*/
protected function throwError($file, $errorType)
{
if ($file !== null) {
if (is_array($file)) {
if (array_key_exists('name', $file)) {
$this->value = $file['name'];
}
} elseif (is_string($file)) {
$this->value = $file;
} elseif ($file instanceof UploadedFileInterface) {
$this->value = $file->getClientFilename();
}
}
$this->error($errorType);
return false;
}
}
laminas-validator/src/File/WordCount.php 0000644 00000013210 15240152634 0014255 0 ustar 00 <?php
namespace Laminas\Validator\File;
use Laminas\Validator\AbstractValidator;
use Laminas\Validator\Exception;
use Traversable;
use function array_shift;
use function file_get_contents;
use function func_get_args;
use function func_num_args;
use function is_array;
use function is_numeric;
use function is_readable;
use function is_string;
use function str_word_count;
/**
* Validator for counting all words in a file
*/
class WordCount extends AbstractValidator
{
use FileInformationTrait;
/**
* @const string Error constants
*/
public const TOO_MUCH = 'fileWordCountTooMuch';
public const TOO_LESS = 'fileWordCountTooLess';
public const NOT_FOUND = 'fileWordCountNotFound';
/** @var array Error message templates */
protected $messageTemplates = [
self::TOO_MUCH => "Too many words, maximum '%max%' are allowed but '%count%' were counted",
self::TOO_LESS => "Too few words, minimum '%min%' are expected but '%count%' were counted",
self::NOT_FOUND => 'File is not readable or does not exist',
];
/** @var array Error message template variables */
protected $messageVariables = [
'min' => ['options' => 'min'],
'max' => ['options' => 'max'],
'count' => 'count',
];
/**
* Word count
*
* @var int
*/
protected $count;
/**
* Options for this validator
*
* @var array
*/
protected $options = [
'min' => null, // Minimum word count, if null there is no minimum word count
'max' => null, // Maximum word count, if null there is no maximum word count
];
/**
* Sets validator options
*
* Min limits the word count, when used with max=null it is the maximum word count
* It also accepts an array with the keys 'min' and 'max'
*
* If $options is an integer, it will be used as maximum word count
* As Array is accepts the following keys:
* 'min': Minimum word count
* 'max': Maximum word count
*
* @param int|array|Traversable $options Options for the adapter
*/
public function __construct($options = null)
{
if (1 < func_num_args()) {
$args = func_get_args();
$options = [
'min' => array_shift($args),
'max' => array_shift($args),
];
}
if (is_string($options) || is_numeric($options)) {
$options = ['max' => $options];
}
parent::__construct($options);
}
/**
* Returns the minimum word count
*
* @return int
*/
public function getMin()
{
return $this->options['min'];
}
/**
* Sets the minimum word count
*
* @param int|array $min The minimum word count
* @return $this Provides a fluent interface
* @throws Exception\InvalidArgumentException When min is greater than max.
*/
public function setMin($min)
{
if (is_array($min) && isset($min['min'])) {
$min = $min['min'];
}
if (! is_numeric($min)) {
throw new Exception\InvalidArgumentException('Invalid options to validator provided');
}
$min = (int) $min;
if (($this->getMax() !== null) && ($min > $this->getMax())) {
throw new Exception\InvalidArgumentException(
"The minimum must be less than or equal to the maximum word count, but $min > {$this->getMax()}"
);
}
$this->options['min'] = $min;
return $this;
}
/**
* Returns the maximum word count
*
* @return int
*/
public function getMax()
{
return $this->options['max'];
}
/**
* Sets the maximum file count
*
* @param int|array $max The maximum word count
* @return $this Provides a fluent interface
* @throws Exception\InvalidArgumentException When max is smaller than min.
*/
public function setMax($max)
{
if (is_array($max) && isset($max['max'])) {
$max = $max['max'];
}
if (! is_numeric($max)) {
throw new Exception\InvalidArgumentException('Invalid options to validator provided');
}
$max = (int) $max;
if (($this->getMin() !== null) && ($max < $this->getMin())) {
throw new Exception\InvalidArgumentException(
"The maximum must be greater than or equal to the minimum word count, but $max < {$this->getMin()}"
);
}
$this->options['max'] = $max;
return $this;
}
/**
* Returns true if and only if the counted words are at least min and
* not bigger than max (when max is not null).
*
* @param string|array $value Filename to check for word count
* @param array $file File data from \Laminas\File\Transfer\Transfer (optional)
* @return bool
*/
public function isValid($value, $file = null)
{
$fileInfo = $this->getFileInfo($value, $file);
$this->setValue($fileInfo['filename']);
// Is file readable ?
if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) {
$this->error(self::NOT_FOUND);
return false;
}
$content = file_get_contents($fileInfo['file']);
$this->count = str_word_count($content);
if (($this->getMax() !== null) && ($this->count > $this->getMax())) {
$this->error(self::TOO_MUCH);
return false;
}
if (($this->getMin() !== null) && ($this->count < $this->getMin())) {
$this->error(self::TOO_LESS);
return false;
}
return true;
}
}
laminas-validator/src/File/FileInformationTrait.php 0000644 00000010734 15240152634 0016432 0 ustar 00 <?php
namespace Laminas\Validator\File;
use Laminas\Validator\Exception;
use Psr\Http\Message\UploadedFileInterface;
use function basename;
use function is_array;
use function is_string;
trait FileInformationTrait
{
/**
* Returns array if the procedure is identified
*
* @param string|array|object $value Filename to check
* @param null|array $file File data (when using legacy Laminas_File_Transfer API)
* @param bool $hasType Return with filetype (optional)
* @param bool $hasBasename Return with basename - is calculated from location path (optional)
* @return array
*/
protected function getFileInfo(
$value,
?array $file = null,
$hasType = false,
$hasBasename = false
) {
if (is_string($value) && is_array($file)) {
return $this->getLegacyFileInfo($file, $hasType, $hasBasename);
}
if (is_array($value)) {
return $this->getSapiFileInfo($value, $hasType, $hasBasename);
}
if ($value instanceof UploadedFileInterface) {
return $this->getPsr7FileInfo($value, $hasType, $hasBasename);
}
return $this->getFileBasedFileInfo($value, $hasType, $hasBasename);
}
/**
* Generate file information array with legacy Laminas_File_Transfer API
*
* @param array $file File data
* @param bool $hasType Return with filetype
* @param bool $hasBasename Basename is calculated from location path
* @return array
*/
private function getLegacyFileInfo(
array $file,
$hasType = false,
$hasBasename = false
) {
$fileInfo = [];
$fileInfo['filename'] = $file['name'];
$fileInfo['file'] = $file['tmp_name'];
if ($hasBasename) {
$fileInfo['basename'] = basename($fileInfo['file']);
}
if ($hasType) {
$fileInfo['filetype'] = $file['type'];
}
return $fileInfo;
}
/**
* Generate file information array with SAPI
*
* @param array $file File data from SAPI
* @param bool $hasType Return with filetype
* @param bool $hasBasename Filename is calculated from location path
* @return array
*/
private function getSapiFileInfo(
array $file,
$hasType = false,
$hasBasename = false
) {
if (! isset($file['tmp_name']) || ! isset($file['name'])) {
throw new Exception\InvalidArgumentException(
'Value array must be in $_FILES format'
);
}
$fileInfo = [];
$fileInfo['file'] = $file['tmp_name'];
$fileInfo['filename'] = $file['name'];
if ($hasBasename) {
$fileInfo['basename'] = basename($fileInfo['file']);
}
if ($hasType) {
$fileInfo['filetype'] = $file['type'];
}
return $fileInfo;
}
/**
* Generate file information array with PSR-7 UploadedFileInterface
*
* @param bool $hasType Return with filetype
* @param bool $hasBasename Filename is calculated from location path
* @return array
*/
private function getPsr7FileInfo(
UploadedFileInterface $file,
$hasType = false,
$hasBasename = false
) {
$fileInfo = [];
$fileInfo['file'] = $file->getStream()->getMetadata('uri');
$fileInfo['filename'] = $file->getClientFilename();
if ($hasBasename) {
$fileInfo['basename'] = basename($fileInfo['file']);
}
if ($hasType) {
$fileInfo['filetype'] = $file->getClientMediaType();
}
return $fileInfo;
}
/**
* Generate file information array with base method
*
* @param string $file File path
* @param bool $hasType Return with filetype
* @param bool $hasBasename Filename is calculated from location path
* @return array
*/
private function getFileBasedFileInfo(
$file,
$hasType = false,
$hasBasename = false
) {
$fileInfo = [];
$fileInfo['file'] = $file;
$fileInfo['filename'] = basename($fileInfo['file']);
if ($hasBasename) {
$fileInfo['basename'] = basename($fileInfo['file']);
}
if ($hasType) {
$fileInfo['filetype'] = null;
}
return $fileInfo;
}
}
laminas-validator/src/File/IsImage.php 0000644 00000006060 15240152634 0013654 0 ustar 00 <?php
namespace Laminas\Validator\File;
use Laminas\Stdlib\ArrayUtils;
use Traversable;
/**
* Validator which checks if the file is an image
*/
class IsImage extends MimeType
{
/**
* @const string Error constants
*/
public const FALSE_TYPE = 'fileIsImageFalseType';
public const NOT_DETECTED = 'fileIsImageNotDetected';
public const NOT_READABLE = 'fileIsImageNotReadable';
/** @var array Error message templates */
protected $messageTemplates = [
self::FALSE_TYPE => "File is no image, '%type%' detected",
self::NOT_DETECTED => 'The mimetype could not be detected from the file',
self::NOT_READABLE => 'File is not readable or does not exist',
];
/**
* Sets validator options
*
* @param array|Traversable|string $options
*/
public function __construct($options = [])
{
// http://www.iana.org/assignments/media-types/media-types.xhtml#image
$default = [
'application/cdf',
'application/dicom',
'application/fractals',
'application/postscript',
'application/vnd.hp-hpgl',
'application/vnd.oasis.opendocument.graphics',
'application/x-cdf',
'application/x-cmu-raster',
'application/x-ima',
'application/x-inventor',
'application/x-koan',
'application/x-portable-anymap',
'application/x-world-x-3dmf',
'image/bmp',
'image/c',
'image/cgm',
'image/fif',
'image/gif',
'image/heic',
'image/heif',
'image/jpeg',
'image/jpm',
'image/jpx',
'image/jp2',
'image/naplps',
'image/pjpeg',
'image/png',
'image/svg',
'image/svg+xml',
'image/tiff',
'image/vnd.adobe.photoshop',
'image/vnd.djvu',
'image/vnd.fpx',
'image/vnd.net-fpx',
'image/webp',
'image/x-cmu-raster',
'image/x-cmx',
'image/x-coreldraw',
'image/x-cpi',
'image/x-emf',
'image/x-ico',
'image/x-icon',
'image/x-jg',
'image/x-ms-bmp',
'image/x-niff',
'image/x-pict',
'image/x-pcx',
'image/x-png',
'image/x-portable-anymap',
'image/x-portable-bitmap',
'image/x-portable-greymap',
'image/x-portable-pixmap',
'image/x-quicktime',
'image/x-rgb',
'image/x-tiff',
'image/x-unknown',
'image/x-windows-bmp',
'image/x-xpmi',
];
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if ($options === null) {
$options = [];
}
parent::__construct($options);
if (! $this->getMimeType()) {
$this->setMimeType($default);
}
}
}
laminas-validator/src/File/IsCompressed.php 0000644 00000004677 15240152634 0014752 0 ustar 00 <?php
namespace Laminas\Validator\File;
use Laminas\Stdlib\ArrayUtils;
use Traversable;
/**
* Validator which checks if the file already exists in the directory
*/
class IsCompressed extends MimeType
{
/**
* @const string Error constants
*/
public const FALSE_TYPE = 'fileIsCompressedFalseType';
public const NOT_DETECTED = 'fileIsCompressedNotDetected';
public const NOT_READABLE = 'fileIsCompressedNotReadable';
/** @var array Error message templates */
protected $messageTemplates = [
self::FALSE_TYPE => "File is not compressed, '%type%' detected",
self::NOT_DETECTED => 'The mimetype could not be detected from the file',
self::NOT_READABLE => 'File is not readable or does not exist',
];
/**
* Sets validator options
*
* @param string|array|Traversable $options
*/
public function __construct($options = [])
{
// http://hul.harvard.edu/ois/systems/wax/wax-public-help/mimetypes.htm
$default = [
'application/arj',
'application/gnutar',
'application/lha',
'application/lzx',
'application/vnd.ms-cab-compressed',
'application/x-ace-compressed',
'application/x-arc',
'application/x-archive',
'application/x-arj',
'application/x-bzip',
'application/x-bzip2',
'application/x-cab-compressed',
'application/x-compress',
'application/x-compressed',
'application/x-cpio',
'application/x-debian-package',
'application/x-eet',
'application/x-gzip',
'application/x-java-pack200',
'application/x-lha',
'application/x-lharc',
'application/x-lzh',
'application/x-lzma',
'application/x-lzx',
'application/x-rar',
'application/x-sit',
'application/x-stuffit',
'application/x-tar',
'application/zip',
'application/x-zip',
'application/zoo',
'multipart/x-gzip',
];
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if ($options === null) {
$options = [];
}
parent::__construct($options);
if (! $this->getMimeType()) {
$this->setMimeType($default);
}
}
}
laminas-validator/src/File/ExcludeMimeType.php 0000644 00000005767 15240152634 0015416 0 ustar 00 <?php
namespace Laminas\Validator\File;
use function array_merge;
use function class_exists;
use function explode;
use function finfo_file;
use function finfo_open;
use function in_array;
use function is_readable;
use const FILEINFO_MIME_TYPE;
/**
* Validator for the mime type of a file
*/
class ExcludeMimeType extends MimeType
{
use FileInformationTrait;
public const FALSE_TYPE = 'fileExcludeMimeTypeFalse';
public const NOT_DETECTED = 'fileExcludeMimeTypeNotDetected';
public const NOT_READABLE = 'fileExcludeMimeTypeNotReadable';
/** @var array Error message templates */
protected $messageTemplates = [
self::FALSE_TYPE => "File has an incorrect mimetype of '%type%'",
self::NOT_DETECTED => 'The mimetype could not be detected from the file',
self::NOT_READABLE => 'File is not readable or does not exist',
];
/**
* Returns true if the mimetype of the file does not matche the given ones. Also parts
* of mimetypes can be checked. If you give for example "image" all image
* mime types will not be accepted like "image/gif", "image/jpeg" and so on.
*
* @param string|array $value Real file to check for mimetype
* @param array $file File data from \Laminas\File\Transfer\Transfer (optional)
* @return bool
*/
public function isValid($value, $file = null)
{
$fileInfo = $this->getFileInfo($value, $file, true);
$this->setValue($fileInfo['filename']);
// Is file readable ?
if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) {
$this->error(self::NOT_READABLE);
return false;
}
$mimefile = $this->getMagicFile();
if (class_exists('finfo', false)) {
if (! $this->isMagicFileDisabled() && (! empty($mimefile) && empty($this->finfo))) {
$this->finfo = finfo_open(FILEINFO_MIME_TYPE, $mimefile);
}
if (empty($this->finfo)) {
$this->finfo = finfo_open(FILEINFO_MIME_TYPE);
}
$this->type = null;
if (! empty($this->finfo)) {
$this->type = finfo_file($this->finfo, $fileInfo['file']);
}
}
if (empty($this->type) && $this->getHeaderCheck()) {
$this->type = $fileInfo['filetype'];
}
if (empty($this->type)) {
$this->error(self::NOT_DETECTED);
return false;
}
$mimetype = $this->getMimeType(true);
if (in_array($this->type, $mimetype)) {
$this->error(self::FALSE_TYPE);
return false;
}
$types = explode('/', $this->type);
$types = array_merge($types, explode('-', $this->type));
$types = array_merge($types, explode(';', $this->type));
foreach ($mimetype as $mime) {
if (in_array($mime, $types)) {
$this->error(self::FALSE_TYPE);
return false;
}
}
return true;
}
}
laminas-validator/src/File/FilesSize.php 0000644 00000013240 15240152634 0014231 0 ustar 00 <?php
namespace Laminas\Validator\File;
use Laminas\Stdlib\ArrayUtils;
use Laminas\Stdlib\ErrorHandler;
use Laminas\Validator\Exception;
use Laminas\Validator\Exception\InvalidArgumentException;
use Traversable;
use function array_key_exists;
use function array_shift;
use function filesize;
use function func_get_args;
use function func_num_args;
use function is_array;
use function is_readable;
use function is_scalar;
use function is_string;
/**
* Validator for the size of all files which will be validated in sum
*/
class FilesSize extends Size
{
/**
* @const string Error constants
*/
public const TOO_BIG = 'fileFilesSizeTooBig';
public const TOO_SMALL = 'fileFilesSizeTooSmall';
public const NOT_READABLE = 'fileFilesSizeNotReadable';
/** @var array Error message templates */
protected $messageTemplates = [
self::TOO_BIG => "All files in sum should have a maximum size of '%max%' but '%size%' were detected",
self::TOO_SMALL => "All files in sum should have a minimum size of '%min%' but '%size%' were detected",
self::NOT_READABLE => 'One or more files can not be read',
];
/**
* Internal file array
*
* @var array
*/
protected $files;
/**
* Sets validator options
*
* Min limits the used disk space for all files, when used with max=null it is the maximum file size
* It also accepts an array with the keys 'min' and 'max'
*
* @param int|array|Traversable $options Options for this validator
* @throws InvalidArgumentException
*/
public function __construct($options = null)
{
$this->files = [];
$this->setSize(0);
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
} elseif (is_scalar($options)) {
$options = ['max' => $options];
} elseif (! is_array($options)) {
throw new Exception\InvalidArgumentException('Invalid options to validator provided');
}
if (1 < func_num_args()) {
$argv = func_get_args();
array_shift($argv);
$options['max'] = array_shift($argv);
if (! empty($argv)) {
$options['useByteString'] = array_shift($argv);
}
}
parent::__construct($options);
}
/**
* Returns true if and only if the disk usage of all files is at least min and
* not bigger than max (when max is not null).
*
* @param string|array $value Real file to check for size
* @param array $file File data from \Laminas\File\Transfer\Transfer
* @return bool
*/
public function isValid($value, $file = null)
{
if (is_string($value)) {
$value = [$value];
} elseif (is_array($value) && isset($value['tmp_name'])) {
$value = [$value];
}
$min = $this->getMin(true);
$max = $this->getMax(true);
$size = $this->getSize();
foreach ($value as $files) {
if (is_array($files)) {
if (! isset($files['tmp_name']) || ! isset($files['name'])) {
throw new Exception\InvalidArgumentException(
'Value array must be in $_FILES format'
);
}
$file = $files;
$files = $files['tmp_name'];
}
// Is file readable ?
if (empty($files) || false === is_readable($files)) {
$this->throwError($file, self::NOT_READABLE);
continue;
}
if (! isset($this->files[$files])) {
$this->files[$files] = $files;
} else {
// file already counted... do not count twice
continue;
}
// limited to 2GB files
ErrorHandler::start();
$size += filesize($files);
ErrorHandler::stop();
$this->size = $size;
if (($max !== null) && ($max < $size)) {
if ($this->getByteString()) {
$this->options['max'] = $this->toByteString($max);
$this->size = $this->toByteString($size);
$this->throwError($file, self::TOO_BIG);
$this->options['max'] = $max;
$this->size = $size;
} else {
$this->throwError($file, self::TOO_BIG);
}
}
}
// Check that aggregate files are >= minimum size
if (($min !== null) && ($size < $min)) {
if ($this->getByteString()) {
$this->options['min'] = $this->toByteString($min);
$this->size = $this->toByteString($size);
$this->throwError($file, self::TOO_SMALL);
$this->options['min'] = $min;
$this->size = $size;
} else {
$this->throwError($file, self::TOO_SMALL);
}
}
if ($this->getMessages()) {
return false;
}
return true;
}
/**
* Throws an error of the given type
*
* @param string $file
* @param string $errorType
* @return false
*/
protected function throwError($file, $errorType)
{
if ($file !== null) {
if (is_array($file)) {
if (array_key_exists('name', $file)) {
$this->value = $file['name'];
}
} elseif (is_string($file)) {
$this->value = $file;
}
}
$this->error($errorType);
return false;
}
}
laminas-validator/src/File/ExcludeExtension.php 0000644 00000004035 15240152634 0015624 0 ustar 00 <?php
namespace Laminas\Validator\File;
use function in_array;
use function is_readable;
use function strrpos;
use function strtolower;
use function substr;
/**
* Validator for the excluding file extensions
*/
class ExcludeExtension extends Extension
{
use FileInformationTrait;
/**
* @const string Error constants
*/
public const FALSE_EXTENSION = 'fileExcludeExtensionFalse';
public const NOT_FOUND = 'fileExcludeExtensionNotFound';
/** @var array Error message templates */
protected $messageTemplates = [
self::FALSE_EXTENSION => 'File has an incorrect extension',
self::NOT_FOUND => 'File is not readable or does not exist',
];
/**
* Returns true if and only if the file extension of $value is not included in the
* set extension list
*
* @param string|array $value Real file to check for extension
* @param array $file File data from \Laminas\File\Transfer\Transfer (optional)
* @return bool
*/
public function isValid($value, $file = null)
{
$fileInfo = $this->getFileInfo($value, $file);
// Is file readable ?
if (
! $this->getAllowNonExistentFile()
&& (empty($fileInfo['file']) || false === is_readable($fileInfo['file']))
) {
$this->error(self::NOT_FOUND);
return false;
}
$this->setValue($fileInfo['filename']);
$extension = substr($fileInfo['filename'], strrpos($fileInfo['filename'], '.') + 1);
$extensions = $this->getExtension();
if ($this->getCase() && (! in_array($extension, $extensions))) {
return true;
} elseif (! $this->getCase()) {
foreach ($extensions as $ext) {
if (strtolower($ext) === strtolower($extension)) {
$this->error(self::FALSE_EXTENSION);
return false;
}
}
return true;
}
$this->error(self::FALSE_EXTENSION);
return false;
}
}
laminas-validator/src/File/Sha1.php 0000644 00000005302 15240152634 0013130 0 ustar 00 <?php
namespace Laminas\Validator\File;
use function array_keys;
use function array_unique;
use function hash_file;
use function is_readable;
/**
* Validator for the sha1 hash of given files
*/
class Sha1 extends Hash
{
use FileInformationTrait;
/**
* @const string Error constants
*/
public const DOES_NOT_MATCH = 'fileSha1DoesNotMatch';
public const NOT_DETECTED = 'fileSha1NotDetected';
public const NOT_FOUND = 'fileSha1NotFound';
/** @var array Error message templates */
protected $messageTemplates = [
self::DOES_NOT_MATCH => 'File does not match the given sha1 hashes',
self::NOT_DETECTED => 'A sha1 hash could not be evaluated for the given file',
self::NOT_FOUND => 'File is not readable or does not exist',
];
/**
* Options for this validator
*
* @var string
*/
protected $options = [
'algorithm' => 'sha1',
'hash' => null,
];
/**
* Returns all set sha1 hashes
*
* @return array
*/
public function getSha1()
{
return $this->getHash();
}
/**
* Sets the sha1 hash for one or multiple files
*
* @param string|array $options
* @return Hash Provides a fluent interface
*/
public function setSha1($options)
{
$this->setHash($options);
return $this;
}
/**
* Adds the sha1 hash for one or multiple files
*
* @param string|array $options
* @return Hash Provides a fluent interface
*/
public function addSha1($options)
{
$this->addHash($options);
return $this;
}
/**
* Returns true if and only if the given file confirms the set hash
*
* @param (int|string)[]|string $value Filename to check for hash
* @param array $file File data from \Laminas\File\Transfer\Transfer (optional)
* @return bool
*/
public function isValid($value, $file = null)
{
$fileInfo = $this->getFileInfo($value, $file);
$this->setValue($fileInfo['filename']);
// Is file readable ?
if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) {
$this->error(self::NOT_FOUND);
return false;
}
$hashes = array_unique(array_keys($this->getHash()));
$filehash = hash_file('sha1', $fileInfo['file']);
if ($filehash === false) {
$this->error(self::NOT_DETECTED);
return false;
}
foreach ($hashes as $hash) {
if ($filehash === $hash) {
return true;
}
}
$this->error(self::DOES_NOT_MATCH);
return false;
}
}
laminas-validator/src/File/ImageSize.php 0000644 00000024534 15240152634 0014221 0 ustar 00 <?php
namespace Laminas\Validator\File;
use Laminas\Stdlib\ErrorHandler;
use Laminas\Validator\AbstractValidator;
use Laminas\Validator\Exception;
use Traversable;
use function array_shift;
use function func_get_args;
use function func_num_args;
use function getimagesize;
use function is_array;
use function is_readable;
/**
* Validator for the image size of an image file
*/
class ImageSize extends AbstractValidator
{
use FileInformationTrait;
/**
* @const string Error constants
*/
public const WIDTH_TOO_BIG = 'fileImageSizeWidthTooBig';
public const WIDTH_TOO_SMALL = 'fileImageSizeWidthTooSmall';
public const HEIGHT_TOO_BIG = 'fileImageSizeHeightTooBig';
public const HEIGHT_TOO_SMALL = 'fileImageSizeHeightTooSmall';
public const NOT_DETECTED = 'fileImageSizeNotDetected';
public const NOT_READABLE = 'fileImageSizeNotReadable';
/** @var array Error message template */
protected $messageTemplates = [
self::WIDTH_TOO_BIG => "Maximum allowed width for image should be '%maxwidth%' but '%width%' detected",
self::WIDTH_TOO_SMALL => "Minimum expected width for image should be '%minwidth%' but '%width%' detected",
self::HEIGHT_TOO_BIG => "Maximum allowed height for image should be '%maxheight%' but '%height%' detected",
self::HEIGHT_TOO_SMALL => "Minimum expected height for image should be '%minheight%' but '%height%' detected",
self::NOT_DETECTED => 'The size of image could not be detected',
self::NOT_READABLE => 'File is not readable or does not exist',
];
/** @var array Error message template variables */
protected $messageVariables = [
'minwidth' => ['options' => 'minWidth'],
'maxwidth' => ['options' => 'maxWidth'],
'minheight' => ['options' => 'minHeight'],
'maxheight' => ['options' => 'maxHeight'],
'width' => 'width',
'height' => 'height',
];
/**
* Detected width
*
* @var int
*/
protected $width;
/**
* Detected height
*
* @var int
*/
protected $height;
/**
* Options for this validator
*
* @var array
*/
protected $options = [
'minWidth' => null, // Minimum image width
'maxWidth' => null, // Maximum image width
'minHeight' => null, // Minimum image height
'maxHeight' => null, // Maximum image height
];
/**
* Sets validator options
*
* Accepts the following option keys:
* - minheight
* - minwidth
* - maxheight
* - maxwidth
*
* @param null|array|Traversable $options
*/
public function __construct($options = null)
{
if (1 < func_num_args()) {
if (! is_array($options)) {
$options = ['minWidth' => $options];
}
$argv = func_get_args();
array_shift($argv);
$options['minHeight'] = array_shift($argv);
if (! empty($argv)) {
$options['maxWidth'] = array_shift($argv);
if (! empty($argv)) {
$options['maxHeight'] = array_shift($argv);
}
}
}
parent::__construct($options);
}
/**
* Returns the minimum allowed width
*
* @return int
*/
public function getMinWidth()
{
return $this->options['minWidth'];
}
/**
* Sets the minimum allowed width
*
* @param int $minWidth
* @return $this Provides a fluid interface
* @throws Exception\InvalidArgumentException When minwidth is greater than maxwidth.
*/
public function setMinWidth($minWidth)
{
if (($this->getMaxWidth() !== null) && ($minWidth > $this->getMaxWidth())) {
throw new Exception\InvalidArgumentException(
'The minimum image width must be less than or equal to the '
. " maximum image width, but {$minWidth} > {$this->getMaxWidth()}"
);
}
$this->options['minWidth'] = (int) $minWidth;
return $this;
}
/**
* Returns the maximum allowed width
*
* @return int
*/
public function getMaxWidth()
{
return $this->options['maxWidth'];
}
/**
* Sets the maximum allowed width
*
* @param int $maxWidth
* @return $this Provides a fluid interface
* @throws Exception\InvalidArgumentException When maxwidth is less than minwidth.
*/
public function setMaxWidth($maxWidth)
{
if (($this->getMinWidth() !== null) && ($maxWidth < $this->getMinWidth())) {
throw new Exception\InvalidArgumentException(
'The maximum image width must be greater than or equal to the '
. "minimum image width, but {$maxWidth} < {$this->getMinWidth()}"
);
}
$this->options['maxWidth'] = (int) $maxWidth;
return $this;
}
/**
* Returns the minimum allowed height
*
* @return int
*/
public function getMinHeight()
{
return $this->options['minHeight'];
}
/**
* Sets the minimum allowed height
*
* @param int $minHeight
* @return $this Provides a fluid interface
* @throws Exception\InvalidArgumentException When minheight is greater than maxheight.
*/
public function setMinHeight($minHeight)
{
if (($this->getMaxHeight() !== null) && ($minHeight > $this->getMaxHeight())) {
throw new Exception\InvalidArgumentException(
'The minimum image height must be less than or equal to the '
. " maximum image height, but {$minHeight} > {$this->getMaxHeight()}"
);
}
$this->options['minHeight'] = (int) $minHeight;
return $this;
}
/**
* Returns the maximum allowed height
*
* @return int
*/
public function getMaxHeight()
{
return $this->options['maxHeight'];
}
/**
* Sets the maximum allowed height
*
* @param int $maxHeight
* @return $this Provides a fluid interface
* @throws Exception\InvalidArgumentException When maxheight is less than minheight.
*/
public function setMaxHeight($maxHeight)
{
if (($this->getMinHeight() !== null) && ($maxHeight < $this->getMinHeight())) {
throw new Exception\InvalidArgumentException(
'The maximum image height must be greater than or equal to the '
. "minimum image height, but {$maxHeight} < {$this->getMinHeight()}"
);
}
$this->options['maxHeight'] = (int) $maxHeight;
return $this;
}
/**
* Returns the set minimum image sizes
*
* @return array
*/
public function getImageMin()
{
return ['minWidth' => $this->getMinWidth(), 'minHeight' => $this->getMinHeight()];
}
/**
* Returns the set maximum image sizes
*
* @return array
*/
public function getImageMax()
{
return ['maxWidth' => $this->getMaxWidth(), 'maxHeight' => $this->getMaxHeight()];
}
/**
* Returns the set image width sizes
*
* @return array
*/
public function getImageWidth()
{
return ['minWidth' => $this->getMinWidth(), 'maxWidth' => $this->getMaxWidth()];
}
/**
* Returns the set image height sizes
*
* @return array
*/
public function getImageHeight()
{
return ['minHeight' => $this->getMinHeight(), 'maxHeight' => $this->getMaxHeight()];
}
/**
* Sets the minimum image size
*
* @param array $options The minimum image dimensions
* @return $this Provides a fluent interface
*/
public function setImageMin($options)
{
$this->setOptions($options);
return $this;
}
/**
* Sets the maximum image size
*
* @param array|Traversable $options The maximum image dimensions
* @return $this Provides a fluent interface
*/
public function setImageMax($options)
{
$this->setOptions($options);
return $this;
}
/**
* Sets the minimum and maximum image width
*
* @param array $options The image width dimensions
* @return $this Provides a fluent interface
*/
public function setImageWidth($options)
{
$this->setImageMin($options);
$this->setImageMax($options);
return $this;
}
/**
* Sets the minimum and maximum image height
*
* @param array $options The image height dimensions
* @return $this Provides a fluent interface
*/
public function setImageHeight($options)
{
$this->setImageMin($options);
$this->setImageMax($options);
return $this;
}
/**
* Returns true if and only if the image size of $value is at least min and
* not bigger than max
*
* @param string|array $value Real file to check for image size
* @param array $file File data from \Laminas\File\Transfer\Transfer (optional)
* @return bool
*/
public function isValid($value, $file = null)
{
$fileInfo = $this->getFileInfo($value, $file);
$this->setValue($fileInfo['filename']);
// Is file readable ?
if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) {
$this->error(self::NOT_READABLE);
return false;
}
ErrorHandler::start();
$size = getimagesize($fileInfo['file']);
ErrorHandler::stop();
if (empty($size) || ($size[0] === 0) || ($size[1] === 0)) {
$this->error(self::NOT_DETECTED);
return false;
}
$this->width = $size[0];
$this->height = $size[1];
if ($this->width < $this->getMinWidth()) {
$this->error(self::WIDTH_TOO_SMALL);
}
if (($this->getMaxWidth() !== null) && ($this->getMaxWidth() < $this->width)) {
$this->error(self::WIDTH_TOO_BIG);
}
if ($this->height < $this->getMinHeight()) {
$this->error(self::HEIGHT_TOO_SMALL);
}
if (($this->getMaxHeight() !== null) && ($this->getMaxHeight() < $this->height)) {
$this->error(self::HEIGHT_TOO_BIG);
}
if ($this->getMessages()) {
return false;
}
return true;
}
}
laminas-validator/src/File/Md5.php 0000644 00000005244 15240152634 0012766 0 ustar 00 <?php
namespace Laminas\Validator\File;
use function array_keys;
use function array_unique;
use function hash_file;
use function is_readable;
/**
* Validator for the md5 hash of given files
*/
class Md5 extends Hash
{
use FileInformationTrait;
/**
* @const string Error constants
*/
public const DOES_NOT_MATCH = 'fileMd5DoesNotMatch';
public const NOT_DETECTED = 'fileMd5NotDetected';
public const NOT_FOUND = 'fileMd5NotFound';
/** @var array Error message templates */
protected $messageTemplates = [
self::DOES_NOT_MATCH => 'File does not match the given md5 hashes',
self::NOT_DETECTED => 'An md5 hash could not be evaluated for the given file',
self::NOT_FOUND => 'File is not readable or does not exist',
];
/**
* Options for this validator
*
* @var string
*/
protected $options = [
'algorithm' => 'md5',
'hash' => null,
];
/**
* Returns all set md5 hashes
*
* @return array
*/
public function getMd5()
{
return $this->getHash();
}
/**
* Sets the md5 hash for one or multiple files
*
* @param string|array $options
* @return Hash Provides a fluent interface
*/
public function setMd5($options)
{
$this->setHash($options);
return $this;
}
/**
* Adds the md5 hash for one or multiple files
*
* @param string|array $options
* @return Hash Provides a fluent interface
*/
public function addMd5($options)
{
$this->addHash($options);
return $this;
}
/**
* Returns true if and only if the given file confirms the set hash
*
* @param string|array $value Filename to check for hash
* @param array $file File data from \Laminas\File\Transfer\Transfer (optional)
* @return bool
*/
public function isValid($value, $file = null)
{
$fileInfo = $this->getFileInfo($value, $file);
$this->setValue($fileInfo['filename']);
// Is file readable ?
if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) {
$this->error(self::NOT_FOUND);
return false;
}
$hashes = array_unique(array_keys($this->getHash()));
$filehash = hash_file('md5', $fileInfo['file']);
if ($filehash === false) {
$this->error(self::NOT_DETECTED);
return false;
}
foreach ($hashes as $hash) {
if ($filehash === $hash) {
return true;
}
}
$this->error(self::DOES_NOT_MATCH);
return false;
}
}
laminas-validator/src/File/Crc32.php 0000644 00000005303 15240152635 0013212 0 ustar 00 <?php
namespace Laminas\Validator\File;
use function array_keys;
use function array_unique;
use function hash_file;
use function is_readable;
/**
* Validator for the crc32 hash of given files
*/
class Crc32 extends Hash
{
use FileInformationTrait;
/**
* @const string Error constants
*/
public const DOES_NOT_MATCH = 'fileCrc32DoesNotMatch';
public const NOT_DETECTED = 'fileCrc32NotDetected';
public const NOT_FOUND = 'fileCrc32NotFound';
/** @var array Error message templates */
protected $messageTemplates = [
self::DOES_NOT_MATCH => 'File does not match the given crc32 hashes',
self::NOT_DETECTED => 'A crc32 hash could not be evaluated for the given file',
self::NOT_FOUND => 'File is not readable or does not exist',
];
/**
* Options for this validator
*
* @var string
*/
protected $options = [
'algorithm' => 'crc32',
'hash' => null,
];
/**
* Returns all set crc32 hashes
*
* @return array
*/
public function getCrc32()
{
return $this->getHash();
}
/**
* Sets the crc32 hash for one or multiple files
*
* @param string|array $options
* @return $this Provides a fluent interface
*/
public function setCrc32($options)
{
$this->setHash($options);
return $this;
}
/**
* Adds the crc32 hash for one or multiple files
*
* @param string|array $options
* @return $this Provides a fluent interface
*/
public function addCrc32($options)
{
$this->addHash($options);
return $this;
}
/**
* Returns true if and only if the given file confirms the set hash
*
* @param string|array $value Filename to check for hash
* @param array $file File data from \Laminas\File\Transfer\Transfer (optional)
* @return bool
*/
public function isValid($value, $file = null)
{
$fileInfo = $this->getFileInfo($value, $file);
$this->setValue($fileInfo['filename']);
// Is file readable ?
if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) {
$this->error(self::NOT_FOUND);
return false;
}
$hashes = array_unique(array_keys($this->getHash()));
$filehash = hash_file('crc32', $fileInfo['file']);
if ($filehash === false) {
$this->error(self::NOT_DETECTED);
return false;
}
foreach ($hashes as $hash) {
if ($filehash === $hash) {
return true;
}
}
$this->error(self::DOES_NOT_MATCH);
return false;
}
}
laminas-validator/src/File/MimeType.php 0000644 00000030337 15240152635 0014074 0 ustar 00 <?php
namespace Laminas\Validator\File;
use Laminas\Stdlib\ArrayUtils;
use Laminas\Stdlib\ErrorHandler;
use Laminas\Validator\AbstractValidator;
use Laminas\Validator\Exception;
use Traversable;
use function array_key_exists;
use function array_keys;
use function array_merge;
use function array_unique;
use function class_exists;
use function explode;
use function finfo_file;
use function finfo_open;
use function getenv;
use function implode;
use function in_array;
use function is_array;
use function is_file;
use function is_int;
use function is_readable;
use function is_string;
use function sprintf;
use function trim;
use const E_NOTICE;
use const E_WARNING;
use const FILEINFO_MIME_TYPE;
/**
* Validator for the mime type of a file
*/
class MimeType extends AbstractValidator
{
use FileInformationTrait;
/**#@+
*
* @const Error type constants
*/
public const FALSE_TYPE = 'fileMimeTypeFalse';
public const NOT_DETECTED = 'fileMimeTypeNotDetected';
public const NOT_READABLE = 'fileMimeTypeNotReadable';
/**#@-*/
/** @var array Error message templates */
protected $messageTemplates = [
self::FALSE_TYPE => "File has an incorrect mimetype of '%type%'",
self::NOT_DETECTED => 'The mimetype could not be detected from the file',
self::NOT_READABLE => 'File is not readable or does not exist',
];
/** @var array */
protected $messageVariables = [
'type' => 'type',
];
/** @var string */
protected $type;
/**
* Finfo object to use
*
* @var resource
*/
protected $finfo;
/**
* If no environment variable 'MAGIC' is set, try and autodiscover it based on common locations
*
* @var array
*/
protected $magicFiles = [
'/usr/share/misc/magic',
'/usr/share/misc/magic.mime',
'/usr/share/misc/magic.mgc',
'/usr/share/mime/magic',
'/usr/share/mime/magic.mime',
'/usr/share/mime/magic.mgc',
'/usr/share/file/magic',
'/usr/share/file/magic.mime',
'/usr/share/file/magic.mgc',
];
/**
* Options for this validator
*
* @var array
*/
protected $options = [
'enableHeaderCheck' => false, // Allow header check
'disableMagicFile' => false, // Disable usage of magicfile
'magicFile' => null, // Magicfile to use
'mimeType' => null, // Mimetype to allow
];
/**
* Sets validator options
*
* Mimetype to accept
* - NULL means default PHP usage by using the environment variable 'magic'
* - FALSE means disabling searching for mimetype, should be used for PHP 5.3
* - A string is the mimetype file to use
*
* @param string|array|Traversable $options
*/
public function __construct($options = null)
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
} elseif (is_string($options)) {
$this->setMimeType($options);
$options = [];
} elseif (is_array($options)) {
if (isset($options['magicFile'])) {
$this->setMagicFile($options['magicFile']);
unset($options['magicFile']);
}
if (isset($options['enableHeaderCheck'])) {
$this->enableHeaderCheck($options['enableHeaderCheck']);
unset($options['enableHeaderCheck']);
}
if (array_key_exists('mimeType', $options)) {
$this->setMimeType($options['mimeType']);
unset($options['mimeType']);
}
// Handle cases where mimetypes are interspersed with options, or
// options are simply an array of mime types
foreach (array_keys($options) as $key) {
if (! is_int($key)) {
continue;
}
$this->addMimeType($options[$key]);
unset($options[$key]);
}
}
parent::__construct($options);
}
/**
* Returns the actual set magicfile
*
* @return string
*/
public function getMagicFile()
{
if (null === $this->options['magicFile']) {
$magic = getenv('magic');
if (! empty($magic)) {
$this->setMagicFile($magic);
if ($this->options['magicFile'] === null) {
$this->options['magicFile'] = false;
}
return $this->options['magicFile'];
}
foreach ($this->magicFiles as $file) {
try {
$this->setMagicFile($file);
} catch (Exception\ExceptionInterface) {
// suppressing errors which are thrown due to open_basedir restrictions
continue;
}
if ($this->options['magicFile'] !== null) {
return $this->options['magicFile'];
}
}
if ($this->options['magicFile'] === null) {
$this->options['magicFile'] = false;
}
}
return $this->options['magicFile'];
}
/**
* Sets the magicfile to use
* if null, the MAGIC constant from php is used
* if the MAGIC file is erroneous, no file will be set
* if false, the default MAGIC file from PHP will be used
*
* @param string $file
* @throws Exception\RuntimeException When finfo can not read the magicfile.
* @throws Exception\InvalidArgumentException
* @throws Exception\InvalidMagicMimeFileException
* @return $this Provides fluid interface
*/
public function setMagicFile($file)
{
if ($file === false) {
$this->options['magicFile'] = false;
} elseif (empty($file)) {
$this->options['magicFile'] = null;
} elseif (! class_exists('finfo', false)) {
$this->options['magicFile'] = null;
throw new Exception\RuntimeException('Magicfile can not be set; there is no finfo extension installed');
} elseif (! is_file($file) || ! is_readable($file)) {
throw new Exception\InvalidArgumentException(sprintf(
'The given magicfile ("%s") could not be read',
$file
));
} else {
ErrorHandler::start(E_NOTICE | E_WARNING);
$this->finfo = finfo_open(FILEINFO_MIME_TYPE, $file);
$error = ErrorHandler::stop();
if (empty($this->finfo)) {
$this->finfo = null;
throw new Exception\InvalidMagicMimeFileException(sprintf(
'The given magicfile ("%s") could not be used by ext/finfo',
$file
), 0, $error);
}
$this->options['magicFile'] = $file;
}
return $this;
}
/**
* Disables usage of MagicFile
*
* @param bool $disable False disables usage of magic file; true enables it.
* @return self Provides fluid interface
*/
public function disableMagicFile($disable)
{
$this->options['disableMagicFile'] = (bool) $disable;
return $this;
}
/**
* Is usage of MagicFile disabled?
*
* @return bool
*/
public function isMagicFileDisabled()
{
return $this->options['disableMagicFile'];
}
/**
* Returns the Header Check option
*
* @return bool
*/
public function getHeaderCheck()
{
return $this->options['enableHeaderCheck'];
}
/**
* Defines if the http header should be used
* Note that this is unsafe and therefor the default value is false
*
* @param bool $headerCheck
* @return $this Provides fluid interface
*/
public function enableHeaderCheck($headerCheck = true)
{
$this->options['enableHeaderCheck'] = (bool) $headerCheck;
return $this;
}
/**
* Returns the set mimetypes
*
* @param bool $asArray Returns the values as array, when false a concatenated string is returned
* @return string|array
* @psalm-return ($asArray is true ? list<string> : string)
*/
public function getMimeType($asArray = false)
{
$asArray = (bool) $asArray;
$mimetype = (string) $this->options['mimeType'];
if ($asArray) {
$mimetype = explode(',', $mimetype);
}
return $mimetype;
}
/**
* Sets the mimetypes
*
* @param string|array $mimetype The mimetypes to validate
* @return $this Provides a fluent interface
*/
public function setMimeType($mimetype)
{
$this->options['mimeType'] = null;
$this->addMimeType($mimetype);
return $this;
}
/**
* Adds the mimetypes
*
* @param string|array $mimetype The mimetypes to add for validation
* @throws Exception\InvalidArgumentException
* @return $this Provides a fluent interface
*/
public function addMimeType($mimetype)
{
$mimetypes = $this->getMimeType(true);
if (is_string($mimetype)) {
$mimetype = explode(',', $mimetype);
} elseif (! is_array($mimetype)) {
throw new Exception\InvalidArgumentException('Invalid options to validator provided');
}
if (isset($mimetype['magicFile'])) {
unset($mimetype['magicFile']);
}
foreach ($mimetype as $content) {
if (empty($content) || ! is_string($content)) {
continue;
}
$mimetypes[] = trim($content);
}
$mimetypes = array_unique($mimetypes);
// Sanity check to ensure no empty values
foreach ($mimetypes as $key => $mt) {
if (empty($mt)) {
unset($mimetypes[$key]);
}
}
$this->options['mimeType'] = implode(',', $mimetypes);
return $this;
}
/**
* Defined by Laminas\Validator\ValidatorInterface
*
* Returns true if the mimetype of the file matches the given ones. Also parts
* of mimetypes can be checked. If you give for example "image" all image
* mime types will be accepted like "image/gif", "image/jpeg" and so on.
*
* @param string|array $value Real file to check for mimetype
* @param array $file File data from \Laminas\File\Transfer\Transfer (optional)
* @return bool
*/
public function isValid($value, $file = null)
{
$fileInfo = $this->getFileInfo($value, $file, true);
$this->setValue($fileInfo['filename']);
// Is file readable ?
if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) {
$this->error(static::NOT_READABLE);
return false;
}
$mimefile = $this->getMagicFile();
if (class_exists('finfo', false)) {
if (! $this->isMagicFileDisabled() && (! empty($mimefile) && empty($this->finfo))) {
ErrorHandler::start(E_NOTICE | E_WARNING);
$this->finfo = finfo_open(FILEINFO_MIME_TYPE, $mimefile);
ErrorHandler::stop();
}
if (empty($this->finfo)) {
ErrorHandler::start(E_NOTICE | E_WARNING);
$this->finfo = finfo_open(FILEINFO_MIME_TYPE);
ErrorHandler::stop();
}
$this->type = null;
if (! empty($this->finfo)) {
$this->type = finfo_file($this->finfo, $fileInfo['file']);
unset($this->finfo);
}
}
if (empty($this->type) && $this->getHeaderCheck()) {
$this->type = $fileInfo['filetype'];
}
if (empty($this->type)) {
$this->error(static::NOT_DETECTED);
return false;
}
$mimetype = $this->getMimeType(true);
if (in_array($this->type, $mimetype)) {
return true;
}
$types = explode('/', $this->type);
$types = array_merge($types, explode('-', $this->type));
$types = array_merge($types, explode(';', $this->type));
foreach ($mimetype as $mime) {
if (in_array($mime, $types)) {
return true;
}
}
$this->error(static::FALSE_TYPE);
return false;
}
}
laminas-validator/src/File/Exists.php 0000644 00000011556 15240152635 0013624 0 ustar 00 <?php
namespace Laminas\Validator\File;
use Laminas\Validator\AbstractValidator;
use Laminas\Validator\Exception;
use Traversable;
use function array_key_exists;
use function array_unique;
use function explode;
use function file_exists;
use function implode;
use function is_array;
use function is_string;
use function trim;
use const DIRECTORY_SEPARATOR;
/**
* Validator which checks if the file already exists in the directory
*/
class Exists extends AbstractValidator
{
use FileInformationTrait;
/**
* @const string Error constants
*/
public const DOES_NOT_EXIST = 'fileExistsDoesNotExist';
/** @var array Error message templates */
protected $messageTemplates = [
self::DOES_NOT_EXIST => 'File does not exist',
];
/**
* Options for this validator
*
* @var array
*/
protected $options = [
'directory' => null, // internal list of directories
];
/** @var array Error message template variables */
protected $messageVariables = [
'directory' => ['options' => 'directory'],
];
/**
* Sets validator options
*
* @param string|array|Traversable $options
*/
public function __construct($options = null)
{
if (is_string($options)) {
$options = explode(',', $options);
}
if (is_array($options) && ! array_key_exists('directory', $options)) {
$options = ['directory' => $options];
}
parent::__construct($options);
}
/**
* Returns the set file directories which are checked
*
* @param bool $asArray Returns the values as array; when false, a concatenated string is returned
* @return string|null
*/
public function getDirectory($asArray = false)
{
$asArray = (bool) $asArray;
$directory = $this->options['directory'];
if ($asArray && isset($directory)) {
$directory = explode(',', (string) $directory);
}
return $directory;
}
/**
* Sets the file directory which will be checked
*
* @param string|array $directory The directories to validate
* @return self Provides a fluent interface
*/
public function setDirectory($directory)
{
$this->options['directory'] = null;
$this->addDirectory($directory);
return $this;
}
/**
* Adds the file directory which will be checked
*
* @param string|array $directory The directory to add for validation
* @return self Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function addDirectory($directory)
{
$directories = $this->getDirectory(true);
if (! isset($directories)) {
$directories = [];
}
if (is_string($directory)) {
$directory = explode(',', $directory);
} elseif (! is_array($directory)) {
throw new Exception\InvalidArgumentException('Invalid options to validator provided');
}
foreach ($directory as $content) {
if (empty($content) || ! is_string($content)) {
continue;
}
$directories[] = trim($content);
}
$directories = array_unique($directories);
// Sanity check to ensure no empty values
foreach ($directories as $key => $dir) {
if (empty($dir)) {
unset($directories[$key]);
}
}
$this->options['directory'] = ! empty($directory)
? implode(',', $directories) : null;
return $this;
}
/**
* Returns true if and only if the file already exists in the set directories
*
* @param string|array $value Real file to check for existence
* @param array $file File data from \Laminas\File\Transfer\Transfer (optional)
* @return bool
*/
public function isValid($value, $file = null)
{
$fileInfo = $this->getFileInfo($value, $file, false, true);
$this->setValue($fileInfo['filename']);
$check = false;
$directories = $this->getDirectory(true);
if (! isset($directories)) {
$check = true;
if (! file_exists($fileInfo['file'])) {
$this->error(self::DOES_NOT_EXIST);
return false;
}
} else {
foreach ($directories as $directory) {
if (! isset($directory) || '' === $directory) {
continue;
}
$check = true;
if (! file_exists($directory . DIRECTORY_SEPARATOR . $fileInfo['basename'])) {
$this->error(self::DOES_NOT_EXIST);
return false;
}
}
}
if (! $check) {
$this->error(self::DOES_NOT_EXIST);
return false;
}
return true;
}
}
laminas-validator/src/Date.php 0000644 00000013414 15240152635 0012336 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Validator;
use DateTime;
use DateTimeImmutable;
use DateTimeInterface;
use Traversable;
use function array_shift;
use function func_get_args;
use function gettype;
use function implode;
use function is_array;
use function iterator_to_array;
/**
* Validates that a given value is a DateTime instance or can be converted into one.
*/
class Date extends AbstractValidator
{
/**#@+
* Validity constants
*/
public const INVALID = 'dateInvalid';
public const INVALID_DATE = 'dateInvalidDate';
public const FALSEFORMAT = 'dateFalseFormat';
/**#@-*/
/**
* Default format constant
*/
public const FORMAT_DEFAULT = 'Y-m-d';
/**
* Validation failure message template definitions
*
* @var string[]
*/
protected $messageTemplates = [
self::INVALID => 'Invalid type given. String, integer, array or DateTime expected',
self::INVALID_DATE => 'The input does not appear to be a valid date',
self::FALSEFORMAT => "The input does not fit the date format '%format%'",
];
/** @var string[] */
protected $messageVariables = [
'format' => 'format',
];
/** @var string */
protected $format = self::FORMAT_DEFAULT;
/** @var bool */
protected $strict = false;
/**
* Sets validator options
*
* @param string|array|Traversable $options OPTIONAL
*/
public function __construct($options = [])
{
if ($options instanceof Traversable) {
$options = iterator_to_array($options);
} elseif (! is_array($options)) {
$options = func_get_args();
$temp['format'] = array_shift($options);
$options = $temp;
}
parent::__construct($options);
}
/**
* Returns the format option
*
* @return string
*/
public function getFormat()
{
return $this->format;
}
/**
* Sets the format option
*
* Format cannot be null. It will always default to 'Y-m-d', even
* if null is provided.
*
* @param string|null $format
* @return $this provides a fluent interface
* @todo validate the format
*/
public function setFormat($format = self::FORMAT_DEFAULT)
{
$this->format = empty($format) ? self::FORMAT_DEFAULT : $format;
return $this;
}
public function setStrict(bool $strict): self
{
$this->strict = $strict;
return $this;
}
public function isStrict(): bool
{
return $this->strict;
}
/**
* Returns true if $value is a DateTimeInterface instance or can be converted into one.
*
* @param string|numeric|array|DateTimeInterface $value
* @return bool
*/
public function isValid($value)
{
$this->setValue($value);
$date = $this->convertToDateTime($value);
if (! $date) {
$this->error(self::INVALID_DATE);
return false;
}
if ($this->isStrict() && $date->format($this->getFormat()) !== $value) {
$this->error(self::FALSEFORMAT);
return false;
}
return true;
}
/**
* Attempts to convert an int, string, or array to a DateTime object
*
* @param string|numeric|array|DateTimeInterface $param
* @param bool $addErrors
* @return false|DateTime
*/
protected function convertToDateTime($param, $addErrors = true)
{
if ($param instanceof DateTime) {
return $param;
}
if ($param instanceof DateTimeImmutable) {
return DateTime::createFromImmutable($param);
}
$type = gettype($param);
switch ($type) {
case 'string':
return $this->convertString($param, $addErrors);
case 'integer':
return $this->convertInteger($param);
case 'double':
return $this->convertDouble($param);
case 'array':
return $this->convertArray($param, $addErrors);
}
if ($addErrors) {
$this->error(self::INVALID);
}
return false;
}
/**
* Attempts to convert an integer into a DateTime object
*
* @param integer $value
* @return false|DateTime
*/
protected function convertInteger($value)
{
return DateTime::createFromFormat('U', (string) $value);
}
/**
* Attempts to convert an double into a DateTime object
*
* @param double $value
* @return false|DateTime
*/
protected function convertDouble($value)
{
return DateTime::createFromFormat('U', (string) $value);
}
/**
* Attempts to convert a string into a DateTime object
*
* @param string $value
* @param bool $addErrors
* @return false|DateTime
*/
protected function convertString($value, $addErrors = true)
{
$date = DateTime::createFromFormat($this->format, $value);
// Invalid dates can show up as warnings (ie. "2007-02-99")
// and still return a DateTime object.
$errors = DateTime::getLastErrors();
if ($errors === false) {
return $date;
}
if ($errors['warning_count'] > 0) {
if ($addErrors) {
$this->error(self::FALSEFORMAT);
}
return false;
}
return $date;
}
/**
* Implodes the array into a string and proxies to {@link convertString()}.
*
* @param bool $addErrors
* @return false|DateTime
* @todo enhance the implosion
*/
protected function convertArray(array $value, $addErrors = true)
{
return $this->convertString(implode('-', $value), $addErrors);
}
}
laminas-validator/src/ValidatorChain.php 0000644 00000023222 15240152635 0014347 0 ustar 00 <?php // phpcs:disable SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse
namespace Laminas\Validator;
use Countable;
use IteratorAggregate;
use Laminas\ServiceManager\ServiceManager;
use Laminas\Stdlib\PriorityQueue;
use ReturnTypeWillChange;
use Traversable;
use function array_replace;
use function assert;
use function count;
use function rsort;
use const SORT_NUMERIC;
/**
* @psalm-type QueueElement = array{instance: ValidatorInterface, breakChainOnFailure: bool}
* @implements IteratorAggregate<array-key, QueueElement>
* @final
*/
class ValidatorChain implements Countable, IteratorAggregate, ValidatorInterface
{
/**
* Default priority at which validators are added
*/
public const DEFAULT_PRIORITY = 1;
/** @var ValidatorPluginManager<ValidatorInterface>|null */
protected $plugins;
/**
* Validator chain
*
* @var PriorityQueue<QueueElement, int>
*/
protected $validators;
/**
* Array of validation failure messages
*
* @var array<string, string>
*/
protected $messages = [];
/**
* Initialize validator chain
*/
public function __construct()
{
/** @psalm-suppress InvalidPropertyAssignmentValue */
$this->validators = new PriorityQueue();
}
/**
* Return the count of attached validators
*
* @return int
*/
#[ReturnTypeWillChange]
public function count()
{
return count($this->validators);
}
/**
* Get plugin manager instance
*
* @return ValidatorPluginManager<ValidatorInterface>
*/
public function getPluginManager()
{
if (! $this->plugins) {
$this->setPluginManager(new ValidatorPluginManager(new ServiceManager()));
}
return $this->plugins;
}
/**
* Set plugin manager instance
*
* @param ValidatorPluginManager $plugins Plugin manager
* @psalm-assert ValidatorPluginManager $this->plugins
* @return $this
*/
public function setPluginManager(ValidatorPluginManager $plugins)
{
$this->plugins = $plugins;
return $this;
}
/**
* Retrieve a validator by name
*
* @param string|class-string<ValidatorInterface> $name Name of validator to return
* @param null|array $options Options to pass to validator constructor
* (if not already instantiated)
* @return ValidatorInterface
* @template T of ValidatorInterface
* @psalm-param string|class-string<T> $name
* @psalm-return ValidatorInterface
*/
public function plugin($name, ?array $options = null)
{
$plugins = $this->getPluginManager();
return $plugins->get($name, $options);
}
/**
* Attach a validator to the end of the chain
* If $breakChainOnFailure is true, then if the validator fails, the next validator in the chain,
* if one exists, will not be executed.
*
* @param bool $breakChainOnFailure
* @param int $priority Priority at which to enqueue validator; defaults to
* 1 (higher executes earlier)
* @return $this
* @throws Exception\InvalidArgumentException
*/
public function attach(
ValidatorInterface $validator,
$breakChainOnFailure = false,
$priority = self::DEFAULT_PRIORITY
) {
/** @psalm-suppress RedundantCastGivenDocblockType */
$this->validators->insert(
[
'instance' => $validator,
'breakChainOnFailure' => (bool) $breakChainOnFailure,
],
$priority
);
return $this;
}
/**
* Proxy to attach() to keep BC
*
* @deprecated Please use attach()
*
* @param bool $breakChainOnFailure
* @param int $priority
* @return ValidatorChain Provides a fluent interface
*/
public function addValidator(
ValidatorInterface $validator,
$breakChainOnFailure = false,
$priority = self::DEFAULT_PRIORITY
) {
return $this->attach($validator, $breakChainOnFailure, $priority);
}
/**
* Adds a validator to the beginning of the chain
*
* If $breakChainOnFailure is true, then if the validator fails, the next validator in the chain,
* if one exists, will not be executed.
*
* @param bool $breakChainOnFailure
* @return $this Provides a fluent interface
*/
public function prependValidator(ValidatorInterface $validator, $breakChainOnFailure = false)
{
$priority = self::DEFAULT_PRIORITY;
if (! $this->validators->isEmpty()) {
$extractedNodes = $this->validators->toArray(PriorityQueue::EXTR_PRIORITY);
rsort($extractedNodes, SORT_NUMERIC);
$priority = $extractedNodes[0] + 1;
}
/** @psalm-suppress RedundantCastGivenDocblockType */
$this->validators->insert(
[
'instance' => $validator,
'breakChainOnFailure' => (bool) $breakChainOnFailure,
],
$priority
);
return $this;
}
/**
* Use the plugin manager to add a validator by name
*
* @param string|class-string<ValidatorInterface> $name
* @param array $options
* @param bool $breakChainOnFailure
* @param int $priority
* @return $this
*/
public function attachByName($name, $options = [], $breakChainOnFailure = false, $priority = self::DEFAULT_PRIORITY)
{
if (isset($options['break_chain_on_failure'])) {
$breakChainOnFailure = (bool) $options['break_chain_on_failure'];
}
if (isset($options['breakchainonfailure'])) {
$breakChainOnFailure = (bool) $options['breakchainonfailure'];
}
$this->attach($this->plugin($name, $options), $breakChainOnFailure, $priority);
return $this;
}
/**
* Proxy to attachByName() to keep BC
*
* @deprecated Please use attachByName()
*
* @param string $name
* @param array $options
* @param bool $breakChainOnFailure
* @return ValidatorChain
*/
public function addByName($name, $options = [], $breakChainOnFailure = false)
{
return $this->attachByName($name, $options, $breakChainOnFailure);
}
/**
* Use the plugin manager to prepend a validator by name
*
* @param string|class-string<ValidatorInterface> $name
* @param array $options
* @param bool $breakChainOnFailure
* @return $this
*/
public function prependByName($name, $options = [], $breakChainOnFailure = false)
{
$validator = $this->plugin($name, $options);
$this->prependValidator($validator, $breakChainOnFailure);
return $this;
}
/**
* Returns true if and only if $value passes all validations in the chain
*
* Validators are run in the order in which they were added to the chain (FIFO).
*
* @param mixed $value
* @param mixed $context Extra "context" to provide the validator
* @return bool
*/
public function isValid($value, $context = null)
{
$this->messages = [];
$result = true;
foreach ($this as $element) {
$validator = $element['instance'];
assert($validator instanceof ValidatorInterface);
if ($validator->isValid($value, $context)) {
continue;
}
$result = false;
$messages = $validator->getMessages();
$this->messages = array_replace($this->messages, $messages);
if ($element['breakChainOnFailure']) {
break;
}
}
return $result;
}
/**
* Merge the validator chain with the one given in parameter
*
* @return $this
*/
public function merge(ValidatorChain $validatorChain)
{
foreach ($validatorChain->validators->toArray(PriorityQueue::EXTR_BOTH) as $item) {
$this->attach($item['data']['instance'], $item['data']['breakChainOnFailure'], $item['priority']);
}
return $this;
}
/**
* Returns array of validation failure messages
*
* @return array<string, string>
*/
public function getMessages()
{
return $this->messages;
}
/**
* Get all the validators
*
* @return list<QueueElement>
*/
public function getValidators()
{
return $this->validators->toArray(PriorityQueue::EXTR_DATA);
}
/**
* Invoke chain as command
*
* @return bool
*/
public function __invoke(mixed $value)
{
return $this->isValid($value);
}
/**
* Deep clone handling
*/
public function __clone()
{
$this->validators = clone $this->validators;
}
/**
* Prepare validator chain for serialization
*
* Plugin manager (property 'plugins') cannot
* be serialized. On wakeup the property remains unset
* and next invocation to getPluginManager() sets
* the default plugin manager instance (ValidatorPluginManager).
*
* @return array
*/
public function __sleep()
{
return ['validators', 'messages'];
}
/** @return Traversable<array-key, QueueElement> */
public function getIterator(): Traversable
{
return clone $this->validators;
}
}
laminas-validator/src/Regex.php 0000644 00000006675 15240152635 0012546 0 ustar 00 <?php
namespace Laminas\Validator;
use Laminas\Stdlib\ArrayUtils;
use Laminas\Stdlib\ErrorHandler;
use Traversable;
use function array_key_exists;
use function is_array;
use function is_float;
use function is_int;
use function is_string;
use function preg_match;
class Regex extends AbstractValidator
{
public const INVALID = 'regexInvalid';
public const NOT_MATCH = 'regexNotMatch';
public const ERROROUS = 'regexErrorous';
/** @var array */
protected $messageTemplates = [
self::INVALID => 'Invalid type given. String, integer or float expected',
self::NOT_MATCH => "The input does not match against pattern '%pattern%'",
self::ERROROUS => "There was an internal error while using the pattern '%pattern%'",
];
/** @var array */
protected $messageVariables = [
'pattern' => 'pattern',
];
/**
* Regular expression pattern
*
* @var string
*/
protected $pattern;
/**
* Sets validator options
*
* @param string|array|Traversable $pattern
* @throws Exception\InvalidArgumentException On missing 'pattern' parameter.
*/
public function __construct($pattern)
{
if (is_string($pattern)) {
$this->setPattern($pattern);
parent::__construct([]);
return;
}
if ($pattern instanceof Traversable) {
$pattern = ArrayUtils::iteratorToArray($pattern);
}
if (! is_array($pattern)) {
throw new Exception\InvalidArgumentException('Invalid options provided to constructor');
}
if (! array_key_exists('pattern', $pattern)) {
throw new Exception\InvalidArgumentException("Missing option 'pattern'");
}
$this->setPattern($pattern['pattern']);
unset($pattern['pattern']);
parent::__construct($pattern);
}
/**
* Returns the pattern option
*
* @return string
*/
public function getPattern()
{
return $this->pattern;
}
/**
* Sets the pattern option
*
* @param string $pattern
* @throws Exception\InvalidArgumentException If there is a fatal error in pattern matching.
* @return $this Provides a fluent interface
*/
public function setPattern($pattern)
{
ErrorHandler::start();
$this->pattern = (string) $pattern;
$status = preg_match($this->pattern, 'Test');
$error = ErrorHandler::stop();
if (false === $status) {
throw new Exception\InvalidArgumentException(
"Internal error parsing the pattern '{$this->pattern}'",
0,
$error
);
}
return $this;
}
/**
* Returns true if and only if $value matches against the pattern option
*
* @param string $value
* @return bool
*/
public function isValid($value)
{
if (! is_string($value) && ! is_int($value) && ! is_float($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
ErrorHandler::start();
$status = preg_match($this->pattern, $value);
ErrorHandler::stop();
if (false === $status) {
$this->error(self::ERROROUS);
return false;
}
if (! $status) {
$this->error(self::NOT_MATCH);
return false;
}
return true;
}
}
laminas-validator/src/Uuid.php 0000644 00000002713 15240152635 0012367 0 ustar 00 <?php
namespace Laminas\Validator;
use function is_string;
use function preg_match;
/**
* Uuid validator.
*/
final class Uuid extends AbstractValidator
{
/**
* Matches Uuid's versions 1 to 5.
*/
public const REGEX_UUID = '/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/';
public const INVALID = 'valueNotUuid';
public const NOT_STRING = 'valueNotString';
/** @var array */
protected $messageTemplates = [
self::NOT_STRING => 'Invalid type given; string expected',
self::INVALID => 'Invalid UUID format',
];
/**
* Returns true if and only if $value meets the validation requirements.
*
* If $value fails validation, then this method returns false, and
* getMessages() will return an array of messages that explain why the
* validation failed.
*
* @param mixed $value
* @return bool
* @throws Exception\RuntimeException If validation of $value is impossible.
*/
public function isValid($value)
{
if (! is_string($value)) {
$this->error(self::NOT_STRING);
return false;
}
$this->setValue($value);
if (
empty($value)
|| $value !== '00000000-0000-0000-0000-000000000000'
&& ! preg_match(self::REGEX_UUID, $value)
) {
$this->error(self::INVALID);
return false;
}
return true;
}
}
laminas-validator/src/Between.php 0000644 00000013277 15240152635 0013061 0 ustar 00 <?php
namespace Laminas\Validator;
use Laminas\Stdlib\ArrayUtils;
use Traversable;
use function array_key_exists;
use function array_shift;
use function func_get_args;
use function is_array;
use function is_numeric;
use function is_string;
use const PHP_INT_MAX;
class Between extends AbstractValidator
{
public const NOT_BETWEEN = 'notBetween';
public const NOT_BETWEEN_STRICT = 'notBetweenStrict';
public const VALUE_NOT_NUMERIC = 'valueNotNumeric';
public const VALUE_NOT_STRING = 'valueNotString';
/**
* Retain if min and max are numeric values. Allow to not compare string and numeric types
*/
private ?bool $numeric = null;
/**
* Validation failure message template definitions
*
* @var array<string, string>
*/
protected $messageTemplates = [
self::NOT_BETWEEN => "The input is not between '%min%' and '%max%', inclusively",
self::NOT_BETWEEN_STRICT => "The input is not strictly between '%min%' and '%max%'",
self::VALUE_NOT_NUMERIC => "The min ('%min%') and max ('%max%') values are numeric, but the input is not",
self::VALUE_NOT_STRING => "The min ('%min%') and max ('%max%') values are non-numeric strings, "
. 'but the input is not a string',
];
/**
* Additional variables available for validation failure messages
*
* @var array
*/
protected $messageVariables = [
'min' => ['options' => 'min'],
'max' => ['options' => 'max'],
];
/**
* Options for the between validator
*
* @var array
*/
protected $options = [
'inclusive' => true, // Whether to do inclusive comparisons, allowing equivalence to min and/or max
'min' => 0,
'max' => PHP_INT_MAX,
];
/**
* Sets validator options
* Accepts the following option keys:
* 'min' => scalar, minimum border
* 'max' => scalar, maximum border
* 'inclusive' => boolean, inclusive border values
*
* @param array<string, mixed>|Traversable<string, mixed> $options
* @throws Exception\InvalidArgumentException
*/
public function __construct($options = null)
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (! is_array($options)) {
$temp = [];
/** @psalm-var array<string, int|string> $options */
$options = func_get_args();
$temp['min'] = array_shift($options);
if (! empty($options)) {
$temp['max'] = array_shift($options);
}
if (! empty($options)) {
$temp['inclusive'] = array_shift($options);
}
$options = $temp;
}
if (! array_key_exists('min', $options) || ! array_key_exists('max', $options)) {
throw new Exception\InvalidArgumentException("Missing option: 'min' and 'max' have to be given");
}
if (
(isset($options['min']) && is_numeric($options['min']))
&& (isset($options['max']) && is_numeric($options['max']))
) {
$this->numeric = true;
} elseif (
(isset($options['min']) && is_string($options['min']))
&& (isset($options['max']) && is_string($options['max']))
) {
$this->numeric = false;
} else {
throw new Exception\InvalidArgumentException(
"Invalid options: 'min' and 'max' should be of the same scalar type"
);
}
parent::__construct($options);
}
/**
* Returns the min option
*
* @return mixed
*/
public function getMin()
{
return $this->options['min'];
}
/**
* Sets the min option
*
* @return $this Provides a fluent interface
*/
public function setMin(mixed $min)
{
$this->options['min'] = $min;
return $this;
}
/**
* Returns the max option
*
* @return mixed
*/
public function getMax()
{
return $this->options['max'];
}
/**
* Sets the max option
*
* @return $this Provides a fluent interface
*/
public function setMax(mixed $max)
{
$this->options['max'] = $max;
return $this;
}
/**
* Returns the inclusive option
*
* @return bool
*/
public function getInclusive()
{
return $this->options['inclusive'];
}
/**
* Sets the inclusive option
*
* @param bool $inclusive
* @return $this Provides a fluent interface
*/
public function setInclusive($inclusive)
{
$this->options['inclusive'] = $inclusive;
return $this;
}
/**
* Returns true if and only if $value is between min and max options, inclusively
* if inclusive option is true.
*
* @param mixed $value
* @return bool
*/
public function isValid($value)
{
$this->setValue($value);
if ($this->numeric && ! is_numeric($value)) {
$this->error(self::VALUE_NOT_NUMERIC);
return false;
}
if (! $this->numeric && ! is_string($value)) {
$this->error(self::VALUE_NOT_STRING);
return false;
}
if ($this->getInclusive()) {
if ($this->getMin() > $value || $value > $this->getMax()) {
$this->error(self::NOT_BETWEEN);
return false;
}
} else {
if ($this->getMin() >= $value || $value >= $this->getMax()) {
$this->error(self::NOT_BETWEEN_STRICT);
return false;
}
}
return true;
}
}
laminas-validator/src/DateStep.php 0000644 00000042120 15240152635 0013166 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Validator;
use DateInterval;
use DateTime;
use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;
use Laminas\Stdlib\ArrayUtils;
use Traversable;
use function array_combine;
use function array_count_values;
use function array_map;
use function array_shift;
use function ceil;
use function date_default_timezone_get;
use function explode;
use function floor;
use function func_get_args;
use function in_array;
use function is_array;
use function max;
use function min;
use function preg_match;
use function sprintf;
use function str_starts_with;
use const PHP_INT_MAX;
class DateStep extends Date
{
/**
* Validity constants
*/
public const NOT_STEP = 'dateStepNotStep';
/**
* Default format constant
*/
public const FORMAT_DEFAULT = DateTime::ISO8601;
/**
* Validation failure message template definitions
*
* @var string[]
*/
protected $messageTemplates = [
self::INVALID => 'Invalid type given. String, integer, array or DateTime expected',
self::INVALID_DATE => 'The input does not appear to be a valid date',
self::FALSEFORMAT => "The input does not fit the date format '%format%'",
self::NOT_STEP => 'The input is not a valid step',
];
/**
* Optional base date value
*
* @var string|int|DateTimeInterface
*/
protected $baseValue = '1970-01-01T00:00:00Z';
/**
* Date step interval (defaults to 1 day).
* Uses the DateInterval specification.
*
* @var DateInterval
*/
protected $step;
/**
* Optional timezone to be used when the baseValue
* and validation values do not contain timezone info
*
* @var DateTimeZone
*/
protected $timezone;
/**
* Set default options for this instance
*
* @param string|array|Traversable $options
*/
public function __construct($options = [])
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
} elseif (! is_array($options)) {
$options = func_get_args();
$temp = [];
$temp['baseValue'] = array_shift($options);
if (! empty($options)) {
$temp['step'] = array_shift($options);
}
if (! empty($options)) {
$temp['format'] = array_shift($options);
}
if (! empty($options)) {
$temp['timezone'] = array_shift($options);
}
$options = $temp;
}
if (! isset($options['step'])) {
$options['step'] = new DateInterval('P1D');
}
if (! isset($options['timezone'])) {
$options['timezone'] = new DateTimeZone(date_default_timezone_get());
}
parent::__construct($options);
}
/**
* Sets the base value from which the step should be computed
*
* @param string|int|DateTimeInterface $baseValue
* @return $this
*/
public function setBaseValue($baseValue)
{
$this->baseValue = $baseValue;
return $this;
}
/**
* Returns the base value from which the step should be computed
*
* @return string|int|DateTimeInterface
*/
public function getBaseValue()
{
return $this->baseValue;
}
/**
* Sets the step date interval
*
* @return $this
*/
public function setStep(DateInterval $step)
{
$this->step = $step;
return $this;
}
/**
* Returns the step date interval
*
* @return DateInterval
*/
public function getStep()
{
return $this->step;
}
/**
* Returns the timezone option
*
* @return DateTimeZone
*/
public function getTimezone()
{
return $this->timezone;
}
/**
* Sets the timezone option
*
* @return $this
*/
public function setTimezone(DateTimeZone $timezone)
{
$this->timezone = $timezone;
return $this;
}
/**
* Supports formats with ISO week (W) definitions
*
* @see Date::convertString()
*
* @param string $value
* @param bool $addErrors
* @return DateTime|false
*/
protected function convertString($value, $addErrors = true)
{
// Custom week format support
if (
str_starts_with($this->format, 'Y-\WW')
&& preg_match('/^([0-9]{4})\-W([0-9]{2})/', $value, $matches)
) {
$date = new DateTime();
$date->setISODate((int) $matches[1], (int) $matches[2]);
} else {
$date = DateTime::createFromFormat($this->format, $value, new DateTimeZone('UTC'));
}
// Invalid dates can show up as warnings (ie. "2007-02-99")
// and still return a DateTime object.
$errors = DateTime::getLastErrors();
if (is_array($errors) && $errors['warning_count'] > 0) {
if ($addErrors) {
$this->error(self::FALSEFORMAT);
}
return false;
}
return $date;
}
/**
* Returns true if a date is within a valid step
*
* @param string|int|DateTimeInterface $value
* @return bool
* @throws Exception\InvalidArgumentException
*/
public function isValid($value)
{
if (! parent::isValid($value)) {
return false;
}
$valueDate = $this->convertToDateTime($value, false); // avoid duplicate errors
$baseDate = $this->convertToDateTime($this->baseValue, false);
if (false === $valueDate || false === $baseDate) {
return false;
}
$step = $this->getStep();
// Same date?
// phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator
if ($valueDate == $baseDate) {
return true;
}
// Optimization for simple intervals.
// Handle intervals of just one date or time unit.
$intervalParts = explode('|', $step->format('%y|%m|%d|%h|%i|%s'));
$intervalParts = array_map('intval', $intervalParts);
$partCounts = array_count_values($intervalParts);
$unitKeys = ['years', 'months', 'days', 'hours', 'minutes', 'seconds'];
$intervalParts = array_combine($unitKeys, $intervalParts);
// Get absolute time difference to avoid special cases of missing/added time
$absoluteValueDate = new DateTime($valueDate->format('Y-m-d H:i:s'), new DateTimeZone('UTC'));
$absoluteBaseDate = new DateTime($baseDate->format('Y-m-d H:i:s'), new DateTimeZone('UTC'));
$timeDiff = $absoluteValueDate->diff($absoluteBaseDate, true);
$diffParts = array_map('intval', explode('|', $timeDiff->format('%y|%m|%d|%h|%i|%s')));
$diffParts = array_combine($unitKeys, $diffParts);
if (5 === $partCounts[0]) {
// Find the unit with the non-zero interval
$intervalUnit = 'days';
$stepValue = 1;
foreach ($intervalParts as $key => $value) {
if (0 !== $value) {
$intervalUnit = $key;
$stepValue = $value;
break;
}
}
// Check date units
if (in_array($intervalUnit, ['years', 'months', 'days'])) {
switch ($intervalUnit) {
case 'years':
if (
0 === $diffParts['months'] && 0 === $diffParts['days']
&& 0 === $diffParts['hours'] && 0 === $diffParts['minutes']
&& 0 === $diffParts['seconds']
) {
if (($diffParts['years'] % $stepValue) === 0) {
return true;
}
}
break;
case 'months':
if (
0 === $diffParts['days'] && 0 === $diffParts['hours']
&& 0 === $diffParts['minutes'] && 0 === $diffParts['seconds']
) {
$months = ($diffParts['years'] * 12) + $diffParts['months'];
if (($months % $stepValue) === 0) {
return true;
}
}
break;
case 'days':
if (
0 === $diffParts['hours'] && 0 === $diffParts['minutes']
&& 0 === $diffParts['seconds']
) {
$days = (int) $timeDiff->format('%a'); // Total days
if (($days % $stepValue) === 0) {
return true;
}
}
break;
}
$this->error(self::NOT_STEP);
return false;
}
// Check time units
if (in_array($intervalUnit, ['hours', 'minutes', 'seconds'])) {
// Simple test if $stepValue is 1.
if (1 === $stepValue) {
if (
'hours' === $intervalUnit
&& 0 === $diffParts['minutes'] && 0 === $diffParts['seconds']
) {
return true;
} elseif ('minutes' === $intervalUnit && 0 === $diffParts['seconds']) {
return true;
} elseif ('seconds' === $intervalUnit) {
return true;
}
$this->error(self::NOT_STEP);
return false;
}
// Simple test for same day, when using default baseDate
if (
$baseDate->format('Y-m-d') === $valueDate->format('Y-m-d')
&& $baseDate->format('Y-m-d') === '1970-01-01'
) {
switch ($intervalUnit) {
case 'hours':
if (0 === $diffParts['minutes'] && 0 === $diffParts['seconds']) {
if (($diffParts['hours'] % $stepValue) === 0) {
return true;
}
}
break;
case 'minutes':
if (0 === $diffParts['seconds']) {
$minutes = ($diffParts['hours'] * 60) + $diffParts['minutes'];
if (($minutes % $stepValue) === 0) {
return true;
}
}
break;
case 'seconds':
$seconds = ($diffParts['hours'] * 60 * 60)
+ ($diffParts['minutes'] * 60)
+ $diffParts['seconds'];
if (($seconds % $stepValue) === 0) {
return true;
}
break;
}
$this->error(self::NOT_STEP);
return false;
}
}
}
return $this->fallbackIncrementalIterationLogic($baseDate, $valueDate, $intervalParts, $diffParts, $step);
}
/**
* Fall back to slower (but accurate) method for complex intervals.
* Keep adding steps to the base date until a match is found
* or until the value is exceeded.
*
* This is really slow if the interval is small, especially if the
* default base date of 1/1/1970 is used. We can skip a chunk of
* iterations by starting at the lower bound of steps needed to reach
* the target
*
* @param int[] $intervalParts
* @param int[] $diffParts
* @throws Exception\InvalidArgumentException
*/
private function fallbackIncrementalIterationLogic(
DateTimeInterface $baseDate,
DateTimeInterface $valueDate,
array $intervalParts,
array $diffParts,
DateInterval $step
): bool {
[$minSteps, $requiredIterations] = $this->computeMinStepAndRequiredIterations($intervalParts, $diffParts);
$minimumInterval = $this->computeMinimumInterval($intervalParts, $minSteps);
$isIncrementalStepping = $baseDate < $valueDate;
if (! ($baseDate instanceof DateTime || $baseDate instanceof DateTimeImmutable)) {
throw new Exception\InvalidArgumentException(sprintf(
'Function %s requires the baseDate to be a DateTime or DateTimeImmutable instance.',
__FUNCTION__
));
}
for ($offsetIterations = 0; $offsetIterations < $requiredIterations; $offsetIterations += 1) {
if ($isIncrementalStepping) {
$baseDate = $baseDate->add($minimumInterval);
} else {
$baseDate = $baseDate->sub($minimumInterval);
}
}
while (
($isIncrementalStepping && $baseDate < $valueDate)
|| (! $isIncrementalStepping && $baseDate > $valueDate)
) {
if ($isIncrementalStepping) {
$baseDate = $baseDate->add($step);
} else {
$baseDate = $baseDate->sub($step);
}
// phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator
if ($baseDate == $valueDate) {
return true;
}
}
$this->error(self::NOT_STEP);
return false;
}
/**
* Computes minimum interval to use for iterations while checking steps
*
* @param int[] $intervalParts
* @param int|float $minSteps
*/
private function computeMinimumInterval(array $intervalParts, $minSteps): DateInterval
{
return new DateInterval(sprintf(
'P%dY%dM%dDT%dH%dM%dS',
$intervalParts['years'] * $minSteps,
$intervalParts['months'] * $minSteps,
$intervalParts['days'] * $minSteps,
$intervalParts['hours'] * $minSteps,
$intervalParts['minutes'] * $minSteps,
$intervalParts['seconds'] * $minSteps
));
}
/**
* @param int[] $intervalParts
* @param int[] $diffParts
* @return int[] (ordered tuple containing minimum steps and required step iterations
* @psalm-return array{0: int, 1: int}
*/
private function computeMinStepAndRequiredIterations(array $intervalParts, array $diffParts): array
{
$minSteps = $this->computeMinSteps($intervalParts, $diffParts);
// If we use PHP_INT_MAX DateInterval::__construct falls over with a bad format error
// before we reach the max on 64 bit machines
$maxInteger = min(2 ** 31, PHP_INT_MAX);
// check for integer overflow and split $minimum interval if needed
$maximumInterval = max($intervalParts);
$requiredStepIterations = 1;
if (($minSteps * $maximumInterval) > $maxInteger) {
$requiredStepIterations = ceil(($minSteps * $maximumInterval) / $maxInteger);
$minSteps = floor($minSteps / $requiredStepIterations);
}
return [(int) $minSteps, $minSteps ? (int) $requiredStepIterations : 0];
}
/**
* Multiply the step interval by the lower bound of steps to reach the target
*
* @param int[] $intervalParts
* @param int[] $diffParts
* @return float|int
*/
private function computeMinSteps(array $intervalParts, array $diffParts)
{
$intervalMaxSeconds = $this->computeIntervalMaxSeconds($intervalParts);
return 0 === $intervalMaxSeconds
? 0
: max(floor($this->computeDiffMinSeconds($diffParts) / $intervalMaxSeconds) - 1, 0);
}
/**
* Get upper bound of the given interval in seconds
* Converts a given `$intervalParts` array into seconds
*
* @param int[] $intervalParts
*/
private function computeIntervalMaxSeconds(array $intervalParts): int
{
return ($intervalParts['years'] * 60 * 60 * 24 * 366)
+ ($intervalParts['months'] * 60 * 60 * 24 * 31)
+ ($intervalParts['days'] * 60 * 60 * 24)
+ ($intervalParts['hours'] * 60 * 60)
+ ($intervalParts['minutes'] * 60)
+ $intervalParts['seconds'];
}
/**
* Get lower bound of difference in secondss
* Converts a given `$diffParts` array into seconds
*
* @param int[] $diffParts
*/
private function computeDiffMinSeconds(array $diffParts): int
{
return ($diffParts['years'] * 60 * 60 * 24 * 365)
+ ($diffParts['months'] * 60 * 60 * 24 * 28)
+ ($diffParts['days'] * 60 * 60 * 24)
+ ($diffParts['hours'] * 60 * 60)
+ ($diffParts['minutes'] * 60)
+ $diffParts['seconds'];
}
}
laminas-validator/src/Step.php 0000644 00000007566 15240152635 0012407 0 ustar 00 <?php
namespace Laminas\Validator;
use Traversable;
use function array_shift;
use function floor;
use function func_get_args;
use function is_array;
use function is_numeric;
use function iterator_to_array;
use function round;
use function strlen;
use function strpos;
use function substr;
class Step extends AbstractValidator
{
public const INVALID = 'typeInvalid';
public const NOT_STEP = 'stepInvalid';
/** @var array */
protected $messageTemplates = [
self::INVALID => 'Invalid value given. Scalar expected',
self::NOT_STEP => 'The input is not a valid step',
];
/** @var mixed */
protected $baseValue = 0;
/** @var mixed */
protected $step = 1;
/**
* Set default options for this instance
*
* @param array $options
*/
public function __construct($options = [])
{
if ($options instanceof Traversable) {
$options = iterator_to_array($options);
} elseif (! is_array($options)) {
$options = func_get_args();
$temp['baseValue'] = array_shift($options);
if (! empty($options)) {
$temp['step'] = array_shift($options);
}
$options = $temp;
}
if (isset($options['baseValue'])) {
$this->setBaseValue($options['baseValue']);
}
if (isset($options['step'])) {
$this->setStep($options['step']);
}
parent::__construct($options);
}
/**
* Sets the base value from which the step should be computed
*
* @return $this
*/
public function setBaseValue(mixed $baseValue)
{
$this->baseValue = $baseValue;
return $this;
}
/**
* Returns the base value from which the step should be computed
*
* @return string
*/
public function getBaseValue()
{
return $this->baseValue;
}
/**
* Sets the step value
*
* @return $this
*/
public function setStep(mixed $step)
{
$this->step = (float) $step;
return $this;
}
/**
* Returns the step value
*
* @return string
*/
public function getStep()
{
return $this->step;
}
/**
* Returns true if $value is a scalar and a valid step value
*
* @param mixed $value
* @return bool
*/
public function isValid($value)
{
if (! is_numeric($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
$substract = $this->sub($value, $this->baseValue);
$fmod = $this->fmod($substract, $this->step);
if ($fmod !== 0.0 && $fmod !== $this->step) {
$this->error(self::NOT_STEP);
return false;
}
return true;
}
/**
* replaces the internal fmod function which give wrong results on many cases
*
* @param int|float $x
* @param int|float $y
* @return float
*/
protected function fmod($x, $y)
{
if ($y === 0.0 || $y === 0) {
return 1.0;
}
//find the maximum precision from both input params to give accurate results
$precision = $this->getPrecision($x) + $this->getPrecision($y);
return round($x - $y * floor($x / $y), $precision);
}
/**
* replaces the internal substraction operation which give wrong results on some cases
*
* @param float $x
* @param float $y
* @return float
*/
private function sub($x, $y)
{
$precision = $this->getPrecision($x) + $this->getPrecision($y);
return round($x - $y, $precision);
}
/**
* @param float $float
* @return int
*/
private function getPrecision($float)
{
$segment = substr($float, strpos($float, '.') + 1);
return $segment ? strlen($segment) : 0;
}
}
laminas-validator/src/Csrf.php 0000644 00000020063 15240152635 0012354 0 ustar 00 <?php
namespace Laminas\Validator;
use Laminas\Session\Container as SessionContainer;
use Laminas\Stdlib\ArrayUtils;
use Traversable;
use function explode;
use function is_array;
use function is_string;
use function md5;
use function random_bytes;
use function sprintf;
use function str_replace;
use function strtolower;
use function strtr;
class Csrf extends AbstractValidator
{
/**
* Error codes
*
* @const string
*/
public const NOT_SAME = 'notSame';
/**
* Error messages
*
* @var array
*/
protected $messageTemplates = [
self::NOT_SAME => 'The form submitted did not originate from the expected site',
];
/**
* Actual hash used.
*
* @var mixed
*/
protected $hash;
/**
* Static cache of the session names to generated hashes
*
* @todo unused, left here to avoid BC breaks
* @var array
*/
protected static $hashCache;
/**
* Name of CSRF element (used to create non-colliding hashes)
*
* @var string
*/
protected $name = 'csrf';
/**
* Salt for CSRF token
*
* @var string
*/
protected $salt = 'salt';
/** @var SessionContainer */
protected $session;
/**
* TTL for CSRF token
*
* @var int|null
*/
protected $timeout = 300;
/**
* Constructor
*
* @param array|Traversable $options
*/
public function __construct($options = [])
{
parent::__construct($options);
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (! is_array($options)) {
$options = (array) $options;
}
foreach ($options as $key => $value) {
switch (strtolower($key)) {
case 'name':
$this->setName($value);
break;
case 'salt':
$this->setSalt($value);
break;
case 'session':
$this->setSession($value);
break;
case 'timeout':
$this->setTimeout($value);
break;
default:
// ignore unknown options
break;
}
}
}
/**
* Does the provided token match the one generated?
*
* @param string $value
* @param mixed $context
* @return bool
*/
public function isValid($value, $context = null)
{
if (! is_string($value)) {
return false;
}
$this->setValue($value);
$tokenId = $this->getTokenIdFromHash($value);
$hash = $this->getValidationToken($tokenId);
$tokenFromValue = $this->getTokenFromHash($value);
$tokenFromHash = $this->getTokenFromHash($hash);
if (! $tokenFromValue || ! $tokenFromHash || ($tokenFromValue !== $tokenFromHash)) {
$this->error(self::NOT_SAME);
return false;
}
return true;
}
/**
* Set CSRF name
*
* @param string $name
* @return $this
*/
public function setName($name)
{
$this->name = (string) $name;
return $this;
}
/**
* Get CSRF name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set session container
*
* @return $this
*/
public function setSession(SessionContainer $session)
{
$this->session = $session;
if ($this->hash) {
$this->initCsrfToken();
}
return $this;
}
/**
* Get session container
*
* Instantiate session container if none currently exists
*
* @return SessionContainer
*/
public function getSession()
{
if (null === $this->session) {
// Using fully qualified name, to ensure polyfill class alias is used
$this->session = new SessionContainer($this->getSessionName());
}
return $this->session;
}
/**
* Salt for CSRF token
*
* @param string $salt
* @return $this
*/
public function setSalt($salt)
{
$this->salt = (string) $salt;
return $this;
}
/**
* Retrieve salt for CSRF token
*
* @return string
*/
public function getSalt()
{
return $this->salt;
}
/**
* Retrieve CSRF token
*
* If no CSRF token currently exists, or should be regenerated,
* generates one.
*
* @param bool $regenerate default false
* @return string
*/
public function getHash($regenerate = false)
{
if ((null === $this->hash) || $regenerate) {
$this->generateHash();
}
return $this->hash;
}
/**
* Get session namespace for CSRF token
*
* Generates a session namespace based on salt, element name, and class.
*
* @return string
*/
public function getSessionName()
{
return str_replace('\\', '_', self::class) . '_'
. $this->getSalt() . '_'
. strtr($this->getName(), ['[' => '_', ']' => '']);
}
/**
* Set timeout for CSRF session token
*
* @param int|null $ttl
* @return $this
*/
public function setTimeout($ttl)
{
$this->timeout = $ttl !== null ? (int) $ttl : null;
return $this;
}
/**
* Get CSRF session token timeout
*
* @return int|null
*/
public function getTimeout()
{
return $this->timeout;
}
/**
* Initialize CSRF token in session
*
* @return void
*/
protected function initCsrfToken()
{
$session = $this->getSession();
$timeout = $this->getTimeout();
if (null !== $timeout) {
$session->setExpirationSeconds($timeout);
}
$hash = $this->getHash();
$token = $this->getTokenFromHash($hash);
$tokenId = $this->getTokenIdFromHash($hash);
if (! $session->tokenList) {
$session->tokenList = [];
}
$session->tokenList[$tokenId] = $token;
$session->hash = $hash; // @todo remove this, left for BC
}
/**
* Generate CSRF token
*
* Generates CSRF token and stores both in {@link $hash} and element
* value.
*
* @return void
*/
protected function generateHash()
{
$token = md5($this->getSalt() . random_bytes(32) . $this->getName());
$this->hash = $this->formatHash($token, $this->generateTokenId());
$this->setValue($this->hash);
$this->initCsrfToken();
}
/**
* @return string
*/
protected function generateTokenId()
{
return md5(random_bytes(32));
}
/**
* Get validation token
*
* Retrieve token from session, if it exists.
*
* @param string $tokenId
* @return null|string
*/
protected function getValidationToken($tokenId = null)
{
$session = $this->getSession();
/**
* if no tokenId is passed we revert to the old behaviour
*
* @todo remove, here for BC
*/
if (! $tokenId && isset($session->hash)) {
return $session->hash;
}
if ($tokenId && isset($session->tokenList[$tokenId])) {
return $this->formatHash($session->tokenList[$tokenId], $tokenId);
}
return null;
}
/**
* @return string
*/
protected function formatHash(string $token, string $tokenId)
{
return sprintf('%s-%s', $token, $tokenId);
}
protected function getTokenFromHash(?string $hash): ?string
{
if (null === $hash) {
return null;
}
$data = explode('-', $hash);
return $data[0] ?: null;
}
protected function getTokenIdFromHash(string $hash): ?string
{
$data = explode('-', $hash);
if (! isset($data[1])) {
return null;
}
return $data[1];
}
}
laminas-validator/src/Barcode/Codabar.php 0000644 00000003163 15240152635 0014353 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
use function strpbrk;
use function substr;
class Codabar extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(-1);
$this->setCharacters('0123456789-$:/.+ABCDTN*E');
$this->useChecksum(false);
}
/**
* Checks for allowed characters
*
* @see Laminas\Validator\Barcode.AbstractAdapter::checkChars()
*
* @param string $value
* @return bool
*/
public function hasValidCharacters($value)
{
if (strpbrk($value, 'ABCD')) {
$first = $value[0];
if (! strpbrk($first, 'ABCD')) {
// Missing start char
return false;
}
$last = substr($value, -1, 1);
if (! strpbrk($last, 'ABCD')) {
// Missing stop char
return false;
}
$value = substr($value, 1, -1);
} elseif (strpbrk($value, 'TN*E')) {
$first = $value[0];
if (! strpbrk($first, 'TN*E')) {
// Missing start char
return false;
}
$last = substr($value, -1, 1);
if (! strpbrk($last, 'TN*E')) {
// Missing stop char
return false;
}
$value = substr($value, 1, -1);
}
$chars = $this->getCharacters();
$this->setCharacters('0123456789-$:/.+');
$result = parent::hasValidCharacters($value);
$this->setCharacters($chars);
return $result;
}
}
laminas-validator/src/Barcode/Gtin14.php 0000644 00000000456 15240152635 0014070 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Gtin14 extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(14);
$this->setCharacters('0123456789');
$this->setChecksum('gtin');
}
}
laminas-validator/src/Barcode/Code39ext.php 0000644 00000000447 15240152635 0014571 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Code39ext extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(-1);
$this->setCharacters(128);
$this->useChecksum(false);
}
}
laminas-validator/src/Barcode/AdapterInterface.php 0000644 00000002411 15240152635 0016214 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
interface AdapterInterface
{
/**
* Checks the length of a barcode
*
* @param string $value The barcode to check for proper length
* @return bool
*/
public function hasValidLength($value);
/**
* Checks for allowed characters within the barcode
*
* @param string $value The barcode to check for allowed characters
* @return bool
*/
public function hasValidCharacters($value);
/**
* Validates the checksum
*
* @param string $value The barcode to check the checksum for
* @return bool
*/
public function hasValidChecksum($value);
/**
* Returns the allowed barcode length
*
* @return int|array
*/
public function getLength();
/**
* Returns the allowed characters
*
* @return int|string|array
*/
public function getCharacters();
/**
* Returns if barcode uses a checksum
*
* @return bool|int|string
*/
public function getChecksum();
/**
* Sets the checksum validation, if no value is given, the actual setting is returned
*
* @param bool $check
* @return AbstractAdapter|bool
*/
public function useChecksum($check = null);
}
laminas-validator/src/Barcode/Sscc.php 0000644 00000000454 15240152635 0013713 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Sscc extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(18);
$this->setCharacters('0123456789');
$this->setChecksum('gtin');
}
}
laminas-validator/src/Barcode/Code128.php 0000644 00000047477 15240152635 0014145 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
use Laminas\Stdlib\StringUtils;
use Laminas\Stdlib\StringWrapper\StringWrapperInterface;
use Laminas\Validator\Exception;
use function chr;
use function is_string;
use function ord;
class Code128 extends AbstractAdapter
{
/**
* The used string wrapper used for basic UTF-8 string functions
*
* @var StringWrapperInterface
*/
protected $utf8StringWrapper;
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(-1);
$this->setCharacters([
'A' => [
0 => ' ',
1 => '!',
2 => '"',
3 => '#',
4 => '$',
5 => '%',
6 => '&',
7 => "'",
8 => '(',
9 => ')',
10 => '*',
11 => '+',
12 => ',',
13 => '-',
14 => '.',
15 => '/',
16 => '0',
17 => '1',
18 => '2',
19 => '3',
20 => '4',
21 => '5',
22 => '6',
23 => '7',
24 => '8',
25 => '9',
26 => ':',
27 => ';',
28 => '<',
29 => '=',
30 => '>',
31 => '?',
32 => '@',
33 => 'A',
34 => 'B',
35 => 'C',
36 => 'D',
37 => 'E',
38 => 'F',
39 => 'G',
40 => 'H',
41 => 'I',
42 => 'J',
43 => 'K',
44 => 'L',
45 => 'M',
46 => 'N',
47 => 'O',
48 => 'P',
49 => 'Q',
50 => 'R',
51 => 'S',
52 => 'T',
53 => 'U',
54 => 'V',
55 => 'W',
56 => 'X',
57 => 'Y',
58 => 'Z',
59 => '[',
60 => '\\',
61 => ']',
62 => '^',
63 => '_',
64 => 0x00,
65 => 0x01,
66 => 0x02,
67 => 0x03,
68 => 0x04,
69 => 0x05,
70 => 0x06,
71 => 0x07,
72 => 0x08,
73 => 0x09,
74 => 0x0A,
75 => 0x0B,
76 => 0x0C,
77 => 0x0D,
78 => 0x0E,
79 => 0x0F,
80 => 0x10,
81 => 0x11,
82 => 0x12,
83 => 0x13,
84 => 0x14,
85 => 0x15,
86 => 0x16,
87 => 0x17,
88 => 0x18,
89 => 0x19,
90 => 0x1A,
91 => 0x1B,
92 => 0x1C,
93 => 0x1D,
94 => 0x1E,
95 => 0x1F,
96 => 'Ç',
97 => 'ü',
98 => 'é',
99 => 'â',
100 => 'ä',
101 => 'à',
102 => 'å',
103 => '‡',
104 => 'ˆ',
105 => '‰',
106 => 'Š',
],
'B' => [
0 => ' ',
1 => '!',
2 => '"',
3 => '#',
4 => '$',
5 => '%',
6 => '&',
7 => "'",
8 => '(',
9 => ')',
10 => '*',
11 => '+',
12 => ',',
13 => '-',
14 => '.',
15 => '/',
16 => '0',
17 => '1',
18 => '2',
19 => '3',
20 => '4',
21 => '5',
22 => '6',
23 => '7',
24 => '8',
25 => '9',
26 => ':',
27 => ';',
28 => '<',
29 => '=',
30 => '>',
31 => '?',
32 => '@',
33 => 'A',
34 => 'B',
35 => 'C',
36 => 'D',
37 => 'E',
38 => 'F',
39 => 'G',
40 => 'H',
41 => 'I',
42 => 'J',
43 => 'K',
44 => 'L',
45 => 'M',
46 => 'N',
47 => 'O',
48 => 'P',
49 => 'Q',
50 => 'R',
51 => 'S',
52 => 'T',
53 => 'U',
54 => 'V',
55 => 'W',
56 => 'X',
57 => 'Y',
58 => 'Z',
59 => '[',
60 => '\\',
61 => ']',
62 => '^',
63 => '_',
64 => '`',
65 => 'a',
66 => 'b',
67 => 'c',
68 => 'd',
69 => 'e',
70 => 'f',
71 => 'g',
72 => 'h',
73 => 'i',
74 => 'j',
75 => 'k',
76 => 'l',
77 => 'm',
78 => 'n',
79 => 'o',
80 => 'p',
81 => 'q',
82 => 'r',
83 => 's',
84 => 't',
85 => 'u',
86 => 'v',
87 => 'w',
88 => 'x',
89 => 'y',
90 => 'z',
91 => '{',
92 => '|',
93 => '}',
94 => '~',
95 => 0x7F,
96 => 'Ç',
97 => 'ü',
98 => 'é',
99 => 'â',
100 => 'ä',
101 => 'à',
102 => 'å',
103 => '‡',
104 => 'ˆ',
105 => '‰',
106 => 'Š',
],
'C' => [
0 => '00',
1 => '01',
2 => '02',
3 => '03',
4 => '04',
5 => '05',
6 => '06',
7 => '07',
8 => '08',
9 => '09',
10 => '10',
11 => '11',
12 => '12',
13 => '13',
14 => '14',
15 => '15',
16 => '16',
17 => '17',
18 => '18',
19 => '19',
20 => '20',
21 => '21',
22 => '22',
23 => '23',
24 => '24',
25 => '25',
26 => '26',
27 => '27',
28 => '28',
29 => '29',
30 => '30',
31 => '31',
32 => '32',
33 => '33',
34 => '34',
35 => '35',
36 => '36',
37 => '37',
38 => '38',
39 => '39',
40 => '40',
41 => '41',
42 => '42',
43 => '43',
44 => '44',
45 => '45',
46 => '46',
47 => '47',
48 => '48',
49 => '49',
50 => '50',
51 => '51',
52 => '52',
53 => '53',
54 => '54',
55 => '55',
56 => '56',
57 => '57',
58 => '58',
59 => '59',
60 => '60',
61 => '61',
62 => '62',
63 => '63',
64 => '64',
65 => '65',
66 => '66',
67 => '67',
68 => '68',
69 => '69',
70 => '70',
71 => '71',
72 => '72',
73 => '73',
74 => '74',
75 => '75',
76 => '76',
77 => '77',
78 => '78',
79 => '79',
80 => '80',
81 => '81',
82 => '82',
83 => '83',
84 => '84',
85 => '85',
86 => '86',
87 => '87',
88 => '88',
89 => '89',
90 => '90',
91 => '91',
92 => '92',
93 => '93',
94 => '94',
95 => '95',
96 => '96',
97 => '97',
98 => '98',
99 => '99',
100 => 'ä',
101 => 'à',
102 => 'å',
103 => '‡',
104 => 'ˆ',
105 => '‰',
106 => 'Š',
],
]);
$this->setChecksum('code128');
}
/**
* @return void
*/
public function setUtf8StringWrapper(StringWrapperInterface $utf8StringWrapper)
{
if (! $utf8StringWrapper->isSupported('UTF-8')) {
throw new Exception\InvalidArgumentException(
'The string wrapper needs to support UTF-8 character encoding'
);
}
$this->utf8StringWrapper = $utf8StringWrapper;
}
/**
* Get the string wrapper supporting UTF-8 character encoding
*
* @return StringWrapperInterface
*/
public function getUtf8StringWrapper()
{
if (! $this->utf8StringWrapper) {
$this->utf8StringWrapper = StringUtils::getWrapper('UTF-8');
}
return $this->utf8StringWrapper;
}
/**
* Checks for allowed characters within the barcode
*
* @param string $value The barcode to check for allowed characters
* @return bool
*/
public function hasValidCharacters($value)
{
if (! is_string($value)) {
return false;
}
// get used string wrapper for UTF-8 character encoding
$strWrapper = $this->getUtf8StringWrapper();
// detect starting charset
$set = $this->getCodingSet($value);
$read = $set;
if ($set !== '') {
$value = $strWrapper->substr($value, 1, null);
}
// process barcode
while ($value !== '' && $value !== false) {
$char = $strWrapper->substr($value, 0, 1);
switch ($char) {
// Function definition
case 'Ç':
case 'ü':
case 'å':
break;
// Switch 1 char between A and B
case 'é':
if ($set === 'A') {
$read = 'B';
break;
}
if ($set === 'B') {
$read = 'A';
break;
}
break;
// Switch to C
case 'â':
$set = 'C';
$read = 'C';
break;
// Switch to B
case 'ä':
$set = 'B';
$read = 'B';
break;
// Switch to A
case 'à':
$set = 'A';
$read = 'A';
break;
// Doubled start character
case '‡':
case 'ˆ':
case '‰':
return false;
// Chars after the stop character
case 'Š':
break 2;
default:
// Does the char exist within the charset to read?
if ($this->ord128($char, $read) === -1) {
return false;
}
break;
}
$value = $strWrapper->substr($value, 1, null);
$read = $set;
}
if ($value !== '' && is_string($value) && $strWrapper->strlen($value) !== 1) {
return false;
}
return true;
}
/**
* Validates the checksum ()
*
* @param string $value The barcode to validate
* @return bool
*/
protected function code128($value)
{
$sum = 0;
$pos = 1;
$set = $this->getCodingSet($value);
$read = $set;
$usecheck = $this->useChecksum(null);
$strWrapper = $this->getUtf8StringWrapper();
$char = $strWrapper->substr($value, 0, 1);
if ($char === '‡') {
$sum = 103;
} elseif ($char === 'ˆ') {
$sum = 104;
} elseif ($char === '‰') {
$sum = 105;
} elseif ($usecheck === true) {
// no start value, unable to detect a proper checksum
return false;
}
$value = $strWrapper->substr($value, 1, null);
while ($strWrapper->strpos($value, 'Š') || ($value !== '')) {
$char = $strWrapper->substr($value, 0, 1);
if ($read === 'C') {
$char = $strWrapper->substr($value, 0, 2);
}
switch ($char) {
// Function definition
case 'Ç':
case 'ü':
case 'å':
$sum += $pos * $this->ord128($char, $set);
break;
case 'é':
$sum += $pos * $this->ord128($char, $set);
if ($set === 'A') {
$read = 'B';
break;
}
if ($set === 'B') {
$read = 'A';
break;
}
break;
// Switch to C
case 'â':
$sum += $pos * $this->ord128($char, $set);
$set = 'C';
$read = 'C';
break;
// Switch to B
case 'ä':
$sum += $pos * $this->ord128($char, $set);
$set = 'B';
$read = 'B';
break;
// Switch to A
case 'à':
$sum += $pos * $this->ord128($char, $set);
$set = 'A';
$read = 'A';
break;
case '‡':
case 'ˆ':
case '‰':
return false;
default:
// Does the char exist within the charset to read?
if ($this->ord128($char, $read) === -1) {
return false;
}
$sum += $pos * $this->ord128($char, $set);
break;
}
$value = $strWrapper->substr($value, 1);
++$pos;
if (($strWrapper->strpos($value, 'Š') === 1) && ($strWrapper->strlen($value) === 2)) {
// break by stop and checksum char
break;
}
$read = $set;
}
if (($strWrapper->strpos($value, 'Š') !== 1) || ($strWrapper->strlen($value) !== 2)) {
// return false if checksum is not readable and true if no startvalue is detected
return ! $usecheck;
}
$mod = $sum % 103;
if ($strWrapper->substr($value, 0, 1) === $this->chr128($mod, $set)) {
return true;
}
return false;
}
/**
* Returns the coding set for a barcode
*
* @param string $value Barcode
* @return string
*/
protected function getCodingSet($value)
{
$value = $this->getUtf8StringWrapper()->substr($value, 0, 1);
return match ($value) {
'‡' => 'A',
'ˆ' => 'B',
'‰' => 'C',
default => '',
};
}
/**
* Internal method to return the code128 integer from an ascii value
*
* Table A
* ASCII CODE128
* 32 to 95 == 0 to 63
* 0 to 31 == 64 to 95
* 128 to 138 == 96 to 106
*
* Table B
* ASCII CODE128
* 32 to 138 == 0 to 106
*
* Table C
* ASCII CODE128
* "00" to "99" == 0 to 99
* 132 to 138 == 100 to 106
*
* @param string $value
* @param string $set
* @return int
*/
protected function ord128($value, $set)
{
$ord = ord($value);
if ($set === 'A') {
if ($ord < 32) {
return $ord + 64;
} elseif ($ord < 96) {
return $ord - 32;
} elseif ($ord > 138) {
return -1;
} else {
return $ord - 32;
}
} elseif ($set === 'B') {
if ($ord < 32) {
return -1;
} elseif ($ord <= 138) {
return $ord - 32;
} else {
return -1;
}
} elseif ($set === 'C') {
$val = (int) $value;
if (($val >= 0) && ($val <= 99)) {
return $val;
} elseif (($ord >= 132) && ($ord <= 138)) {
return $ord - 32;
} else {
return -1;
}
} else {
if ($ord < 32) {
return $ord + 64;
} elseif ($ord <= 138) {
return $ord - 32;
} else {
return -1;
}
}
}
/**
* Internal Method to return the ascii value from a code128 integer
*
* Table A
* ASCII CODE128
* 32 to 95 == 0 to 63
* 0 to 31 == 64 to 95
* 128 to 138 == 96 to 106
*
* Table B
* ASCII CODE128
* 32 to 138 == 0 to 106
*
* Table C
* ASCII CODE128
* "00" to "99" == 0 to 99
* 132 to 138 == 100 to 106
*
* @param int $value
* @param string $set
* @return int|string
*/
protected function chr128($value, $set)
{
if ($set === 'A') {
if ($value < 64) {
return chr($value + 32);
} elseif ($value < 96) {
return chr($value - 64);
} elseif ($value > 106) {
return -1;
} else {
return chr($value + 32);
}
} elseif ($set === 'B') {
if ($value > 106) {
return -1;
} else {
return chr($value + 32);
}
} elseif ($set === 'C') {
if (($value >= 0) && ($value <= 9)) {
return '0' . (string) $value;
} elseif ($value <= 99) {
return (string) $value;
} elseif ($value <= 106) {
return chr($value + 32);
} else {
return -1;
}
} else {
if ($value <= 106) {
return $value + 32;
} else {
return -1;
}
}
}
}
laminas-validator/src/Barcode/Itf14.php 0000644 00000000455 15240152635 0013710 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Itf14 extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(14);
$this->setCharacters('0123456789');
$this->setChecksum('gtin');
}
}
laminas-validator/src/Barcode/Issn.php 0000644 00000003732 15240152635 0013736 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
use function str_contains;
use function str_split;
use function strlen;
use function substr;
class Issn extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength([8, 13]);
$this->setCharacters('0123456789X');
$this->setChecksum('gtin');
}
/**
* Allows X on length of 8 chars
*
* @param string $value The barcode to check for allowed characters
* @return bool
*/
public function hasValidCharacters($value)
{
if (strlen($value) !== 8) {
if (str_contains($value, 'X')) {
return false;
}
}
return parent::hasValidCharacters($value);
}
/**
* Validates the checksum
*
* @param string $value The barcode to check the checksum for
* @return bool
*/
public function hasValidChecksum($value)
{
if (strlen($value) === 8) {
$this->setChecksum('issn');
} else {
$this->setChecksum('gtin');
}
return parent::hasValidChecksum($value);
}
/**
* Validates the checksum ()
* ISSN implementation (reversed mod11)
*
* @param string $value The barcode to validate
* @return bool
*/
protected function issn($value)
{
$checksum = substr($value, -1, 1);
$values = str_split(substr($value, 0, -1));
$check = 0;
$multi = 8;
foreach ($values as $token) {
if ($token === 'X') {
$token = 10;
}
$check += $token * $multi;
--$multi;
}
$check %= 11;
$check = $check === 0 ? 0 : 11 - $check;
if ((string) $check === $checksum) {
return true;
}
if (($check === 10) && ($checksum === 'X')) {
return true;
}
return false;
}
}
laminas-validator/src/Barcode/Code25interleaved.php 0000644 00000000561 15240152635 0016263 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Code25interleaved extends AbstractAdapter
{
/**
* Constructor
*
* Sets check flag to false.
*/
public function __construct()
{
$this->setLength('even');
$this->setCharacters('0123456789');
$this->setChecksum('code25');
$this->useChecksum(false);
}
}
laminas-validator/src/Barcode/Identcode.php 0000644 00000001173 15240152635 0014715 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Identcode extends AbstractAdapter
{
/**
* Allowed barcode lengths
*
* @var int
*/
protected $length = 12;
/**
* Allowed barcode characters
*
* @var string
*/
protected $characters = '0123456789';
/**
* Checksum function
*
* @var string
*/
protected $checksum = 'identcode';
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(12);
$this->setCharacters('0123456789');
$this->setChecksum('identcode');
}
}
laminas-validator/src/Barcode/Intelligentmail.php 0000644 00000000523 15240152635 0016136 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Intelligentmail extends AbstractAdapter
{
/**
* Constructor
*
* Sets check flag to false.
*/
public function __construct()
{
$this->setLength([20, 25, 29, 31]);
$this->setCharacters('0123456789');
$this->useChecksum(false);
}
}
laminas-validator/src/Barcode/Ean18.php 0000644 00000000455 15240152635 0013675 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Ean18 extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(18);
$this->setCharacters('0123456789');
$this->setChecksum('gtin');
}
}
laminas-validator/src/Barcode/Postnet.php 0000644 00000000476 15240152635 0014460 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Postnet extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength([6, 7, 10, 12]);
$this->setCharacters('0123456789');
$this->setChecksum('postnet');
}
}
laminas-validator/src/Barcode/Upce.php 0000644 00000001256 15240152635 0013715 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
use function strlen;
class Upce extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength([6, 7, 8]);
$this->setCharacters('0123456789');
$this->setChecksum('gtin');
}
/**
* Overrides parent checkLength
*
* @param string $value Value
* @return bool
*/
public function hasValidLength($value)
{
if (strlen($value) !== 8) {
$this->useChecksum(false);
} else {
$this->useChecksum(true);
}
return parent::hasValidLength($value);
}
}
laminas-validator/src/Barcode/Upca.php 0000644 00000000454 15240152635 0013710 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Upca extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(12);
$this->setCharacters('0123456789');
$this->setChecksum('gtin');
}
}
laminas-validator/src/Barcode/Ean8.php 0000644 00000001253 15240152635 0013611 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
use function strlen;
class Ean8 extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength([7, 8]);
$this->setCharacters('0123456789');
$this->setChecksum('gtin');
}
/**
* Overrides parent checkLength
*
* @param string $value Value
* @return bool
*/
public function hasValidLength($value)
{
if (strlen($value) === 7) {
$this->useChecksum(false);
} else {
$this->useChecksum(true);
}
return parent::hasValidLength($value);
}
}
laminas-validator/src/Barcode/Ean14.php 0000644 00000000455 15240152635 0013671 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Ean14 extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(14);
$this->setCharacters('0123456789');
$this->setChecksum('gtin');
}
}
laminas-validator/src/Barcode/Gtin13.php 0000644 00000000456 15240152635 0014067 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Gtin13 extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(13);
$this->setCharacters('0123456789');
$this->setChecksum('gtin');
}
}
laminas-validator/src/Barcode/Code25.php 0000644 00000000523 15240152635 0014036 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Code25 extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(-1);
$this->setCharacters('0123456789');
$this->setChecksum('code25');
$this->useChecksum(false);
}
}
laminas-validator/src/Barcode/Ean13.php 0000644 00000000455 15240152635 0013670 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Ean13 extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(13);
$this->setCharacters('0123456789');
$this->setChecksum('gtin');
}
}
laminas-validator/src/Barcode/Ean12.php 0000644 00000000455 15240152635 0013667 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Ean12 extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(12);
$this->setCharacters('0123456789');
$this->setChecksum('gtin');
}
}
laminas-validator/src/Barcode/Gtin12.php 0000644 00000000456 15240152635 0014066 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Gtin12 extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(12);
$this->setCharacters('0123456789');
$this->setChecksum('gtin');
}
}
laminas-validator/src/Barcode/Code39.php 0000644 00000003425 15240152635 0014047 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
use function str_split;
use function substr;
class Code39 extends AbstractAdapter
{
/** @var array */
protected $check = [
'0' => 0,
'1' => 1,
'2' => 2,
'3' => 3,
'4' => 4,
'5' => 5,
'6' => 6,
'7' => 7,
'8' => 8,
'9' => 9,
'A' => 10,
'B' => 11,
'C' => 12,
'D' => 13,
'E' => 14,
'F' => 15,
'G' => 16,
'H' => 17,
'I' => 18,
'J' => 19,
'K' => 20,
'L' => 21,
'M' => 22,
'N' => 23,
'O' => 24,
'P' => 25,
'Q' => 26,
'R' => 27,
'S' => 28,
'T' => 29,
'U' => 30,
'V' => 31,
'W' => 32,
'X' => 33,
'Y' => 34,
'Z' => 35,
'-' => 36,
'.' => 37,
' ' => 38,
'$' => 39,
'/' => 40,
'+' => 41,
'%' => 42,
];
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(-1);
$this->setCharacters('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ -.$/+%');
$this->setChecksum('code39');
$this->useChecksum(false);
}
/**
* Validates the checksum (Modulo 43)
*
* @param string $value The barcode to validate
* @return bool
*/
protected function code39($value)
{
$checksum = substr($value, -1, 1);
$value = str_split(substr($value, 0, -1));
$count = 0;
foreach ($value as $char) {
$count += $this->check[$char];
}
$mod = $count % 43;
if ($mod === $this->check[$checksum]) {
return true;
}
return false;
}
}
laminas-validator/src/Barcode/Ean2.php 0000644 00000000452 15240152635 0013603 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Ean2 extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(2);
$this->setCharacters('0123456789');
$this->useChecksum(false);
}
}
laminas-validator/src/Barcode/Royalmail.php 0000644 00000006343 15240152635 0014754 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
use function array_intersect;
use function array_keys;
use function current;
use function str_split;
use function strlen;
use function substr;
class Royalmail extends AbstractAdapter
{
/** @var array<string, int> */
protected $rows = [
'0' => 1,
'1' => 1,
'2' => 1,
'3' => 1,
'4' => 1,
'5' => 1,
'6' => 2,
'7' => 2,
'8' => 2,
'9' => 2,
'A' => 2,
'B' => 2,
'C' => 3,
'D' => 3,
'E' => 3,
'F' => 3,
'G' => 3,
'H' => 3,
'I' => 4,
'J' => 4,
'K' => 4,
'L' => 4,
'M' => 4,
'N' => 4,
'O' => 5,
'P' => 5,
'Q' => 5,
'R' => 5,
'S' => 5,
'T' => 5,
'U' => 0,
'V' => 0,
'W' => 0,
'X' => 0,
'Y' => 0,
'Z' => 0,
];
/** @var array<string, int> */
protected $columns = [
'0' => 1,
'1' => 2,
'2' => 3,
'3' => 4,
'4' => 5,
'5' => 0,
'6' => 1,
'7' => 2,
'8' => 3,
'9' => 4,
'A' => 5,
'B' => 0,
'C' => 1,
'D' => 2,
'E' => 3,
'F' => 4,
'G' => 5,
'H' => 0,
'I' => 1,
'J' => 2,
'K' => 3,
'L' => 4,
'M' => 5,
'N' => 0,
'O' => 1,
'P' => 2,
'Q' => 3,
'R' => 4,
'S' => 5,
'T' => 0,
'U' => 1,
'V' => 2,
'W' => 3,
'X' => 4,
'Y' => 5,
'Z' => 0,
];
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(-1);
$this->setCharacters('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ');
$this->setChecksum('royalmail');
}
/**
* Validates the checksum ()
*
* @param string $value The barcode to validate
* @return bool
*/
protected function royalmail($value)
{
$checksum = substr($value, -1, 1);
$values = str_split(substr($value, 0, -1));
$rowvalue = 0;
$colvalue = 0;
foreach ($values as $row) {
$rowvalue += $this->rows[$row];
$colvalue += $this->columns[$row];
}
$rowvalue %= 6;
$colvalue %= 6;
$rowchkvalue = array_keys($this->rows, $rowvalue);
$colchkvalue = array_keys($this->columns, $colvalue);
$intersect = array_intersect($rowchkvalue, $colchkvalue);
$chkvalue = (string) current($intersect);
if ($chkvalue === $checksum) {
return true;
}
return false;
}
/**
* Allows start and stop tag within checked chars
*
* @param string $value The barcode to check for allowed characters
* @return bool
*/
public function hasValidCharacters($value)
{
if ($value[0] === '(') {
$value = substr($value, 1);
if ($value[strlen($value) - 1] === ')') {
$value = substr($value, 0, -1);
} else {
return false;
}
}
return parent::hasValidCharacters($value);
}
}
laminas-validator/src/Barcode/Code93ext.php 0000644 00000000447 15240152635 0014571 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Code93ext extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(-1);
$this->setCharacters(128);
$this->useChecksum(false);
}
}
laminas-validator/src/Barcode/Planet.php 0000644 00000000467 15240152635 0014247 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Planet extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength([12, 14]);
$this->setCharacters('0123456789');
$this->setChecksum('postnet');
}
}
laminas-validator/src/Barcode/Code93.php 0000644 00000004743 15240152635 0014053 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
use function array_search;
use function count;
use function str_split;
use function substr;
class Code93 extends AbstractAdapter
{
/**
* Note that the characters !"§& are only synonyms
*
* @var array
*/
protected $check = [
'0' => 0,
'1' => 1,
'2' => 2,
'3' => 3,
'4' => 4,
'5' => 5,
'6' => 6,
'7' => 7,
'8' => 8,
'9' => 9,
'A' => 10,
'B' => 11,
'C' => 12,
'D' => 13,
'E' => 14,
'F' => 15,
'G' => 16,
'H' => 17,
'I' => 18,
'J' => 19,
'K' => 20,
'L' => 21,
'M' => 22,
'N' => 23,
'O' => 24,
'P' => 25,
'Q' => 26,
'R' => 27,
'S' => 28,
'T' => 29,
'U' => 30,
'V' => 31,
'W' => 32,
'X' => 33,
'Y' => 34,
'Z' => 35,
'-' => 36,
'.' => 37,
' ' => 38,
'$' => 39,
'/' => 40,
'+' => 41,
'%' => 42,
'!' => 43,
'"' => 44,
'§' => 45,
'&' => 46,
];
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(-1);
$this->setCharacters('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ -.$/+%');
$this->setChecksum('code93');
$this->useChecksum(false);
}
/**
* Validates the checksum (Modulo CK)
*
* @param string $value The barcode to validate
* @return bool
*/
protected function code93($value)
{
$checksum = substr($value, -2, 2);
$value = str_split(substr($value, 0, -2));
$count = 0;
$length = count($value) % 20;
foreach ($value as $char) {
if ($length === 0) {
$length = 20;
}
$count += $this->check[$char] * $length;
--$length;
}
$check = array_search($count % 47, $this->check);
$value[] = $check;
$count = 0;
$length = count($value) % 15;
foreach ($value as $char) {
if ($length === 0) {
$length = 15;
}
$count += $this->check[$char] * $length;
--$length;
}
$check .= array_search($count % 47, $this->check);
if ($check === $checksum) {
return true;
}
return false;
}
}
laminas-validator/src/Barcode/Leitcode.php 0000644 00000000465 15240152635 0014552 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Leitcode extends AbstractAdapter
{
/**
* Constructor for this barcode adapter
*/
public function __construct()
{
$this->setLength(14);
$this->setCharacters('0123456789');
$this->setChecksum('identcode');
}
}
laminas-validator/src/Barcode/Ean5.php 0000644 00000000471 15240152635 0013607 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
class Ean5 extends AbstractAdapter
{
/**
* Constructor
*
* Sets check flag to false.
*/
public function __construct()
{
$this->setLength(5);
$this->setCharacters('0123456789');
$this->useChecksum(false);
}
}
laminas-validator/src/Barcode/AbstractAdapter.php 0000644 00000016075 15240152635 0016072 0 ustar 00 <?php
namespace Laminas\Validator\Barcode;
use function chr;
use function is_array;
use function is_string;
use function method_exists;
use function str_replace;
use function str_split;
use function strlen;
use function substr;
abstract class AbstractAdapter implements AdapterInterface
{
/**
* Allowed options for this adapter
*
* @var array
*/
protected $options = [
'length' => null, // Allowed barcode lengths, integer, array, string
'characters' => null, // Allowed barcode characters
'checksum' => null, // Callback to checksum function
'useChecksum' => true, // Is a checksum value included?, boolean
];
/**
* Checks the length of a barcode
*
* @param string $value The barcode to check for proper length
* @return bool
*/
public function hasValidLength($value)
{
if (! is_string($value)) {
return false;
}
$fixum = strlen($value);
$length = $this->getLength();
if (is_array($length)) {
foreach ($length as $value) {
if ($fixum === $value) {
return true;
}
if ($value === -1) {
return true;
}
}
return false;
}
if ($fixum === $length) {
return true;
}
if ($length === -1) {
return true;
}
if ($length === 'even') {
$count = $fixum % 2;
return 0 === $count;
}
if ($length === 'odd') {
$count = $fixum % 2;
return 1 === $count;
}
return false;
}
/**
* Checks for allowed characters within the barcode
*
* @param string $value The barcode to check for allowed characters
* @return bool
*/
public function hasValidCharacters($value)
{
if (! is_string($value)) {
return false;
}
$characters = $this->getCharacters();
if ($characters === 128) {
for ($x = 0; $x < 128; ++$x) {
$value = str_replace(chr($x), '', $value);
}
} else {
$chars = str_split($characters);
foreach ($chars as $char) {
$value = str_replace($char, '', $value);
}
}
if (strlen($value) > 0) {
return false;
}
return true;
}
/**
* Validates the checksum
*
* @param string $value The barcode to check the checksum for
* @return bool
*/
public function hasValidChecksum($value)
{
$checksum = $this->getChecksum();
if (! empty($checksum)) {
if (method_exists($this, $checksum)) {
return $this->$checksum($value);
}
}
return false;
}
/**
* Returns the allowed barcode length
*
* @return int|array
*/
public function getLength()
{
return $this->options['length'];
}
/**
* Returns the allowed characters
*
* @return int|string|array
*/
public function getCharacters()
{
return $this->options['characters'];
}
/**
* Returns the checksum function name
*
* @return string
*/
public function getChecksum()
{
return $this->options['checksum'];
}
/**
* Sets the checksum validation method
*
* @param callable $checksum Checksum method to call
* @return $this
*/
protected function setChecksum($checksum)
{
$this->options['checksum'] = $checksum;
return $this;
}
/**
* Sets the checksum validation, if no value is given, the actual setting is returned
*
* @param bool $check
* @return AbstractAdapter|bool
*/
public function useChecksum($check = null)
{
if ($check === null) {
return $this->options['useChecksum'];
}
$this->options['useChecksum'] = (bool) $check;
return $this;
}
/**
* Sets the length of this barcode
*
* @param int|array $length
* @return $this
*/
protected function setLength($length)
{
$this->options['length'] = $length;
return $this;
}
/**
* Sets the allowed characters of this barcode
*
* @param int $characters
* @return $this
*/
protected function setCharacters($characters)
{
$this->options['characters'] = $characters;
return $this;
}
/**
* Validates the checksum (Modulo 10)
* GTIN implementation factor 3
*
* @param string $value The barcode to validate
* @return bool
*/
protected function gtin($value)
{
$barcode = substr($value, 0, -1);
$sum = 0;
$length = strlen($barcode) - 1;
for ($i = 0; $i <= $length; $i++) {
if (($i % 2) === 0) {
$sum += $barcode[$length - $i] * 3;
} else {
$sum += $barcode[$length - $i];
}
}
$calc = $sum % 10;
$checksum = $calc === 0 ? 0 : 10 - $calc;
return $value[$length + 1] === (string) $checksum;
}
/**
* Validates the checksum (Modulo 10)
* IDENTCODE implementation factors 9 and 4
*
* @param string $value The barcode to validate
* @return bool
*/
protected function identcode($value)
{
$barcode = substr($value, 0, -1);
$sum = 0;
$length = strlen($value) - 2;
for ($i = 0; $i <= $length; $i++) {
if (($i % 2) === 0) {
$sum += $barcode[$length - $i] * 4;
} else {
$sum += $barcode[$length - $i] * 9;
}
}
$calc = $sum % 10;
$checksum = $calc === 0 ? 0 : 10 - $calc;
return $value[$length + 1] === (string) $checksum;
}
/**
* Validates the checksum (Modulo 10)
* CODE25 implementation factor 3
*
* @param string $value The barcode to validate
* @return bool
*/
protected function code25($value)
{
$barcode = substr($value, 0, -1);
$sum = 0;
$length = strlen($barcode) - 1;
for ($i = 0; $i <= $length; $i++) {
if (($i % 2) === 0) {
$sum += $barcode[$i] * 3;
} else {
$sum += $barcode[$i];
}
}
$calc = $sum % 10;
$checksum = $calc === 0 ? 0 : 10 - $calc;
return $value[$length + 1] === (string) $checksum;
}
/**
* Validates the checksum ()
* POSTNET implementation
*
* @param string $value The barcode to validate
* @return bool
*/
protected function postnet($value)
{
$checksum = substr($value, -1, 1);
$values = str_split(substr($value, 0, -1));
$check = 0;
foreach ($values as $row) {
$check += $row;
}
$check %= 10;
$check = 10 - $check;
return (string) $check === $checksum;
}
}
laminas-validator/src/ConfigProvider.php 0000644 00000001522 15240152635 0014376 0 ustar 00 <?php
namespace Laminas\Validator;
class ConfigProvider
{
/**
* Return configuration for this component.
*
* @return array
*/
public function __invoke()
{
return [
'dependencies' => $this->getDependencyConfig(),
];
}
/**
* Return dependency mappings for this component.
*
* @return array
*/
public function getDependencyConfig()
{
return [
'aliases' => [
'ValidatorManager' => ValidatorPluginManager::class,
// Legacy Zend Framework aliases
'Zend\Validator\ValidatorPluginManager' => ValidatorPluginManager::class,
],
'factories' => [
ValidatorPluginManager::class => ValidatorPluginManagerFactory::class,
],
];
}
}
laminas-validator/src/Hostname/Jp.php 0000644 00000170507 15240152635 0013617 0 ustar 00 <?php // phpcs:disable PSR12.Files.FileHeader.IncorrectOrder
namespace Laminas\Validator\Hostname;
/**
* Resource file for japanese idn validation
*/
return [
1 => '/^[\x{002d}0-9a-z\x{3005}-\x{3007}\x{3041}-\x{3093}\x{309D}\x{309E}'
. '\x{30A1}-\x{30F6}\x{30FC}'
. '\x{30FD}\x{30FE}\x{4E00}\x{4E01}\x{4E03}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}'
. '\x{4E0B}\x{4E0D}\x{4E0E}\x{4E10}\x{4E11}\x{4E14}\x{4E15}\x{4E16}\x{4E17}'
. '\x{4E18}\x{4E19}\x{4E1E}\x{4E21}\x{4E26}\x{4E2A}\x{4E2D}\x{4E31}\x{4E32}'
. '\x{4E36}\x{4E38}\x{4E39}\x{4E3B}\x{4E3C}\x{4E3F}\x{4E42}\x{4E43}\x{4E45}'
. '\x{4E4B}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E55}\x{4E56}\x{4E57}\x{4E58}\x{4E59}'
. '\x{4E5D}\x{4E5E}\x{4E5F}\x{4E62}\x{4E71}\x{4E73}\x{4E7E}\x{4E80}\x{4E82}'
. '\x{4E85}\x{4E86}\x{4E88}\x{4E89}\x{4E8A}\x{4E8B}\x{4E8C}\x{4E8E}\x{4E91}'
. '\x{4E92}\x{4E94}\x{4E95}\x{4E98}\x{4E99}\x{4E9B}\x{4E9C}\x{4E9E}\x{4E9F}'
. '\x{4EA0}\x{4EA1}\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA8}\x{4EAB}\x{4EAC}'
. '\x{4EAD}\x{4EAE}\x{4EB0}\x{4EB3}\x{4EB6}\x{4EBA}\x{4EC0}\x{4EC1}\x{4EC2}'
. '\x{4EC4}\x{4EC6}\x{4EC7}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED4}'
. '\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE3}'
. '\x{4EE4}\x{4EE5}\x{4EED}\x{4EEE}\x{4EF0}\x{4EF2}\x{4EF6}\x{4EF7}\x{4EFB}'
. '\x{4F01}\x{4F09}\x{4F0A}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}\x{4F11}\x{4F1A}'
. '\x{4F1C}\x{4F1D}\x{4F2F}\x{4F30}\x{4F34}\x{4F36}\x{4F38}\x{4F3A}\x{4F3C}'
. '\x{4F3D}\x{4F43}\x{4F46}\x{4F47}\x{4F4D}\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}'
. '\x{4F53}\x{4F55}\x{4F57}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}'
. '\x{4F69}\x{4F6F}\x{4F70}\x{4F73}\x{4F75}\x{4F76}\x{4F7B}\x{4F7C}\x{4F7F}'
. '\x{4F83}\x{4F86}\x{4F88}\x{4F8B}\x{4F8D}\x{4F8F}\x{4F91}\x{4F96}\x{4F98}'
. '\x{4F9B}\x{4F9D}\x{4FA0}\x{4FA1}\x{4FAB}\x{4FAD}\x{4FAE}\x{4FAF}\x{4FB5}'
. '\x{4FB6}\x{4FBF}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FCA}\x{4FCE}\x{4FD0}\x{4FD1}'
. '\x{4FD4}\x{4FD7}\x{4FD8}\x{4FDA}\x{4FDB}\x{4FDD}\x{4FDF}\x{4FE1}\x{4FE3}'
. '\x{4FE4}\x{4FE5}\x{4FEE}\x{4FEF}\x{4FF3}\x{4FF5}\x{4FF6}\x{4FF8}\x{4FFA}'
. '\x{4FFE}\x{5005}\x{5006}\x{5009}\x{500B}\x{500D}\x{500F}\x{5011}\x{5012}'
. '\x{5014}\x{5016}\x{5019}\x{501A}\x{501F}\x{5021}\x{5023}\x{5024}\x{5025}'
. '\x{5026}\x{5028}\x{5029}\x{502A}\x{502B}\x{502C}\x{502D}\x{5036}\x{5039}'
. '\x{5043}\x{5047}\x{5048}\x{5049}\x{504F}\x{5050}\x{5055}\x{5056}\x{505A}'
. '\x{505C}\x{5065}\x{506C}\x{5072}\x{5074}\x{5075}\x{5076}\x{5078}\x{507D}'
. '\x{5080}\x{5085}\x{508D}\x{5091}\x{5098}\x{5099}\x{509A}\x{50AC}\x{50AD}'
. '\x{50B2}\x{50B3}\x{50B4}\x{50B5}\x{50B7}\x{50BE}\x{50C2}\x{50C5}\x{50C9}'
. '\x{50CA}\x{50CD}\x{50CF}\x{50D1}\x{50D5}\x{50D6}\x{50DA}\x{50DE}\x{50E3}'
. '\x{50E5}\x{50E7}\x{50ED}\x{50EE}\x{50F5}\x{50F9}\x{50FB}\x{5100}\x{5101}'
. '\x{5102}\x{5104}\x{5109}\x{5112}\x{5114}\x{5115}\x{5116}\x{5118}\x{511A}'
. '\x{511F}\x{5121}\x{512A}\x{5132}\x{5137}\x{513A}\x{513B}\x{513C}\x{513F}'
. '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}'
. '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5152}\x{5154}\x{515A}\x{515C}'
. '\x{5162}\x{5165}\x{5168}\x{5169}\x{516A}\x{516B}\x{516C}\x{516D}\x{516E}'
. '\x{5171}\x{5175}\x{5176}\x{5177}\x{5178}\x{517C}\x{5180}\x{5182}\x{5185}'
. '\x{5186}\x{5189}\x{518A}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}'
. '\x{5193}\x{5195}\x{5196}\x{5197}\x{5199}\x{51A0}\x{51A2}\x{51A4}\x{51A5}'
. '\x{51A6}\x{51A8}\x{51A9}\x{51AA}\x{51AB}\x{51AC}\x{51B0}\x{51B1}\x{51B2}'
. '\x{51B3}\x{51B4}\x{51B5}\x{51B6}\x{51B7}\x{51BD}\x{51C4}\x{51C5}\x{51C6}'
. '\x{51C9}\x{51CB}\x{51CC}\x{51CD}\x{51D6}\x{51DB}\x{51DC}\x{51DD}\x{51E0}'
. '\x{51E1}\x{51E6}\x{51E7}\x{51E9}\x{51EA}\x{51ED}\x{51F0}\x{51F1}\x{51F5}'
. '\x{51F6}\x{51F8}\x{51F9}\x{51FA}\x{51FD}\x{51FE}\x{5200}\x{5203}\x{5204}'
. '\x{5206}\x{5207}\x{5208}\x{520A}\x{520B}\x{520E}\x{5211}\x{5214}\x{5217}'
. '\x{521D}\x{5224}\x{5225}\x{5227}\x{5229}\x{522A}\x{522E}\x{5230}\x{5233}'
. '\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{5243}\x{5244}\x{5247}'
. '\x{524A}\x{524B}\x{524C}\x{524D}\x{524F}\x{5254}\x{5256}\x{525B}\x{525E}'
. '\x{5263}\x{5264}\x{5265}\x{5269}\x{526A}\x{526F}\x{5270}\x{5271}\x{5272}'
. '\x{5273}\x{5274}\x{5275}\x{527D}\x{527F}\x{5283}\x{5287}\x{5288}\x{5289}'
. '\x{528D}\x{5291}\x{5292}\x{5294}\x{529B}\x{529F}\x{52A0}\x{52A3}\x{52A9}'
. '\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52B1}\x{52B4}\x{52B5}\x{52B9}\x{52BC}'
. '\x{52BE}\x{52C1}\x{52C3}\x{52C5}\x{52C7}\x{52C9}\x{52CD}\x{52D2}\x{52D5}'
. '\x{52D7}\x{52D8}\x{52D9}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}'
. '\x{52E4}\x{52E6}\x{52E7}\x{52F2}\x{52F3}\x{52F5}\x{52F8}\x{52F9}\x{52FA}'
. '\x{52FE}\x{52FF}\x{5301}\x{5302}\x{5305}\x{5306}\x{5308}\x{530D}\x{530F}'
. '\x{5310}\x{5315}\x{5316}\x{5317}\x{5319}\x{531A}\x{531D}\x{5320}\x{5321}'
. '\x{5323}\x{532A}\x{532F}\x{5331}\x{5333}\x{5338}\x{5339}\x{533A}\x{533B}'
. '\x{533F}\x{5340}\x{5341}\x{5343}\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}'
. '\x{534A}\x{534D}\x{5351}\x{5352}\x{5353}\x{5354}\x{5357}\x{5358}\x{535A}'
. '\x{535C}\x{535E}\x{5360}\x{5366}\x{5369}\x{536E}\x{536F}\x{5370}\x{5371}'
. '\x{5373}\x{5374}\x{5375}\x{5377}\x{5378}\x{537B}\x{537F}\x{5382}\x{5384}'
. '\x{5396}\x{5398}\x{539A}\x{539F}\x{53A0}\x{53A5}\x{53A6}\x{53A8}\x{53A9}'
. '\x{53AD}\x{53AE}\x{53B0}\x{53B3}\x{53B6}\x{53BB}\x{53C2}\x{53C3}\x{53C8}'
. '\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}\x{53D4}\x{53D6}\x{53D7}'
. '\x{53D9}\x{53DB}\x{53DF}\x{53E1}\x{53E2}\x{53E3}\x{53E4}\x{53E5}\x{53E8}'
. '\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}\x{53EF}\x{53F0}\x{53F1}'
. '\x{53F2}\x{53F3}\x{53F6}\x{53F7}\x{53F8}\x{53FA}\x{5401}\x{5403}\x{5404}'
. '\x{5408}\x{5409}\x{540A}\x{540B}\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}'
. '\x{5411}\x{541B}\x{541D}\x{541F}\x{5420}\x{5426}\x{5429}\x{542B}\x{542C}'
. '\x{542D}\x{542E}\x{5436}\x{5438}\x{5439}\x{543B}\x{543C}\x{543D}\x{543E}'
. '\x{5440}\x{5442}\x{5446}\x{5448}\x{5449}\x{544A}\x{544E}\x{5451}\x{545F}'
. '\x{5468}\x{546A}\x{5470}\x{5471}\x{5473}\x{5475}\x{5476}\x{5477}\x{547B}'
. '\x{547C}\x{547D}\x{5480}\x{5484}\x{5486}\x{548B}\x{548C}\x{548E}\x{548F}'
. '\x{5490}\x{5492}\x{54A2}\x{54A4}\x{54A5}\x{54A8}\x{54AB}\x{54AC}\x{54AF}'
. '\x{54B2}\x{54B3}\x{54B8}\x{54BC}\x{54BD}\x{54BE}\x{54C0}\x{54C1}\x{54C2}'
. '\x{54C4}\x{54C7}\x{54C8}\x{54C9}\x{54D8}\x{54E1}\x{54E2}\x{54E5}\x{54E6}'
. '\x{54E8}\x{54E9}\x{54ED}\x{54EE}\x{54F2}\x{54FA}\x{54FD}\x{5504}\x{5506}'
. '\x{5507}\x{550F}\x{5510}\x{5514}\x{5516}\x{552E}\x{552F}\x{5531}\x{5533}'
. '\x{5538}\x{5539}\x{553E}\x{5540}\x{5544}\x{5545}\x{5546}\x{554C}\x{554F}'
. '\x{5553}\x{5556}\x{5557}\x{555C}\x{555D}\x{5563}\x{557B}\x{557C}\x{557E}'
. '\x{5580}\x{5583}\x{5584}\x{5587}\x{5589}\x{558A}\x{558B}\x{5598}\x{5599}'
. '\x{559A}\x{559C}\x{559D}\x{559E}\x{559F}\x{55A7}\x{55A8}\x{55A9}\x{55AA}'
. '\x{55AB}\x{55AC}\x{55AE}\x{55B0}\x{55B6}\x{55C4}\x{55C5}\x{55C7}\x{55D4}'
. '\x{55DA}\x{55DC}\x{55DF}\x{55E3}\x{55E4}\x{55F7}\x{55F9}\x{55FD}\x{55FE}'
. '\x{5606}\x{5609}\x{5614}\x{5616}\x{5617}\x{5618}\x{561B}\x{5629}\x{562F}'
. '\x{5631}\x{5632}\x{5634}\x{5636}\x{5638}\x{5642}\x{564C}\x{564E}\x{5650}'
. '\x{565B}\x{5664}\x{5668}\x{566A}\x{566B}\x{566C}\x{5674}\x{5678}\x{567A}'
. '\x{5680}\x{5686}\x{5687}\x{568A}\x{568F}\x{5694}\x{56A0}\x{56A2}\x{56A5}'
. '\x{56AE}\x{56B4}\x{56B6}\x{56BC}\x{56C0}\x{56C1}\x{56C2}\x{56C3}\x{56C8}'
. '\x{56CE}\x{56D1}\x{56D3}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DE}\x{56E0}'
. '\x{56E3}\x{56EE}\x{56F0}\x{56F2}\x{56F3}\x{56F9}\x{56FA}\x{56FD}\x{56FF}'
. '\x{5700}\x{5703}\x{5704}\x{5708}\x{5709}\x{570B}\x{570D}\x{570F}\x{5712}'
. '\x{5713}\x{5716}\x{5718}\x{571C}\x{571F}\x{5726}\x{5727}\x{5728}\x{572D}'
. '\x{5730}\x{5737}\x{5738}\x{573B}\x{5740}\x{5742}\x{5747}\x{574A}\x{574E}'
. '\x{574F}\x{5750}\x{5751}\x{5761}\x{5764}\x{5766}\x{5769}\x{576A}\x{577F}'
. '\x{5782}\x{5788}\x{5789}\x{578B}\x{5793}\x{57A0}\x{57A2}\x{57A3}\x{57A4}'
. '\x{57AA}\x{57B0}\x{57B3}\x{57C0}\x{57C3}\x{57C6}\x{57CB}\x{57CE}\x{57D2}'
. '\x{57D3}\x{57D4}\x{57D6}\x{57DC}\x{57DF}\x{57E0}\x{57E3}\x{57F4}\x{57F7}'
. '\x{57F9}\x{57FA}\x{57FC}\x{5800}\x{5802}\x{5805}\x{5806}\x{580A}\x{580B}'
. '\x{5815}\x{5819}\x{581D}\x{5821}\x{5824}\x{582A}\x{582F}\x{5830}\x{5831}'
. '\x{5834}\x{5835}\x{583A}\x{583D}\x{5840}\x{5841}\x{584A}\x{584B}\x{5851}'
. '\x{5852}\x{5854}\x{5857}\x{5858}\x{5859}\x{585A}\x{585E}\x{5862}\x{5869}'
. '\x{586B}\x{5870}\x{5872}\x{5875}\x{5879}\x{587E}\x{5883}\x{5885}\x{5893}'
. '\x{5897}\x{589C}\x{589F}\x{58A8}\x{58AB}\x{58AE}\x{58B3}\x{58B8}\x{58B9}'
. '\x{58BA}\x{58BB}\x{58BE}\x{58C1}\x{58C5}\x{58C7}\x{58CA}\x{58CC}\x{58D1}'
. '\x{58D3}\x{58D5}\x{58D7}\x{58D8}\x{58D9}\x{58DC}\x{58DE}\x{58DF}\x{58E4}'
. '\x{58E5}\x{58EB}\x{58EC}\x{58EE}\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F7}'
. '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{5902}\x{5909}\x{590A}\x{590F}'
. '\x{5910}\x{5915}\x{5916}\x{5918}\x{5919}\x{591A}\x{591B}\x{591C}\x{5922}'
. '\x{5925}\x{5927}\x{5929}\x{592A}\x{592B}\x{592C}\x{592D}\x{592E}\x{5931}'
. '\x{5932}\x{5937}\x{5938}\x{593E}\x{5944}\x{5947}\x{5948}\x{5949}\x{594E}'
. '\x{594F}\x{5950}\x{5951}\x{5954}\x{5955}\x{5957}\x{5958}\x{595A}\x{5960}'
. '\x{5962}\x{5965}\x{5967}\x{5968}\x{5969}\x{596A}\x{596C}\x{596E}\x{5973}'
. '\x{5974}\x{5978}\x{597D}\x{5981}\x{5982}\x{5983}\x{5984}\x{598A}\x{598D}'
. '\x{5993}\x{5996}\x{5999}\x{599B}\x{599D}\x{59A3}\x{59A5}\x{59A8}\x{59AC}'
. '\x{59B2}\x{59B9}\x{59BB}\x{59BE}\x{59C6}\x{59C9}\x{59CB}\x{59D0}\x{59D1}'
. '\x{59D3}\x{59D4}\x{59D9}\x{59DA}\x{59DC}\x{59E5}\x{59E6}\x{59E8}\x{59EA}'
. '\x{59EB}\x{59F6}\x{59FB}\x{59FF}\x{5A01}\x{5A03}\x{5A09}\x{5A11}\x{5A18}'
. '\x{5A1A}\x{5A1C}\x{5A1F}\x{5A20}\x{5A25}\x{5A29}\x{5A2F}\x{5A35}\x{5A36}'
. '\x{5A3C}\x{5A40}\x{5A41}\x{5A46}\x{5A49}\x{5A5A}\x{5A62}\x{5A66}\x{5A6A}'
. '\x{5A6C}\x{5A7F}\x{5A92}\x{5A9A}\x{5A9B}\x{5ABC}\x{5ABD}\x{5ABE}\x{5AC1}'
. '\x{5AC2}\x{5AC9}\x{5ACB}\x{5ACC}\x{5AD0}\x{5AD6}\x{5AD7}\x{5AE1}\x{5AE3}'
. '\x{5AE6}\x{5AE9}\x{5AFA}\x{5AFB}\x{5B09}\x{5B0B}\x{5B0C}\x{5B16}\x{5B22}'
. '\x{5B2A}\x{5B2C}\x{5B30}\x{5B32}\x{5B36}\x{5B3E}\x{5B40}\x{5B43}\x{5B45}'
. '\x{5B50}\x{5B51}\x{5B54}\x{5B55}\x{5B57}\x{5B58}\x{5B5A}\x{5B5B}\x{5B5C}'
. '\x{5B5D}\x{5B5F}\x{5B63}\x{5B64}\x{5B65}\x{5B66}\x{5B69}\x{5B6B}\x{5B70}'
. '\x{5B71}\x{5B73}\x{5B75}\x{5B78}\x{5B7A}\x{5B80}\x{5B83}\x{5B85}\x{5B87}'
. '\x{5B88}\x{5B89}\x{5B8B}\x{5B8C}\x{5B8D}\x{5B8F}\x{5B95}\x{5B97}\x{5B98}'
. '\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9F}\x{5BA2}\x{5BA3}\x{5BA4}'
. '\x{5BA5}\x{5BA6}\x{5BAE}\x{5BB0}\x{5BB3}\x{5BB4}\x{5BB5}\x{5BB6}\x{5BB8}'
. '\x{5BB9}\x{5BBF}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BC9}'
. '\x{5BCC}\x{5BD0}\x{5BD2}\x{5BD3}\x{5BD4}\x{5BDB}\x{5BDD}\x{5BDE}\x{5BDF}'
. '\x{5BE1}\x{5BE2}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}\x{5BE8}\x{5BE9}\x{5BEB}'
. '\x{5BEE}\x{5BF0}\x{5BF3}\x{5BF5}\x{5BF6}\x{5BF8}\x{5BFA}\x{5BFE}\x{5BFF}'
. '\x{5C01}\x{5C02}\x{5C04}\x{5C05}\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}'
. '\x{5C0B}\x{5C0D}\x{5C0E}\x{5C0F}\x{5C11}\x{5C13}\x{5C16}\x{5C1A}\x{5C20}'
. '\x{5C22}\x{5C24}\x{5C28}\x{5C2D}\x{5C31}\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}'
. '\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}\x{5C41}\x{5C45}\x{5C46}\x{5C48}'
. '\x{5C4A}\x{5C4B}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C53}\x{5C55}'
. '\x{5C5E}\x{5C60}\x{5C61}\x{5C64}\x{5C65}\x{5C6C}\x{5C6E}\x{5C6F}\x{5C71}'
. '\x{5C76}\x{5C79}\x{5C8C}\x{5C90}\x{5C91}\x{5C94}\x{5CA1}\x{5CA8}\x{5CA9}'
. '\x{5CAB}\x{5CAC}\x{5CB1}\x{5CB3}\x{5CB6}\x{5CB7}\x{5CB8}\x{5CBB}\x{5CBC}'
. '\x{5CBE}\x{5CC5}\x{5CC7}\x{5CD9}\x{5CE0}\x{5CE1}\x{5CE8}\x{5CE9}\x{5CEA}'
. '\x{5CED}\x{5CEF}\x{5CF0}\x{5CF6}\x{5CFA}\x{5CFB}\x{5CFD}\x{5D07}\x{5D0B}'
. '\x{5D0E}\x{5D11}\x{5D14}\x{5D15}\x{5D16}\x{5D17}\x{5D18}\x{5D19}\x{5D1A}'
. '\x{5D1B}\x{5D1F}\x{5D22}\x{5D29}\x{5D4B}\x{5D4C}\x{5D4E}\x{5D50}\x{5D52}'
. '\x{5D5C}\x{5D69}\x{5D6C}\x{5D6F}\x{5D73}\x{5D76}\x{5D82}\x{5D84}\x{5D87}'
. '\x{5D8B}\x{5D8C}\x{5D90}\x{5D9D}\x{5DA2}\x{5DAC}\x{5DAE}\x{5DB7}\x{5DBA}'
. '\x{5DBC}\x{5DBD}\x{5DC9}\x{5DCC}\x{5DCD}\x{5DD2}\x{5DD3}\x{5DD6}\x{5DDB}'
. '\x{5DDD}\x{5DDE}\x{5DE1}\x{5DE3}\x{5DE5}\x{5DE6}\x{5DE7}\x{5DE8}\x{5DEB}'
. '\x{5DEE}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DFB}\x{5DFD}'
. '\x{5DFE}\x{5E02}\x{5E03}\x{5E06}\x{5E0B}\x{5E0C}\x{5E11}\x{5E16}\x{5E19}'
. '\x{5E1A}\x{5E1B}\x{5E1D}\x{5E25}\x{5E2B}\x{5E2D}\x{5E2F}\x{5E30}\x{5E33}'
. '\x{5E36}\x{5E37}\x{5E38}\x{5E3D}\x{5E40}\x{5E43}\x{5E44}\x{5E45}\x{5E47}'
. '\x{5E4C}\x{5E4E}\x{5E54}\x{5E55}\x{5E57}\x{5E5F}\x{5E61}\x{5E62}\x{5E63}'
. '\x{5E64}\x{5E72}\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E78}\x{5E79}\x{5E7A}'
. '\x{5E7B}\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E81}\x{5E83}\x{5E84}\x{5E87}'
. '\x{5E8A}\x{5E8F}\x{5E95}\x{5E96}\x{5E97}\x{5E9A}\x{5E9C}\x{5EA0}\x{5EA6}'
. '\x{5EA7}\x{5EAB}\x{5EAD}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EC1}\x{5EC2}'
. '\x{5EC3}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECF}\x{5ED0}\x{5ED3}\x{5ED6}\x{5EDA}'
. '\x{5EDB}\x{5EDD}\x{5EDF}\x{5EE0}\x{5EE1}\x{5EE2}\x{5EE3}\x{5EE8}\x{5EE9}'
. '\x{5EEC}\x{5EF0}\x{5EF1}\x{5EF3}\x{5EF4}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}'
. '\x{5EFB}\x{5EFC}\x{5EFE}\x{5EFF}\x{5F01}\x{5F03}\x{5F04}\x{5F09}\x{5F0A}'
. '\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F10}\x{5F11}\x{5F13}\x{5F14}\x{5F15}'
. '\x{5F16}\x{5F17}\x{5F18}\x{5F1B}\x{5F1F}\x{5F25}\x{5F26}\x{5F27}\x{5F29}'
. '\x{5F2D}\x{5F2F}\x{5F31}\x{5F35}\x{5F37}\x{5F38}\x{5F3C}\x{5F3E}\x{5F41}'
. '\x{5F48}\x{5F4A}\x{5F4C}\x{5F4E}\x{5F51}\x{5F53}\x{5F56}\x{5F57}\x{5F59}'
. '\x{5F5C}\x{5F5D}\x{5F61}\x{5F62}\x{5F66}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}'
. '\x{5F6D}\x{5F70}\x{5F71}\x{5F73}\x{5F77}\x{5F79}\x{5F7C}\x{5F7F}\x{5F80}'
. '\x{5F81}\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F87}\x{5F88}\x{5F8A}\x{5F8B}'
. '\x{5F8C}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F97}\x{5F98}\x{5F99}\x{5F9E}'
. '\x{5FA0}\x{5FA1}\x{5FA8}\x{5FA9}\x{5FAA}\x{5FAD}\x{5FAE}\x{5FB3}\x{5FB4}'
. '\x{5FB9}\x{5FBC}\x{5FBD}\x{5FC3}\x{5FC5}\x{5FCC}\x{5FCD}\x{5FD6}\x{5FD7}'
. '\x{5FD8}\x{5FD9}\x{5FDC}\x{5FDD}\x{5FE0}\x{5FE4}\x{5FEB}\x{5FF0}\x{5FF1}'
. '\x{5FF5}\x{5FF8}\x{5FFB}\x{5FFD}\x{5FFF}\x{600E}\x{600F}\x{6010}\x{6012}'
. '\x{6015}\x{6016}\x{6019}\x{601B}\x{601C}\x{601D}\x{6020}\x{6021}\x{6025}'
. '\x{6026}\x{6027}\x{6028}\x{6029}\x{602A}\x{602B}\x{602F}\x{6031}\x{603A}'
. '\x{6041}\x{6042}\x{6043}\x{6046}\x{604A}\x{604B}\x{604D}\x{6050}\x{6052}'
. '\x{6055}\x{6059}\x{605A}\x{605F}\x{6060}\x{6062}\x{6063}\x{6064}\x{6065}'
. '\x{6068}\x{6069}\x{606A}\x{606B}\x{606C}\x{606D}\x{606F}\x{6070}\x{6075}'
. '\x{6077}\x{6081}\x{6083}\x{6084}\x{6089}\x{608B}\x{608C}\x{608D}\x{6092}'
. '\x{6094}\x{6096}\x{6097}\x{609A}\x{609B}\x{609F}\x{60A0}\x{60A3}\x{60A6}'
. '\x{60A7}\x{60A9}\x{60AA}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B8}'
. '\x{60BC}\x{60BD}\x{60C5}\x{60C6}\x{60C7}\x{60D1}\x{60D3}\x{60D8}\x{60DA}'
. '\x{60DC}\x{60DF}\x{60E0}\x{60E1}\x{60E3}\x{60E7}\x{60E8}\x{60F0}\x{60F1}'
. '\x{60F3}\x{60F4}\x{60F6}\x{60F7}\x{60F9}\x{60FA}\x{60FB}\x{6100}\x{6101}'
. '\x{6103}\x{6106}\x{6108}\x{6109}\x{610D}\x{610E}\x{610F}\x{6115}\x{611A}'
. '\x{611B}\x{611F}\x{6121}\x{6127}\x{6128}\x{612C}\x{6134}\x{613C}\x{613D}'
. '\x{613E}\x{613F}\x{6142}\x{6144}\x{6147}\x{6148}\x{614A}\x{614B}\x{614C}'
. '\x{614D}\x{614E}\x{6153}\x{6155}\x{6158}\x{6159}\x{615A}\x{615D}\x{615F}'
. '\x{6162}\x{6163}\x{6165}\x{6167}\x{6168}\x{616B}\x{616E}\x{616F}\x{6170}'
. '\x{6171}\x{6173}\x{6174}\x{6175}\x{6176}\x{6177}\x{617E}\x{6182}\x{6187}'
. '\x{618A}\x{618E}\x{6190}\x{6191}\x{6194}\x{6196}\x{6199}\x{619A}\x{61A4}'
. '\x{61A7}\x{61A9}\x{61AB}\x{61AC}\x{61AE}\x{61B2}\x{61B6}\x{61BA}\x{61BE}'
. '\x{61C3}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}'
. '\x{61D0}\x{61E3}\x{61E6}\x{61F2}\x{61F4}\x{61F6}\x{61F7}\x{61F8}\x{61FA}'
. '\x{61FC}\x{61FD}\x{61FE}\x{61FF}\x{6200}\x{6208}\x{6209}\x{620A}\x{620C}'
. '\x{620D}\x{620E}\x{6210}\x{6211}\x{6212}\x{6214}\x{6216}\x{621A}\x{621B}'
. '\x{621D}\x{621E}\x{621F}\x{6221}\x{6226}\x{622A}\x{622E}\x{622F}\x{6230}'
. '\x{6232}\x{6233}\x{6234}\x{6238}\x{623B}\x{623F}\x{6240}\x{6241}\x{6247}'
. '\x{6248}\x{6249}\x{624B}\x{624D}\x{624E}\x{6253}\x{6255}\x{6258}\x{625B}'
. '\x{625E}\x{6260}\x{6263}\x{6268}\x{626E}\x{6271}\x{6276}\x{6279}\x{627C}'
. '\x{627E}\x{627F}\x{6280}\x{6282}\x{6283}\x{6284}\x{6289}\x{628A}\x{6291}'
. '\x{6292}\x{6293}\x{6294}\x{6295}\x{6296}\x{6297}\x{6298}\x{629B}\x{629C}'
. '\x{629E}\x{62AB}\x{62AC}\x{62B1}\x{62B5}\x{62B9}\x{62BB}\x{62BC}\x{62BD}'
. '\x{62C2}\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CC}\x{62CD}'
. '\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D7}\x{62D8}\x{62D9}'
. '\x{62DB}\x{62DC}\x{62DD}\x{62E0}\x{62E1}\x{62EC}\x{62ED}\x{62EE}\x{62EF}'
. '\x{62F1}\x{62F3}\x{62F5}\x{62F6}\x{62F7}\x{62FE}\x{62FF}\x{6301}\x{6302}'
. '\x{6307}\x{6308}\x{6309}\x{630C}\x{6311}\x{6319}\x{631F}\x{6327}\x{6328}'
. '\x{632B}\x{632F}\x{633A}\x{633D}\x{633E}\x{633F}\x{6349}\x{634C}\x{634D}'
. '\x{634F}\x{6350}\x{6355}\x{6357}\x{635C}\x{6367}\x{6368}\x{6369}\x{636B}'
. '\x{636E}\x{6372}\x{6376}\x{6377}\x{637A}\x{637B}\x{6380}\x{6383}\x{6388}'
. '\x{6389}\x{638C}\x{638E}\x{638F}\x{6392}\x{6396}\x{6398}\x{639B}\x{639F}'
. '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A5}\x{63A7}\x{63A8}\x{63A9}\x{63AA}'
. '\x{63AB}\x{63AC}\x{63B2}\x{63B4}\x{63B5}\x{63BB}\x{63BE}\x{63C0}\x{63C3}'
. '\x{63C4}\x{63C6}\x{63C9}\x{63CF}\x{63D0}\x{63D2}\x{63D6}\x{63DA}\x{63DB}'
. '\x{63E1}\x{63E3}\x{63E9}\x{63EE}\x{63F4}\x{63F6}\x{63FA}\x{6406}\x{640D}'
. '\x{640F}\x{6413}\x{6416}\x{6417}\x{641C}\x{6426}\x{6428}\x{642C}\x{642D}'
. '\x{6434}\x{6436}\x{643A}\x{643E}\x{6442}\x{644E}\x{6458}\x{6467}\x{6469}'
. '\x{646F}\x{6476}\x{6478}\x{647A}\x{6483}\x{6488}\x{6492}\x{6493}\x{6495}'
. '\x{649A}\x{649E}\x{64A4}\x{64A5}\x{64A9}\x{64AB}\x{64AD}\x{64AE}\x{64B0}'
. '\x{64B2}\x{64B9}\x{64BB}\x{64BC}\x{64C1}\x{64C2}\x{64C5}\x{64C7}\x{64CD}'
. '\x{64D2}\x{64D4}\x{64D8}\x{64DA}\x{64E0}\x{64E1}\x{64E2}\x{64E3}\x{64E6}'
. '\x{64E7}\x{64EC}\x{64EF}\x{64F1}\x{64F2}\x{64F4}\x{64F6}\x{64FA}\x{64FD}'
. '\x{64FE}\x{6500}\x{6505}\x{6518}\x{651C}\x{651D}\x{6523}\x{6524}\x{652A}'
. '\x{652B}\x{652C}\x{652F}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}'
. '\x{653B}\x{653E}\x{653F}\x{6545}\x{6548}\x{654D}\x{654F}\x{6551}\x{6555}'
. '\x{6556}\x{6557}\x{6558}\x{6559}\x{655D}\x{655E}\x{6562}\x{6563}\x{6566}'
. '\x{656C}\x{6570}\x{6572}\x{6574}\x{6575}\x{6577}\x{6578}\x{6582}\x{6583}'
. '\x{6587}\x{6588}\x{6589}\x{658C}\x{658E}\x{6590}\x{6591}\x{6597}\x{6599}'
. '\x{659B}\x{659C}\x{659F}\x{65A1}\x{65A4}\x{65A5}\x{65A7}\x{65AB}\x{65AC}'
. '\x{65AD}\x{65AF}\x{65B0}\x{65B7}\x{65B9}\x{65BC}\x{65BD}\x{65C1}\x{65C3}'
. '\x{65C4}\x{65C5}\x{65C6}\x{65CB}\x{65CC}\x{65CF}\x{65D2}\x{65D7}\x{65D9}'
. '\x{65DB}\x{65E0}\x{65E1}\x{65E2}\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}'
. '\x{65EC}\x{65ED}\x{65F1}\x{65FA}\x{65FB}\x{6602}\x{6603}\x{6606}\x{6607}'
. '\x{660A}\x{660C}\x{660E}\x{660F}\x{6613}\x{6614}\x{661C}\x{661F}\x{6620}'
. '\x{6625}\x{6627}\x{6628}\x{662D}\x{662F}\x{6634}\x{6635}\x{6636}\x{663C}'
. '\x{663F}\x{6641}\x{6642}\x{6643}\x{6644}\x{6649}\x{664B}\x{664F}\x{6652}'
. '\x{665D}\x{665E}\x{665F}\x{6662}\x{6664}\x{6666}\x{6667}\x{6668}\x{6669}'
. '\x{666E}\x{666F}\x{6670}\x{6674}\x{6676}\x{667A}\x{6681}\x{6683}\x{6684}'
. '\x{6687}\x{6688}\x{6689}\x{668E}\x{6691}\x{6696}\x{6697}\x{6698}\x{669D}'
. '\x{66A2}\x{66A6}\x{66AB}\x{66AE}\x{66B4}\x{66B8}\x{66B9}\x{66BC}\x{66BE}'
. '\x{66C1}\x{66C4}\x{66C7}\x{66C9}\x{66D6}\x{66D9}\x{66DA}\x{66DC}\x{66DD}'
. '\x{66E0}\x{66E6}\x{66E9}\x{66F0}\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F7}'
. '\x{66F8}\x{66F9}\x{66FC}\x{66FD}\x{66FE}\x{66FF}\x{6700}\x{6703}\x{6708}'
. '\x{6709}\x{670B}\x{670D}\x{670F}\x{6714}\x{6715}\x{6716}\x{6717}\x{671B}'
. '\x{671D}\x{671E}\x{671F}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}'
. '\x{672D}\x{672E}\x{6731}\x{6734}\x{6736}\x{6737}\x{6738}\x{673A}\x{673D}'
. '\x{673F}\x{6741}\x{6746}\x{6749}\x{674E}\x{674F}\x{6750}\x{6751}\x{6753}'
. '\x{6756}\x{6759}\x{675C}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}'
. '\x{6764}\x{6765}\x{676A}\x{676D}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}'
. '\x{6775}\x{6777}\x{677C}\x{677E}\x{677F}\x{6785}\x{6787}\x{6789}\x{678B}'
. '\x{678C}\x{6790}\x{6795}\x{6797}\x{679A}\x{679C}\x{679D}\x{67A0}\x{67A1}'
. '\x{67A2}\x{67A6}\x{67A9}\x{67AF}\x{67B3}\x{67B4}\x{67B6}\x{67B7}\x{67B8}'
. '\x{67B9}\x{67C1}\x{67C4}\x{67C6}\x{67CA}\x{67CE}\x{67CF}\x{67D0}\x{67D1}'
. '\x{67D3}\x{67D4}\x{67D8}\x{67DA}\x{67DD}\x{67DE}\x{67E2}\x{67E4}\x{67E7}'
. '\x{67E9}\x{67EC}\x{67EE}\x{67EF}\x{67F1}\x{67F3}\x{67F4}\x{67F5}\x{67FB}'
. '\x{67FE}\x{67FF}\x{6802}\x{6803}\x{6804}\x{6813}\x{6816}\x{6817}\x{681E}'
. '\x{6821}\x{6822}\x{6829}\x{682A}\x{682B}\x{6832}\x{6834}\x{6838}\x{6839}'
. '\x{683C}\x{683D}\x{6840}\x{6841}\x{6842}\x{6843}\x{6846}\x{6848}\x{684D}'
. '\x{684E}\x{6850}\x{6851}\x{6853}\x{6854}\x{6859}\x{685C}\x{685D}\x{685F}'
. '\x{6863}\x{6867}\x{6874}\x{6876}\x{6877}\x{687E}\x{687F}\x{6881}\x{6883}'
. '\x{6885}\x{688D}\x{688F}\x{6893}\x{6894}\x{6897}\x{689B}\x{689D}\x{689F}'
. '\x{68A0}\x{68A2}\x{68A6}\x{68A7}\x{68A8}\x{68AD}\x{68AF}\x{68B0}\x{68B1}'
. '\x{68B3}\x{68B5}\x{68B6}\x{68B9}\x{68BA}\x{68BC}\x{68C4}\x{68C6}\x{68C9}'
. '\x{68CA}\x{68CB}\x{68CD}\x{68D2}\x{68D4}\x{68D5}\x{68D7}\x{68D8}\x{68DA}'
. '\x{68DF}\x{68E0}\x{68E1}\x{68E3}\x{68E7}\x{68EE}\x{68EF}\x{68F2}\x{68F9}'
. '\x{68FA}\x{6900}\x{6901}\x{6904}\x{6905}\x{6908}\x{690B}\x{690C}\x{690D}'
. '\x{690E}\x{690F}\x{6912}\x{6919}\x{691A}\x{691B}\x{691C}\x{6921}\x{6922}'
. '\x{6923}\x{6925}\x{6926}\x{6928}\x{692A}\x{6930}\x{6934}\x{6936}\x{6939}'
. '\x{693D}\x{693F}\x{694A}\x{6953}\x{6954}\x{6955}\x{6959}\x{695A}\x{695C}'
. '\x{695D}\x{695E}\x{6960}\x{6961}\x{6962}\x{696A}\x{696B}\x{696D}\x{696E}'
. '\x{696F}\x{6973}\x{6974}\x{6975}\x{6977}\x{6978}\x{6979}\x{697C}\x{697D}'
. '\x{697E}\x{6981}\x{6982}\x{698A}\x{698E}\x{6991}\x{6994}\x{6995}\x{699B}'
. '\x{699C}\x{69A0}\x{69A7}\x{69AE}\x{69B1}\x{69B2}\x{69B4}\x{69BB}\x{69BE}'
. '\x{69BF}\x{69C1}\x{69C3}\x{69C7}\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}'
. '\x{69D0}\x{69D3}\x{69D8}\x{69D9}\x{69DD}\x{69DE}\x{69E7}\x{69E8}\x{69EB}'
. '\x{69ED}\x{69F2}\x{69F9}\x{69FB}\x{69FD}\x{69FF}\x{6A02}\x{6A05}\x{6A0A}'
. '\x{6A0B}\x{6A0C}\x{6A12}\x{6A13}\x{6A14}\x{6A17}\x{6A19}\x{6A1B}\x{6A1E}'
. '\x{6A1F}\x{6A21}\x{6A22}\x{6A23}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2E}\x{6A35}'
. '\x{6A36}\x{6A38}\x{6A39}\x{6A3A}\x{6A3D}\x{6A44}\x{6A47}\x{6A48}\x{6A4B}'
. '\x{6A58}\x{6A59}\x{6A5F}\x{6A61}\x{6A62}\x{6A66}\x{6A72}\x{6A78}\x{6A7F}'
. '\x{6A80}\x{6A84}\x{6A8D}\x{6A8E}\x{6A90}\x{6A97}\x{6A9C}\x{6AA0}\x{6AA2}'
. '\x{6AA3}\x{6AAA}\x{6AAC}\x{6AAE}\x{6AB3}\x{6AB8}\x{6ABB}\x{6AC1}\x{6AC2}'
. '\x{6AC3}\x{6AD1}\x{6AD3}\x{6ADA}\x{6ADB}\x{6ADE}\x{6ADF}\x{6AE8}\x{6AEA}'
. '\x{6AFA}\x{6AFB}\x{6B04}\x{6B05}\x{6B0A}\x{6B12}\x{6B16}\x{6B1D}\x{6B1F}'
. '\x{6B20}\x{6B21}\x{6B23}\x{6B27}\x{6B32}\x{6B37}\x{6B38}\x{6B39}\x{6B3A}'
. '\x{6B3D}\x{6B3E}\x{6B43}\x{6B47}\x{6B49}\x{6B4C}\x{6B4E}\x{6B50}\x{6B53}'
. '\x{6B54}\x{6B59}\x{6B5B}\x{6B5F}\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B66}'
. '\x{6B69}\x{6B6A}\x{6B6F}\x{6B73}\x{6B74}\x{6B78}\x{6B79}\x{6B7B}\x{6B7F}'
. '\x{6B80}\x{6B83}\x{6B84}\x{6B86}\x{6B89}\x{6B8A}\x{6B8B}\x{6B8D}\x{6B95}'
. '\x{6B96}\x{6B98}\x{6B9E}\x{6BA4}\x{6BAA}\x{6BAB}\x{6BAF}\x{6BB1}\x{6BB2}'
. '\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB7}\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBF}\x{6BC0}'
. '\x{6BC5}\x{6BC6}\x{6BCB}\x{6BCD}\x{6BCE}\x{6BD2}\x{6BD3}\x{6BD4}\x{6BD8}'
. '\x{6BDB}\x{6BDF}\x{6BEB}\x{6BEC}\x{6BEF}\x{6BF3}\x{6C08}\x{6C0F}\x{6C11}'
. '\x{6C13}\x{6C14}\x{6C17}\x{6C1B}\x{6C23}\x{6C24}\x{6C34}\x{6C37}\x{6C38}'
. '\x{6C3E}\x{6C40}\x{6C41}\x{6C42}\x{6C4E}\x{6C50}\x{6C55}\x{6C57}\x{6C5A}'
. '\x{6C5D}\x{6C5E}\x{6C5F}\x{6C60}\x{6C62}\x{6C68}\x{6C6A}\x{6C70}\x{6C72}'
. '\x{6C73}\x{6C7A}\x{6C7D}\x{6C7E}\x{6C81}\x{6C82}\x{6C83}\x{6C88}\x{6C8C}'
. '\x{6C8D}\x{6C90}\x{6C92}\x{6C93}\x{6C96}\x{6C99}\x{6C9A}\x{6C9B}\x{6CA1}'
. '\x{6CA2}\x{6CAB}\x{6CAE}\x{6CB1}\x{6CB3}\x{6CB8}\x{6CB9}\x{6CBA}\x{6CBB}'
. '\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC1}\x{6CC4}\x{6CC5}\x{6CC9}\x{6CCA}'
. '\x{6CCC}\x{6CD3}\x{6CD5}\x{6CD7}\x{6CD9}\x{6CDB}\x{6CDD}\x{6CE1}\x{6CE2}'
. '\x{6CE3}\x{6CE5}\x{6CE8}\x{6CEA}\x{6CEF}\x{6CF0}\x{6CF1}\x{6CF3}\x{6D0B}'
. '\x{6D0C}\x{6D12}\x{6D17}\x{6D19}\x{6D1B}\x{6D1E}\x{6D1F}\x{6D25}\x{6D29}'
. '\x{6D2A}\x{6D2B}\x{6D32}\x{6D33}\x{6D35}\x{6D36}\x{6D38}\x{6D3B}\x{6D3D}'
. '\x{6D3E}\x{6D41}\x{6D44}\x{6D45}\x{6D59}\x{6D5A}\x{6D5C}\x{6D63}\x{6D64}'
. '\x{6D66}\x{6D69}\x{6D6A}\x{6D6C}\x{6D6E}\x{6D74}\x{6D77}\x{6D78}\x{6D79}'
. '\x{6D85}\x{6D88}\x{6D8C}\x{6D8E}\x{6D93}\x{6D95}\x{6D99}\x{6D9B}\x{6D9C}'
. '\x{6DAF}\x{6DB2}\x{6DB5}\x{6DB8}\x{6DBC}\x{6DC0}\x{6DC5}\x{6DC6}\x{6DC7}'
. '\x{6DCB}\x{6DCC}\x{6DD1}\x{6DD2}\x{6DD5}\x{6DD8}\x{6DD9}\x{6DDE}\x{6DE1}'
. '\x{6DE4}\x{6DE6}\x{6DE8}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DEE}\x{6DF1}\x{6DF3}'
. '\x{6DF5}\x{6DF7}\x{6DF9}\x{6DFA}\x{6DFB}\x{6E05}\x{6E07}\x{6E08}\x{6E09}'
. '\x{6E0A}\x{6E0B}\x{6E13}\x{6E15}\x{6E19}\x{6E1A}\x{6E1B}\x{6E1D}\x{6E1F}'
. '\x{6E20}\x{6E21}\x{6E23}\x{6E24}\x{6E25}\x{6E26}\x{6E29}\x{6E2B}\x{6E2C}'
. '\x{6E2D}\x{6E2E}\x{6E2F}\x{6E38}\x{6E3A}\x{6E3E}\x{6E43}\x{6E4A}\x{6E4D}'
. '\x{6E4E}\x{6E56}\x{6E58}\x{6E5B}\x{6E5F}\x{6E67}\x{6E6B}\x{6E6E}\x{6E6F}'
. '\x{6E72}\x{6E76}\x{6E7E}\x{6E7F}\x{6E80}\x{6E82}\x{6E8C}\x{6E8F}\x{6E90}'
. '\x{6E96}\x{6E98}\x{6E9C}\x{6E9D}\x{6E9F}\x{6EA2}\x{6EA5}\x{6EAA}\x{6EAF}'
. '\x{6EB2}\x{6EB6}\x{6EB7}\x{6EBA}\x{6EBD}\x{6EC2}\x{6EC4}\x{6EC5}\x{6EC9}'
. '\x{6ECB}\x{6ECC}\x{6ED1}\x{6ED3}\x{6ED4}\x{6ED5}\x{6EDD}\x{6EDE}\x{6EEC}'
. '\x{6EEF}\x{6EF2}\x{6EF4}\x{6EF7}\x{6EF8}\x{6EFE}\x{6EFF}\x{6F01}\x{6F02}'
. '\x{6F06}\x{6F09}\x{6F0F}\x{6F11}\x{6F13}\x{6F14}\x{6F15}\x{6F20}\x{6F22}'
. '\x{6F23}\x{6F2B}\x{6F2C}\x{6F31}\x{6F32}\x{6F38}\x{6F3E}\x{6F3F}\x{6F41}'
. '\x{6F45}\x{6F54}\x{6F58}\x{6F5B}\x{6F5C}\x{6F5F}\x{6F64}\x{6F66}\x{6F6D}'
. '\x{6F6E}\x{6F6F}\x{6F70}\x{6F74}\x{6F78}\x{6F7A}\x{6F7C}\x{6F80}\x{6F81}'
. '\x{6F82}\x{6F84}\x{6F86}\x{6F8E}\x{6F91}\x{6F97}\x{6FA1}\x{6FA3}\x{6FA4}'
. '\x{6FAA}\x{6FB1}\x{6FB3}\x{6FB9}\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC6}'
. '\x{6FD4}\x{6FD5}\x{6FD8}\x{6FDB}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE4}\x{6FEB}'
. '\x{6FEC}\x{6FEE}\x{6FEF}\x{6FF1}\x{6FF3}\x{6FF6}\x{6FFA}\x{6FFE}\x{7001}'
. '\x{7009}\x{700B}\x{700F}\x{7011}\x{7015}\x{7018}\x{701A}\x{701B}\x{701D}'
. '\x{701E}\x{701F}\x{7026}\x{7027}\x{702C}\x{7030}\x{7032}\x{703E}\x{704C}'
. '\x{7051}\x{7058}\x{7063}\x{706B}\x{706F}\x{7070}\x{7078}\x{707C}\x{707D}'
. '\x{7089}\x{708A}\x{708E}\x{7092}\x{7099}\x{70AC}\x{70AD}\x{70AE}\x{70AF}'
. '\x{70B3}\x{70B8}\x{70B9}\x{70BA}\x{70C8}\x{70CB}\x{70CF}\x{70D9}\x{70DD}'
. '\x{70DF}\x{70F1}\x{70F9}\x{70FD}\x{7109}\x{7114}\x{7119}\x{711A}\x{711C}'
. '\x{7121}\x{7126}\x{7136}\x{713C}\x{7149}\x{714C}\x{714E}\x{7155}\x{7156}'
. '\x{7159}\x{7162}\x{7164}\x{7165}\x{7166}\x{7167}\x{7169}\x{716C}\x{716E}'
. '\x{717D}\x{7184}\x{7188}\x{718A}\x{718F}\x{7194}\x{7195}\x{7199}\x{719F}'
. '\x{71A8}\x{71AC}\x{71B1}\x{71B9}\x{71BE}\x{71C3}\x{71C8}\x{71C9}\x{71CE}'
. '\x{71D0}\x{71D2}\x{71D4}\x{71D5}\x{71D7}\x{71DF}\x{71E0}\x{71E5}\x{71E6}'
. '\x{71E7}\x{71EC}\x{71ED}\x{71EE}\x{71F5}\x{71F9}\x{71FB}\x{71FC}\x{71FF}'
. '\x{7206}\x{720D}\x{7210}\x{721B}\x{7228}\x{722A}\x{722C}\x{722D}\x{7230}'
. '\x{7232}\x{7235}\x{7236}\x{723A}\x{723B}\x{723C}\x{723D}\x{723E}\x{723F}'
. '\x{7240}\x{7246}\x{7247}\x{7248}\x{724B}\x{724C}\x{7252}\x{7258}\x{7259}'
. '\x{725B}\x{725D}\x{725F}\x{7261}\x{7262}\x{7267}\x{7269}\x{7272}\x{7274}'
. '\x{7279}\x{727D}\x{727E}\x{7280}\x{7281}\x{7282}\x{7287}\x{7292}\x{7296}'
. '\x{72A0}\x{72A2}\x{72A7}\x{72AC}\x{72AF}\x{72B2}\x{72B6}\x{72B9}\x{72C2}'
. '\x{72C3}\x{72C4}\x{72C6}\x{72CE}\x{72D0}\x{72D2}\x{72D7}\x{72D9}\x{72DB}'
. '\x{72E0}\x{72E1}\x{72E2}\x{72E9}\x{72EC}\x{72ED}\x{72F7}\x{72F8}\x{72F9}'
. '\x{72FC}\x{72FD}\x{730A}\x{7316}\x{7317}\x{731B}\x{731C}\x{731D}\x{731F}'
. '\x{7325}\x{7329}\x{732A}\x{732B}\x{732E}\x{732F}\x{7334}\x{7336}\x{7337}'
. '\x{733E}\x{733F}\x{7344}\x{7345}\x{734E}\x{734F}\x{7357}\x{7363}\x{7368}'
. '\x{736A}\x{7370}\x{7372}\x{7375}\x{7378}\x{737A}\x{737B}\x{7384}\x{7387}'
. '\x{7389}\x{738B}\x{7396}\x{73A9}\x{73B2}\x{73B3}\x{73BB}\x{73C0}\x{73C2}'
. '\x{73C8}\x{73CA}\x{73CD}\x{73CE}\x{73DE}\x{73E0}\x{73E5}\x{73EA}\x{73ED}'
. '\x{73EE}\x{73F1}\x{73F8}\x{73FE}\x{7403}\x{7405}\x{7406}\x{7409}\x{7422}'
. '\x{7425}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{743A}\x{743F}\x{7441}'
. '\x{7455}\x{7459}\x{745A}\x{745B}\x{745C}\x{745E}\x{745F}\x{7460}\x{7463}'
. '\x{7464}\x{7469}\x{746A}\x{746F}\x{7470}\x{7473}\x{7476}\x{747E}\x{7483}'
. '\x{748B}\x{749E}\x{74A2}\x{74A7}\x{74B0}\x{74BD}\x{74CA}\x{74CF}\x{74D4}'
. '\x{74DC}\x{74E0}\x{74E2}\x{74E3}\x{74E6}\x{74E7}\x{74E9}\x{74EE}\x{74F0}'
. '\x{74F1}\x{74F2}\x{74F6}\x{74F7}\x{74F8}\x{7503}\x{7504}\x{7505}\x{750C}'
. '\x{750D}\x{750E}\x{7511}\x{7513}\x{7515}\x{7518}\x{751A}\x{751C}\x{751E}'
. '\x{751F}\x{7523}\x{7525}\x{7526}\x{7528}\x{752B}\x{752C}\x{7530}\x{7531}'
. '\x{7532}\x{7533}\x{7537}\x{7538}\x{753A}\x{753B}\x{753C}\x{7544}\x{7546}'
. '\x{7549}\x{754A}\x{754B}\x{754C}\x{754D}\x{754F}\x{7551}\x{7554}\x{7559}'
. '\x{755A}\x{755B}\x{755C}\x{755D}\x{7560}\x{7562}\x{7564}\x{7565}\x{7566}'
. '\x{7567}\x{7569}\x{756A}\x{756B}\x{756D}\x{7570}\x{7573}\x{7574}\x{7576}'
. '\x{7577}\x{7578}\x{757F}\x{7582}\x{7586}\x{7587}\x{7589}\x{758A}\x{758B}'
. '\x{758E}\x{758F}\x{7591}\x{7594}\x{759A}\x{759D}\x{75A3}\x{75A5}\x{75AB}'
. '\x{75B1}\x{75B2}\x{75B3}\x{75B5}\x{75B8}\x{75B9}\x{75BC}\x{75BD}\x{75BE}'
. '\x{75C2}\x{75C3}\x{75C5}\x{75C7}\x{75CA}\x{75CD}\x{75D2}\x{75D4}\x{75D5}'
. '\x{75D8}\x{75D9}\x{75DB}\x{75DE}\x{75E2}\x{75E3}\x{75E9}\x{75F0}\x{75F2}'
. '\x{75F3}\x{75F4}\x{75FA}\x{75FC}\x{75FE}\x{75FF}\x{7601}\x{7609}\x{760B}'
. '\x{760D}\x{761F}\x{7620}\x{7621}\x{7622}\x{7624}\x{7627}\x{7630}\x{7634}'
. '\x{763B}\x{7642}\x{7646}\x{7647}\x{7648}\x{764C}\x{7652}\x{7656}\x{7658}'
. '\x{765C}\x{7661}\x{7662}\x{7667}\x{7668}\x{7669}\x{766A}\x{766C}\x{7670}'
. '\x{7672}\x{7676}\x{7678}\x{767A}\x{767B}\x{767C}\x{767D}\x{767E}\x{7680}'
. '\x{7683}\x{7684}\x{7686}\x{7687}\x{7688}\x{768B}\x{768E}\x{7690}\x{7693}'
. '\x{7696}\x{7699}\x{769A}\x{76AE}\x{76B0}\x{76B4}\x{76B7}\x{76B8}\x{76B9}'
. '\x{76BA}\x{76BF}\x{76C2}\x{76C3}\x{76C6}\x{76C8}\x{76CA}\x{76CD}\x{76D2}'
. '\x{76D6}\x{76D7}\x{76DB}\x{76DC}\x{76DE}\x{76DF}\x{76E1}\x{76E3}\x{76E4}'
. '\x{76E5}\x{76E7}\x{76EA}\x{76EE}\x{76F2}\x{76F4}\x{76F8}\x{76FB}\x{76FE}'
. '\x{7701}\x{7704}\x{7707}\x{7708}\x{7709}\x{770B}\x{770C}\x{771B}\x{771E}'
. '\x{771F}\x{7720}\x{7724}\x{7725}\x{7726}\x{7729}\x{7737}\x{7738}\x{773A}'
. '\x{773C}\x{7740}\x{7747}\x{775A}\x{775B}\x{7761}\x{7763}\x{7765}\x{7766}'
. '\x{7768}\x{776B}\x{7779}\x{777E}\x{777F}\x{778B}\x{778E}\x{7791}\x{779E}'
. '\x{77A0}\x{77A5}\x{77AC}\x{77AD}\x{77B0}\x{77B3}\x{77B6}\x{77B9}\x{77BB}'
. '\x{77BC}\x{77BD}\x{77BF}\x{77C7}\x{77CD}\x{77D7}\x{77DA}\x{77DB}\x{77DC}'
. '\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E9}\x{77ED}\x{77EE}\x{77EF}\x{77F3}'
. '\x{77FC}\x{7802}\x{780C}\x{7812}\x{7814}\x{7815}\x{7820}\x{7825}\x{7826}'
. '\x{7827}\x{7832}\x{7834}\x{783A}\x{783F}\x{7845}\x{785D}\x{786B}\x{786C}'
. '\x{786F}\x{7872}\x{7874}\x{787C}\x{7881}\x{7886}\x{7887}\x{788C}\x{788D}'
. '\x{788E}\x{7891}\x{7893}\x{7895}\x{7897}\x{789A}\x{78A3}\x{78A7}\x{78A9}'
. '\x{78AA}\x{78AF}\x{78B5}\x{78BA}\x{78BC}\x{78BE}\x{78C1}\x{78C5}\x{78C6}'
. '\x{78CA}\x{78CB}\x{78D0}\x{78D1}\x{78D4}\x{78DA}\x{78E7}\x{78E8}\x{78EC}'
. '\x{78EF}\x{78F4}\x{78FD}\x{7901}\x{7907}\x{790E}\x{7911}\x{7912}\x{7919}'
. '\x{7926}\x{792A}\x{792B}\x{792C}\x{793A}\x{793C}\x{793E}\x{7940}\x{7941}'
. '\x{7947}\x{7948}\x{7949}\x{7950}\x{7953}\x{7955}\x{7956}\x{7957}\x{795A}'
. '\x{795D}\x{795E}\x{795F}\x{7960}\x{7962}\x{7965}\x{7968}\x{796D}\x{7977}'
. '\x{797A}\x{797F}\x{7980}\x{7981}\x{7984}\x{7985}\x{798A}\x{798D}\x{798E}'
. '\x{798F}\x{799D}\x{79A6}\x{79A7}\x{79AA}\x{79AE}\x{79B0}\x{79B3}\x{79B9}'
. '\x{79BA}\x{79BD}\x{79BE}\x{79BF}\x{79C0}\x{79C1}\x{79C9}\x{79CB}\x{79D1}'
. '\x{79D2}\x{79D5}\x{79D8}\x{79DF}\x{79E1}\x{79E3}\x{79E4}\x{79E6}\x{79E7}'
. '\x{79E9}\x{79EC}\x{79F0}\x{79FB}\x{7A00}\x{7A08}\x{7A0B}\x{7A0D}\x{7A0E}'
. '\x{7A14}\x{7A17}\x{7A18}\x{7A19}\x{7A1A}\x{7A1C}\x{7A1F}\x{7A20}\x{7A2E}'
. '\x{7A31}\x{7A32}\x{7A37}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}'
. '\x{7A42}\x{7A43}\x{7A46}\x{7A49}\x{7A4D}\x{7A4E}\x{7A4F}\x{7A50}\x{7A57}'
. '\x{7A61}\x{7A62}\x{7A63}\x{7A69}\x{7A6B}\x{7A70}\x{7A74}\x{7A76}\x{7A79}'
. '\x{7A7A}\x{7A7D}\x{7A7F}\x{7A81}\x{7A83}\x{7A84}\x{7A88}\x{7A92}\x{7A93}'
. '\x{7A95}\x{7A96}\x{7A97}\x{7A98}\x{7A9F}\x{7AA9}\x{7AAA}\x{7AAE}\x{7AAF}'
. '\x{7AB0}\x{7AB6}\x{7ABA}\x{7ABF}\x{7AC3}\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}'
. '\x{7ACA}\x{7ACB}\x{7ACD}\x{7ACF}\x{7AD2}\x{7AD3}\x{7AD5}\x{7AD9}\x{7ADA}'
. '\x{7ADC}\x{7ADD}\x{7ADF}\x{7AE0}\x{7AE1}\x{7AE2}\x{7AE3}\x{7AE5}\x{7AE6}'
. '\x{7AEA}\x{7AED}\x{7AEF}\x{7AF0}\x{7AF6}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFF}'
. '\x{7B02}\x{7B04}\x{7B06}\x{7B08}\x{7B0A}\x{7B0B}\x{7B0F}\x{7B11}\x{7B18}'
. '\x{7B19}\x{7B1B}\x{7B1E}\x{7B20}\x{7B25}\x{7B26}\x{7B28}\x{7B2C}\x{7B33}'
. '\x{7B35}\x{7B36}\x{7B39}\x{7B45}\x{7B46}\x{7B48}\x{7B49}\x{7B4B}\x{7B4C}'
. '\x{7B4D}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B56}\x{7B5D}\x{7B65}'
. '\x{7B67}\x{7B6C}\x{7B6E}\x{7B70}\x{7B71}\x{7B74}\x{7B75}\x{7B7A}\x{7B86}'
. '\x{7B87}\x{7B8B}\x{7B8D}\x{7B8F}\x{7B92}\x{7B94}\x{7B95}\x{7B97}\x{7B98}'
. '\x{7B99}\x{7B9A}\x{7B9C}\x{7B9D}\x{7B9F}\x{7BA1}\x{7BAA}\x{7BAD}\x{7BB1}'
. '\x{7BB4}\x{7BB8}\x{7BC0}\x{7BC1}\x{7BC4}\x{7BC6}\x{7BC7}\x{7BC9}\x{7BCB}'
. '\x{7BCC}\x{7BCF}\x{7BDD}\x{7BE0}\x{7BE4}\x{7BE5}\x{7BE6}\x{7BE9}\x{7BED}'
. '\x{7BF3}\x{7BF6}\x{7BF7}\x{7C00}\x{7C07}\x{7C0D}\x{7C11}\x{7C12}\x{7C13}'
. '\x{7C14}\x{7C17}\x{7C1F}\x{7C21}\x{7C23}\x{7C27}\x{7C2A}\x{7C2B}\x{7C37}'
. '\x{7C38}\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C43}\x{7C4C}\x{7C4D}\x{7C4F}'
. '\x{7C50}\x{7C54}\x{7C56}\x{7C58}\x{7C5F}\x{7C60}\x{7C64}\x{7C65}\x{7C6C}'
. '\x{7C73}\x{7C75}\x{7C7E}\x{7C81}\x{7C82}\x{7C83}\x{7C89}\x{7C8B}\x{7C8D}'
. '\x{7C90}\x{7C92}\x{7C95}\x{7C97}\x{7C98}\x{7C9B}\x{7C9F}\x{7CA1}\x{7CA2}'
. '\x{7CA4}\x{7CA5}\x{7CA7}\x{7CA8}\x{7CAB}\x{7CAD}\x{7CAE}\x{7CB1}\x{7CB2}'
. '\x{7CB3}\x{7CB9}\x{7CBD}\x{7CBE}\x{7CC0}\x{7CC2}\x{7CC5}\x{7CCA}\x{7CCE}'
. '\x{7CD2}\x{7CD6}\x{7CD8}\x{7CDC}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE7}'
. '\x{7CEF}\x{7CF2}\x{7CF4}\x{7CF6}\x{7CF8}\x{7CFA}\x{7CFB}\x{7CFE}\x{7D00}'
. '\x{7D02}\x{7D04}\x{7D05}\x{7D06}\x{7D0A}\x{7D0B}\x{7D0D}\x{7D10}\x{7D14}'
. '\x{7D15}\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D20}\x{7D21}'
. '\x{7D22}\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D32}\x{7D33}\x{7D35}'
. '\x{7D39}\x{7D3A}\x{7D3F}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}\x{7D4B}'
. '\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D56}\x{7D5B}\x{7D5E}\x{7D61}\x{7D62}'
. '\x{7D63}\x{7D66}\x{7D68}\x{7D6E}\x{7D71}\x{7D72}\x{7D73}\x{7D75}\x{7D76}'
. '\x{7D79}\x{7D7D}\x{7D89}\x{7D8F}\x{7D93}\x{7D99}\x{7D9A}\x{7D9B}\x{7D9C}'
. '\x{7D9F}\x{7DA2}\x{7DA3}\x{7DAB}\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}'
. '\x{7DB1}\x{7DB2}\x{7DB4}\x{7DB5}\x{7DB8}\x{7DBA}\x{7DBB}\x{7DBD}\x{7DBE}'
. '\x{7DBF}\x{7DC7}\x{7DCA}\x{7DCB}\x{7DCF}\x{7DD1}\x{7DD2}\x{7DD5}\x{7DD8}'
. '\x{7DDA}\x{7DDC}\x{7DDD}\x{7DDE}\x{7DE0}\x{7DE1}\x{7DE4}\x{7DE8}\x{7DE9}'
. '\x{7DEC}\x{7DEF}\x{7DF2}\x{7DF4}\x{7DFB}\x{7E01}\x{7E04}\x{7E05}\x{7E09}'
. '\x{7E0A}\x{7E0B}\x{7E12}\x{7E1B}\x{7E1E}\x{7E1F}\x{7E21}\x{7E22}\x{7E23}'
. '\x{7E26}\x{7E2B}\x{7E2E}\x{7E31}\x{7E32}\x{7E35}\x{7E37}\x{7E39}\x{7E3A}'
. '\x{7E3B}\x{7E3D}\x{7E3E}\x{7E41}\x{7E43}\x{7E46}\x{7E4A}\x{7E4B}\x{7E4D}'
. '\x{7E54}\x{7E55}\x{7E56}\x{7E59}\x{7E5A}\x{7E5D}\x{7E5E}\x{7E66}\x{7E67}'
. '\x{7E69}\x{7E6A}\x{7E6D}\x{7E70}\x{7E79}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7F}'
. '\x{7E82}\x{7E83}\x{7E88}\x{7E89}\x{7E8C}\x{7E8E}\x{7E8F}\x{7E90}\x{7E92}'
. '\x{7E93}\x{7E94}\x{7E96}\x{7E9B}\x{7E9C}\x{7F36}\x{7F38}\x{7F3A}\x{7F45}'
. '\x{7F4C}\x{7F4D}\x{7F4E}\x{7F50}\x{7F51}\x{7F54}\x{7F55}\x{7F58}\x{7F5F}'
. '\x{7F60}\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6E}\x{7F70}\x{7F72}'
. '\x{7F75}\x{7F77}\x{7F78}\x{7F79}\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}'
. '\x{7F88}\x{7F8A}\x{7F8C}\x{7F8E}\x{7F94}\x{7F9A}\x{7F9D}\x{7F9E}\x{7FA3}'
. '\x{7FA4}\x{7FA8}\x{7FA9}\x{7FAE}\x{7FAF}\x{7FB2}\x{7FB6}\x{7FB8}\x{7FB9}'
. '\x{7FBD}\x{7FC1}\x{7FC5}\x{7FC6}\x{7FCA}\x{7FCC}\x{7FD2}\x{7FD4}\x{7FD5}'
. '\x{7FE0}\x{7FE1}\x{7FE6}\x{7FE9}\x{7FEB}\x{7FF0}\x{7FF3}\x{7FF9}\x{7FFB}'
. '\x{7FFC}\x{8000}\x{8001}\x{8003}\x{8004}\x{8005}\x{8006}\x{800B}\x{800C}'
. '\x{8010}\x{8012}\x{8015}\x{8017}\x{8018}\x{8019}\x{801C}\x{8021}\x{8028}'
. '\x{8033}\x{8036}\x{803B}\x{803D}\x{803F}\x{8046}\x{804A}\x{8052}\x{8056}'
. '\x{8058}\x{805A}\x{805E}\x{805F}\x{8061}\x{8062}\x{8068}\x{806F}\x{8070}'
. '\x{8072}\x{8073}\x{8074}\x{8076}\x{8077}\x{8079}\x{807D}\x{807E}\x{807F}'
. '\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808B}\x{808C}\x{8093}\x{8096}'
. '\x{8098}\x{809A}\x{809B}\x{809D}\x{80A1}\x{80A2}\x{80A5}\x{80A9}\x{80AA}'
. '\x{80AC}\x{80AD}\x{80AF}\x{80B1}\x{80B2}\x{80B4}\x{80BA}\x{80C3}\x{80C4}'
. '\x{80C6}\x{80CC}\x{80CE}\x{80D6}\x{80D9}\x{80DA}\x{80DB}\x{80DD}\x{80DE}'
. '\x{80E1}\x{80E4}\x{80E5}\x{80EF}\x{80F1}\x{80F4}\x{80F8}\x{80FC}\x{80FD}'
. '\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{811A}\x{811B}'
. '\x{8123}\x{8129}\x{812F}\x{8131}\x{8133}\x{8139}\x{813E}\x{8146}\x{814B}'
. '\x{814E}\x{8150}\x{8151}\x{8153}\x{8154}\x{8155}\x{815F}\x{8165}\x{8166}'
. '\x{816B}\x{816E}\x{8170}\x{8171}\x{8174}\x{8178}\x{8179}\x{817A}\x{817F}'
. '\x{8180}\x{8182}\x{8183}\x{8188}\x{818A}\x{818F}\x{8193}\x{8195}\x{819A}'
. '\x{819C}\x{819D}\x{81A0}\x{81A3}\x{81A4}\x{81A8}\x{81A9}\x{81B0}\x{81B3}'
. '\x{81B5}\x{81B8}\x{81BA}\x{81BD}\x{81BE}\x{81BF}\x{81C0}\x{81C2}\x{81C6}'
. '\x{81C8}\x{81C9}\x{81CD}\x{81D1}\x{81D3}\x{81D8}\x{81D9}\x{81DA}\x{81DF}'
. '\x{81E0}\x{81E3}\x{81E5}\x{81E7}\x{81E8}\x{81EA}\x{81ED}\x{81F3}\x{81F4}'
. '\x{81FA}\x{81FB}\x{81FC}\x{81FE}\x{8201}\x{8202}\x{8205}\x{8207}\x{8208}'
. '\x{8209}\x{820A}\x{820C}\x{820D}\x{820E}\x{8210}\x{8212}\x{8216}\x{8217}'
. '\x{8218}\x{821B}\x{821C}\x{821E}\x{821F}\x{8229}\x{822A}\x{822B}\x{822C}'
. '\x{822E}\x{8233}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{8240}\x{8247}'
. '\x{8258}\x{8259}\x{825A}\x{825D}\x{825F}\x{8262}\x{8264}\x{8266}\x{8268}'
. '\x{826A}\x{826B}\x{826E}\x{826F}\x{8271}\x{8272}\x{8276}\x{8277}\x{8278}'
. '\x{827E}\x{828B}\x{828D}\x{8292}\x{8299}\x{829D}\x{829F}\x{82A5}\x{82A6}'
. '\x{82AB}\x{82AC}\x{82AD}\x{82AF}\x{82B1}\x{82B3}\x{82B8}\x{82B9}\x{82BB}'
. '\x{82BD}\x{82C5}\x{82D1}\x{82D2}\x{82D3}\x{82D4}\x{82D7}\x{82D9}\x{82DB}'
. '\x{82DC}\x{82DE}\x{82DF}\x{82E1}\x{82E3}\x{82E5}\x{82E6}\x{82E7}\x{82EB}'
. '\x{82F1}\x{82F3}\x{82F4}\x{82F9}\x{82FA}\x{82FB}\x{8302}\x{8303}\x{8304}'
. '\x{8305}\x{8306}\x{8309}\x{830E}\x{8316}\x{8317}\x{8318}\x{831C}\x{8323}'
. '\x{8328}\x{832B}\x{832F}\x{8331}\x{8332}\x{8334}\x{8335}\x{8336}\x{8338}'
. '\x{8339}\x{8340}\x{8345}\x{8349}\x{834A}\x{834F}\x{8350}\x{8352}\x{8358}'
. '\x{8373}\x{8375}\x{8377}\x{837B}\x{837C}\x{8385}\x{8387}\x{8389}\x{838A}'
. '\x{838E}\x{8393}\x{8396}\x{839A}\x{839E}\x{839F}\x{83A0}\x{83A2}\x{83A8}'
. '\x{83AA}\x{83AB}\x{83B1}\x{83B5}\x{83BD}\x{83C1}\x{83C5}\x{83CA}\x{83CC}'
. '\x{83CE}\x{83D3}\x{83D6}\x{83D8}\x{83DC}\x{83DF}\x{83E0}\x{83E9}\x{83EB}'
. '\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F4}\x{83F7}\x{83FB}\x{83FD}\x{8403}'
. '\x{8404}\x{8407}\x{840B}\x{840C}\x{840D}\x{840E}\x{8413}\x{8420}\x{8422}'
. '\x{8429}\x{842A}\x{842C}\x{8431}\x{8435}\x{8438}\x{843C}\x{843D}\x{8446}'
. '\x{8449}\x{844E}\x{8457}\x{845B}\x{8461}\x{8462}\x{8463}\x{8466}\x{8469}'
. '\x{846B}\x{846C}\x{846D}\x{846E}\x{846F}\x{8471}\x{8475}\x{8477}\x{8479}'
. '\x{847A}\x{8482}\x{8484}\x{848B}\x{8490}\x{8494}\x{8499}\x{849C}\x{849F}'
. '\x{84A1}\x{84AD}\x{84B2}\x{84B8}\x{84B9}\x{84BB}\x{84BC}\x{84BF}\x{84C1}'
. '\x{84C4}\x{84C6}\x{84C9}\x{84CA}\x{84CB}\x{84CD}\x{84D0}\x{84D1}\x{84D6}'
. '\x{84D9}\x{84DA}\x{84EC}\x{84EE}\x{84F4}\x{84FC}\x{84FF}\x{8500}\x{8506}'
. '\x{8511}\x{8513}\x{8514}\x{8515}\x{8517}\x{8518}\x{851A}\x{851F}\x{8521}'
. '\x{8526}\x{852C}\x{852D}\x{8535}\x{853D}\x{8540}\x{8541}\x{8543}\x{8548}'
. '\x{8549}\x{854A}\x{854B}\x{854E}\x{8555}\x{8557}\x{8558}\x{855A}\x{8563}'
. '\x{8568}\x{8569}\x{856A}\x{856D}\x{8577}\x{857E}\x{8580}\x{8584}\x{8587}'
. '\x{8588}\x{858A}\x{8590}\x{8591}\x{8594}\x{8597}\x{8599}\x{859B}\x{859C}'
. '\x{85A4}\x{85A6}\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AE}\x{85AF}'
. '\x{85B9}\x{85BA}\x{85C1}\x{85C9}\x{85CD}\x{85CF}\x{85D0}\x{85D5}\x{85DC}'
. '\x{85DD}\x{85E4}\x{85E5}\x{85E9}\x{85EA}\x{85F7}\x{85F9}\x{85FA}\x{85FB}'
. '\x{85FE}\x{8602}\x{8606}\x{8607}\x{860A}\x{860B}\x{8613}\x{8616}\x{8617}'
. '\x{861A}\x{8622}\x{862D}\x{862F}\x{8630}\x{863F}\x{864D}\x{864E}\x{8650}'
. '\x{8654}\x{8655}\x{865A}\x{865C}\x{865E}\x{865F}\x{8667}\x{866B}\x{8671}'
. '\x{8679}\x{867B}\x{868A}\x{868B}\x{868C}\x{8693}\x{8695}\x{86A3}\x{86A4}'
. '\x{86A9}\x{86AA}\x{86AB}\x{86AF}\x{86B0}\x{86B6}\x{86C4}\x{86C6}\x{86C7}'
. '\x{86C9}\x{86CB}\x{86CD}\x{86CE}\x{86D4}\x{86D9}\x{86DB}\x{86DE}\x{86DF}'
. '\x{86E4}\x{86E9}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F8}\x{86F9}\x{86FB}'
. '\x{86FE}\x{8700}\x{8702}\x{8703}\x{8706}\x{8708}\x{8709}\x{870A}\x{870D}'
. '\x{8711}\x{8712}\x{8718}\x{871A}\x{871C}\x{8725}\x{8729}\x{8734}\x{8737}'
. '\x{873B}\x{873F}\x{8749}\x{874B}\x{874C}\x{874E}\x{8753}\x{8755}\x{8757}'
. '\x{8759}\x{875F}\x{8760}\x{8763}\x{8766}\x{8768}\x{876A}\x{876E}\x{8774}'
. '\x{8776}\x{8778}\x{877F}\x{8782}\x{878D}\x{879F}\x{87A2}\x{87AB}\x{87AF}'
. '\x{87B3}\x{87BA}\x{87BB}\x{87BD}\x{87C0}\x{87C4}\x{87C6}\x{87C7}\x{87CB}'
. '\x{87D0}\x{87D2}\x{87E0}\x{87EF}\x{87F2}\x{87F6}\x{87F7}\x{87F9}\x{87FB}'
. '\x{87FE}\x{8805}\x{880D}\x{880E}\x{880F}\x{8811}\x{8815}\x{8816}\x{8821}'
. '\x{8822}\x{8823}\x{8827}\x{8831}\x{8836}\x{8839}\x{883B}\x{8840}\x{8842}'
. '\x{8844}\x{8846}\x{884C}\x{884D}\x{8852}\x{8853}\x{8857}\x{8859}\x{885B}'
. '\x{885D}\x{885E}\x{8861}\x{8862}\x{8863}\x{8868}\x{886B}\x{8870}\x{8872}'
. '\x{8875}\x{8877}\x{887D}\x{887E}\x{887F}\x{8881}\x{8882}\x{8888}\x{888B}'
. '\x{888D}\x{8892}\x{8896}\x{8897}\x{8899}\x{889E}\x{88A2}\x{88A4}\x{88AB}'
. '\x{88AE}\x{88B0}\x{88B1}\x{88B4}\x{88B5}\x{88B7}\x{88BF}\x{88C1}\x{88C2}'
. '\x{88C3}\x{88C4}\x{88C5}\x{88CF}\x{88D4}\x{88D5}\x{88D8}\x{88D9}\x{88DC}'
. '\x{88DD}\x{88DF}\x{88E1}\x{88E8}\x{88F2}\x{88F3}\x{88F4}\x{88F8}\x{88F9}'
. '\x{88FC}\x{88FD}\x{88FE}\x{8902}\x{8904}\x{8907}\x{890A}\x{890C}\x{8910}'
. '\x{8912}\x{8913}\x{891D}\x{891E}\x{8925}\x{892A}\x{892B}\x{8936}\x{8938}'
. '\x{893B}\x{8941}\x{8943}\x{8944}\x{894C}\x{894D}\x{8956}\x{895E}\x{895F}'
. '\x{8960}\x{8964}\x{8966}\x{896A}\x{896D}\x{896F}\x{8972}\x{8974}\x{8977}'
. '\x{897E}\x{897F}\x{8981}\x{8983}\x{8986}\x{8987}\x{8988}\x{898A}\x{898B}'
. '\x{898F}\x{8993}\x{8996}\x{8997}\x{8998}\x{899A}\x{89A1}\x{89A6}\x{89A7}'
. '\x{89A9}\x{89AA}\x{89AC}\x{89AF}\x{89B2}\x{89B3}\x{89BA}\x{89BD}\x{89BF}'
. '\x{89C0}\x{89D2}\x{89DA}\x{89DC}\x{89DD}\x{89E3}\x{89E6}\x{89E7}\x{89F4}'
. '\x{89F8}\x{8A00}\x{8A02}\x{8A03}\x{8A08}\x{8A0A}\x{8A0C}\x{8A0E}\x{8A10}'
. '\x{8A13}\x{8A16}\x{8A17}\x{8A18}\x{8A1B}\x{8A1D}\x{8A1F}\x{8A23}\x{8A25}'
. '\x{8A2A}\x{8A2D}\x{8A31}\x{8A33}\x{8A34}\x{8A36}\x{8A3A}\x{8A3B}\x{8A3C}'
. '\x{8A41}\x{8A46}\x{8A48}\x{8A50}\x{8A51}\x{8A52}\x{8A54}\x{8A55}\x{8A5B}'
. '\x{8A5E}\x{8A60}\x{8A62}\x{8A63}\x{8A66}\x{8A69}\x{8A6B}\x{8A6C}\x{8A6D}'
. '\x{8A6E}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A7C}\x{8A82}\x{8A84}\x{8A85}'
. '\x{8A87}\x{8A89}\x{8A8C}\x{8A8D}\x{8A91}\x{8A93}\x{8A95}\x{8A98}\x{8A9A}'
. '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA8}\x{8AAC}'
. '\x{8AAD}\x{8AB0}\x{8AB2}\x{8AB9}\x{8ABC}\x{8ABF}\x{8AC2}\x{8AC4}\x{8AC7}'
. '\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACF}\x{8AD2}\x{8AD6}\x{8ADA}\x{8ADB}\x{8ADC}'
. '\x{8ADE}\x{8AE0}\x{8AE1}\x{8AE2}\x{8AE4}\x{8AE6}\x{8AE7}\x{8AEB}\x{8AED}'
. '\x{8AEE}\x{8AF1}\x{8AF3}\x{8AF7}\x{8AF8}\x{8AFA}\x{8AFE}\x{8B00}\x{8B01}'
. '\x{8B02}\x{8B04}\x{8B07}\x{8B0C}\x{8B0E}\x{8B10}\x{8B14}\x{8B16}\x{8B17}'
. '\x{8B19}\x{8B1A}\x{8B1B}\x{8B1D}\x{8B20}\x{8B21}\x{8B26}\x{8B28}\x{8B2B}'
. '\x{8B2C}\x{8B33}\x{8B39}\x{8B3E}\x{8B41}\x{8B49}\x{8B4C}\x{8B4E}\x{8B4F}'
. '\x{8B56}\x{8B58}\x{8B5A}\x{8B5B}\x{8B5C}\x{8B5F}\x{8B66}\x{8B6B}\x{8B6C}'
. '\x{8B6F}\x{8B70}\x{8B71}\x{8B72}\x{8B74}\x{8B77}\x{8B7D}\x{8B80}\x{8B83}'
. '\x{8B8A}\x{8B8C}\x{8B8E}\x{8B90}\x{8B92}\x{8B93}\x{8B96}\x{8B99}\x{8B9A}'
. '\x{8C37}\x{8C3A}\x{8C3F}\x{8C41}\x{8C46}\x{8C48}\x{8C4A}\x{8C4C}\x{8C4E}'
. '\x{8C50}\x{8C55}\x{8C5A}\x{8C61}\x{8C62}\x{8C6A}\x{8C6B}\x{8C6C}\x{8C78}'
. '\x{8C79}\x{8C7A}\x{8C7C}\x{8C82}\x{8C85}\x{8C89}\x{8C8A}\x{8C8C}\x{8C8D}'
. '\x{8C8E}\x{8C94}\x{8C98}\x{8C9D}\x{8C9E}\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA7}'
. '\x{8CA8}\x{8CA9}\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}'
. '\x{8CB2}\x{8CB3}\x{8CB4}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CBB}\x{8CBC}\x{8CBD}'
. '\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}\x{8CC7}\x{8CC8}\x{8CCA}'
. '\x{8CCD}\x{8CCE}\x{8CD1}\x{8CD3}\x{8CDA}\x{8CDB}\x{8CDC}\x{8CDE}\x{8CE0}'
. '\x{8CE2}\x{8CE3}\x{8CE4}\x{8CE6}\x{8CEA}\x{8CED}\x{8CFA}\x{8CFB}\x{8CFC}'
. '\x{8CFD}\x{8D04}\x{8D05}\x{8D07}\x{8D08}\x{8D0A}\x{8D0B}\x{8D0D}\x{8D0F}'
. '\x{8D10}\x{8D13}\x{8D14}\x{8D16}\x{8D64}\x{8D66}\x{8D67}\x{8D6B}\x{8D6D}'
. '\x{8D70}\x{8D71}\x{8D73}\x{8D74}\x{8D77}\x{8D81}\x{8D85}\x{8D8A}\x{8D99}'
. '\x{8DA3}\x{8DA8}\x{8DB3}\x{8DBA}\x{8DBE}\x{8DC2}\x{8DCB}\x{8DCC}\x{8DCF}'
. '\x{8DD6}\x{8DDA}\x{8DDB}\x{8DDD}\x{8DDF}\x{8DE1}\x{8DE3}\x{8DE8}\x{8DEA}'
. '\x{8DEB}\x{8DEF}\x{8DF3}\x{8DF5}\x{8DFC}\x{8DFF}\x{8E08}\x{8E09}\x{8E0A}'
. '\x{8E0F}\x{8E10}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E2A}\x{8E30}\x{8E34}\x{8E35}'
. '\x{8E42}\x{8E44}\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4C}\x{8E50}\x{8E55}'
. '\x{8E59}\x{8E5F}\x{8E60}\x{8E63}\x{8E64}\x{8E72}\x{8E74}\x{8E76}\x{8E7C}'
. '\x{8E81}\x{8E84}\x{8E85}\x{8E87}\x{8E8A}\x{8E8B}\x{8E8D}\x{8E91}\x{8E93}'
. '\x{8E94}\x{8E99}\x{8EA1}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAF}\x{8EB0}\x{8EB1}'
. '\x{8EBE}\x{8EC5}\x{8EC6}\x{8EC8}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ED2}'
. '\x{8EDB}\x{8EDF}\x{8EE2}\x{8EE3}\x{8EEB}\x{8EF8}\x{8EFB}\x{8EFC}\x{8EFD}'
. '\x{8EFE}\x{8F03}\x{8F05}\x{8F09}\x{8F0A}\x{8F0C}\x{8F12}\x{8F13}\x{8F14}'
. '\x{8F15}\x{8F19}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1F}\x{8F26}\x{8F29}\x{8F2A}'
. '\x{8F2F}\x{8F33}\x{8F38}\x{8F39}\x{8F3B}\x{8F3E}\x{8F3F}\x{8F42}\x{8F44}'
. '\x{8F45}\x{8F46}\x{8F49}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F57}\x{8F5C}\x{8F5F}'
. '\x{8F61}\x{8F62}\x{8F63}\x{8F64}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA3}'
. '\x{8FA7}\x{8FA8}\x{8FAD}\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB7}'
. '\x{8FBA}\x{8FBB}\x{8FBC}\x{8FBF}\x{8FC2}\x{8FC4}\x{8FC5}\x{8FCE}\x{8FD1}'
. '\x{8FD4}\x{8FDA}\x{8FE2}\x{8FE5}\x{8FE6}\x{8FE9}\x{8FEA}\x{8FEB}\x{8FED}'
. '\x{8FEF}\x{8FF0}\x{8FF4}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}\x{8FFD}\x{9000}'
. '\x{9001}\x{9003}\x{9005}\x{9006}\x{900B}\x{900D}\x{900E}\x{900F}\x{9010}'
. '\x{9011}\x{9013}\x{9014}\x{9015}\x{9016}\x{9017}\x{9019}\x{901A}\x{901D}'
. '\x{901E}\x{901F}\x{9020}\x{9021}\x{9022}\x{9023}\x{9027}\x{902E}\x{9031}'
. '\x{9032}\x{9035}\x{9036}\x{9038}\x{9039}\x{903C}\x{903E}\x{9041}\x{9042}'
. '\x{9045}\x{9047}\x{9049}\x{904A}\x{904B}\x{904D}\x{904E}\x{904F}\x{9050}'
. '\x{9051}\x{9052}\x{9053}\x{9054}\x{9055}\x{9056}\x{9058}\x{9059}\x{905C}'
. '\x{905E}\x{9060}\x{9061}\x{9063}\x{9065}\x{9068}\x{9069}\x{906D}\x{906E}'
. '\x{906F}\x{9072}\x{9075}\x{9076}\x{9077}\x{9078}\x{907A}\x{907C}\x{907D}'
. '\x{907F}\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9087}\x{9089}\x{908A}'
. '\x{908F}\x{9091}\x{90A3}\x{90A6}\x{90A8}\x{90AA}\x{90AF}\x{90B1}\x{90B5}'
. '\x{90B8}\x{90C1}\x{90CA}\x{90CE}\x{90DB}\x{90E1}\x{90E2}\x{90E4}\x{90E8}'
. '\x{90ED}\x{90F5}\x{90F7}\x{90FD}\x{9102}\x{9112}\x{9119}\x{912D}\x{9130}'
. '\x{9132}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}\x{914E}\x{9152}\x{9154}'
. '\x{9156}\x{9158}\x{9162}\x{9163}\x{9165}\x{9169}\x{916A}\x{916C}\x{9172}'
. '\x{9173}\x{9175}\x{9177}\x{9178}\x{9182}\x{9187}\x{9189}\x{918B}\x{918D}'
. '\x{9190}\x{9192}\x{9197}\x{919C}\x{91A2}\x{91A4}\x{91AA}\x{91AB}\x{91AF}'
. '\x{91B4}\x{91B5}\x{91B8}\x{91BA}\x{91C0}\x{91C1}\x{91C6}\x{91C7}\x{91C8}'
. '\x{91C9}\x{91CB}\x{91CC}\x{91CD}\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D6}'
. '\x{91D8}\x{91DB}\x{91DC}\x{91DD}\x{91DF}\x{91E1}\x{91E3}\x{91E6}\x{91E7}'
. '\x{91F5}\x{91F6}\x{91FC}\x{91FF}\x{920D}\x{920E}\x{9211}\x{9214}\x{9215}'
. '\x{921E}\x{9229}\x{922C}\x{9234}\x{9237}\x{923F}\x{9244}\x{9245}\x{9248}'
. '\x{9249}\x{924B}\x{9250}\x{9257}\x{925A}\x{925B}\x{925E}\x{9262}\x{9264}'
. '\x{9266}\x{9271}\x{927E}\x{9280}\x{9283}\x{9285}\x{9291}\x{9293}\x{9295}'
. '\x{9296}\x{9298}\x{929A}\x{929B}\x{929C}\x{92AD}\x{92B7}\x{92B9}\x{92CF}'
. '\x{92D2}\x{92E4}\x{92E9}\x{92EA}\x{92ED}\x{92F2}\x{92F3}\x{92F8}\x{92FA}'
. '\x{92FC}\x{9306}\x{930F}\x{9310}\x{9318}\x{9319}\x{931A}\x{9320}\x{9322}'
. '\x{9323}\x{9326}\x{9328}\x{932B}\x{932C}\x{932E}\x{932F}\x{9332}\x{9335}'
. '\x{933A}\x{933B}\x{9344}\x{934B}\x{934D}\x{9354}\x{9356}\x{935B}\x{935C}'
. '\x{9360}\x{936C}\x{936E}\x{9375}\x{937C}\x{937E}\x{938C}\x{9394}\x{9396}'
. '\x{9397}\x{939A}\x{93A7}\x{93AC}\x{93AD}\x{93AE}\x{93B0}\x{93B9}\x{93C3}'
. '\x{93C8}\x{93D0}\x{93D1}\x{93D6}\x{93D7}\x{93D8}\x{93DD}\x{93E1}\x{93E4}'
. '\x{93E5}\x{93E8}\x{9403}\x{9407}\x{9410}\x{9413}\x{9414}\x{9418}\x{9419}'
. '\x{941A}\x{9421}\x{942B}\x{9435}\x{9436}\x{9438}\x{943A}\x{9441}\x{9444}'
. '\x{9451}\x{9452}\x{9453}\x{945A}\x{945B}\x{945E}\x{9460}\x{9462}\x{946A}'
. '\x{9470}\x{9475}\x{9477}\x{947C}\x{947D}\x{947E}\x{947F}\x{9481}\x{9577}'
. '\x{9580}\x{9582}\x{9583}\x{9587}\x{9589}\x{958A}\x{958B}\x{958F}\x{9591}'
. '\x{9593}\x{9594}\x{9596}\x{9598}\x{9599}\x{95A0}\x{95A2}\x{95A3}\x{95A4}'
. '\x{95A5}\x{95A7}\x{95A8}\x{95AD}\x{95B2}\x{95B9}\x{95BB}\x{95BC}\x{95BE}'
. '\x{95C3}\x{95C7}\x{95CA}\x{95CC}\x{95CD}\x{95D4}\x{95D5}\x{95D6}\x{95D8}'
. '\x{95DC}\x{95E1}\x{95E2}\x{95E5}\x{961C}\x{9621}\x{9628}\x{962A}\x{962E}'
. '\x{962F}\x{9632}\x{963B}\x{963F}\x{9640}\x{9642}\x{9644}\x{964B}\x{964C}'
. '\x{964D}\x{964F}\x{9650}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9662}'
. '\x{9663}\x{9664}\x{9665}\x{9666}\x{966A}\x{966C}\x{9670}\x{9672}\x{9673}'
. '\x{9675}\x{9676}\x{9677}\x{9678}\x{967A}\x{967D}\x{9685}\x{9686}\x{9688}'
. '\x{968A}\x{968B}\x{968D}\x{968E}\x{968F}\x{9694}\x{9695}\x{9697}\x{9698}'
. '\x{9699}\x{969B}\x{969C}\x{96A0}\x{96A3}\x{96A7}\x{96A8}\x{96AA}\x{96B0}'
. '\x{96B1}\x{96B2}\x{96B4}\x{96B6}\x{96B7}\x{96B8}\x{96B9}\x{96BB}\x{96BC}'
. '\x{96C0}\x{96C1}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C9}\x{96CB}\x{96CC}'
. '\x{96CD}\x{96CE}\x{96D1}\x{96D5}\x{96D6}\x{96D9}\x{96DB}\x{96DC}\x{96E2}'
. '\x{96E3}\x{96E8}\x{96EA}\x{96EB}\x{96F0}\x{96F2}\x{96F6}\x{96F7}\x{96F9}'
. '\x{96FB}\x{9700}\x{9704}\x{9706}\x{9707}\x{9708}\x{970A}\x{970D}\x{970E}'
. '\x{970F}\x{9711}\x{9713}\x{9716}\x{9719}\x{971C}\x{971E}\x{9724}\x{9727}'
. '\x{972A}\x{9730}\x{9732}\x{9738}\x{9739}\x{973D}\x{973E}\x{9742}\x{9744}'
. '\x{9746}\x{9748}\x{9749}\x{9752}\x{9756}\x{9759}\x{975C}\x{975E}\x{9760}'
. '\x{9761}\x{9762}\x{9764}\x{9766}\x{9768}\x{9769}\x{976B}\x{976D}\x{9771}'
. '\x{9774}\x{9779}\x{977A}\x{977C}\x{9781}\x{9784}\x{9785}\x{9786}\x{978B}'
. '\x{978D}\x{978F}\x{9790}\x{9798}\x{979C}\x{97A0}\x{97A3}\x{97A6}\x{97A8}'
. '\x{97AB}\x{97AD}\x{97B3}\x{97B4}\x{97C3}\x{97C6}\x{97C8}\x{97CB}\x{97D3}'
. '\x{97DC}\x{97ED}\x{97EE}\x{97F2}\x{97F3}\x{97F5}\x{97F6}\x{97FB}\x{97FF}'
. '\x{9801}\x{9802}\x{9803}\x{9805}\x{9806}\x{9808}\x{980C}\x{980F}\x{9810}'
. '\x{9811}\x{9812}\x{9813}\x{9817}\x{9818}\x{981A}\x{9821}\x{9824}\x{982C}'
. '\x{982D}\x{9834}\x{9837}\x{9838}\x{983B}\x{983C}\x{983D}\x{9846}\x{984B}'
. '\x{984C}\x{984D}\x{984E}\x{984F}\x{9854}\x{9855}\x{9858}\x{985B}\x{985E}'
. '\x{9867}\x{986B}\x{986F}\x{9870}\x{9871}\x{9873}\x{9874}\x{98A8}\x{98AA}'
. '\x{98AF}\x{98B1}\x{98B6}\x{98C3}\x{98C4}\x{98C6}\x{98DB}\x{98DC}\x{98DF}'
. '\x{98E2}\x{98E9}\x{98EB}\x{98ED}\x{98EE}\x{98EF}\x{98F2}\x{98F4}\x{98FC}'
. '\x{98FD}\x{98FE}\x{9903}\x{9905}\x{9909}\x{990A}\x{990C}\x{9910}\x{9912}'
. '\x{9913}\x{9914}\x{9918}\x{991D}\x{991E}\x{9920}\x{9921}\x{9924}\x{9928}'
. '\x{992C}\x{992E}\x{993D}\x{993E}\x{9942}\x{9945}\x{9949}\x{994B}\x{994C}'
. '\x{9950}\x{9951}\x{9952}\x{9955}\x{9957}\x{9996}\x{9997}\x{9998}\x{9999}'
. '\x{99A5}\x{99A8}\x{99AC}\x{99AD}\x{99AE}\x{99B3}\x{99B4}\x{99BC}\x{99C1}'
. '\x{99C4}\x{99C5}\x{99C6}\x{99C8}\x{99D0}\x{99D1}\x{99D2}\x{99D5}\x{99D8}'
. '\x{99DB}\x{99DD}\x{99DF}\x{99E2}\x{99ED}\x{99EE}\x{99F1}\x{99F2}\x{99F8}'
. '\x{99FB}\x{99FF}\x{9A01}\x{9A05}\x{9A0E}\x{9A0F}\x{9A12}\x{9A13}\x{9A19}'
. '\x{9A28}\x{9A2B}\x{9A30}\x{9A37}\x{9A3E}\x{9A40}\x{9A42}\x{9A43}\x{9A45}'
. '\x{9A4D}\x{9A55}\x{9A57}\x{9A5A}\x{9A5B}\x{9A5F}\x{9A62}\x{9A64}\x{9A65}'
. '\x{9A69}\x{9A6A}\x{9A6B}\x{9AA8}\x{9AAD}\x{9AB0}\x{9AB8}\x{9ABC}\x{9AC0}'
. '\x{9AC4}\x{9ACF}\x{9AD1}\x{9AD3}\x{9AD4}\x{9AD8}\x{9ADE}\x{9ADF}\x{9AE2}'
. '\x{9AE3}\x{9AE6}\x{9AEA}\x{9AEB}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF4}'
. '\x{9AF7}\x{9AFB}\x{9B06}\x{9B18}\x{9B1A}\x{9B1F}\x{9B22}\x{9B23}\x{9B25}'
. '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2E}\x{9B2F}\x{9B31}\x{9B32}\x{9B3B}'
. '\x{9B3C}\x{9B41}\x{9B42}\x{9B43}\x{9B44}\x{9B45}\x{9B4D}\x{9B4E}\x{9B4F}'
. '\x{9B51}\x{9B54}\x{9B58}\x{9B5A}\x{9B6F}\x{9B74}\x{9B83}\x{9B8E}\x{9B91}'
. '\x{9B92}\x{9B93}\x{9B96}\x{9B97}\x{9B9F}\x{9BA0}\x{9BA8}\x{9BAA}\x{9BAB}'
. '\x{9BAD}\x{9BAE}\x{9BB4}\x{9BB9}\x{9BC0}\x{9BC6}\x{9BC9}\x{9BCA}\x{9BCF}'
. '\x{9BD1}\x{9BD2}\x{9BD4}\x{9BD6}\x{9BDB}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}'
. '\x{9BE8}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF5}\x{9C04}\x{9C06}\x{9C08}\x{9C09}'
. '\x{9C0A}\x{9C0C}\x{9C0D}\x{9C10}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C1B}'
. '\x{9C21}\x{9C24}\x{9C25}\x{9C2D}\x{9C2E}\x{9C2F}\x{9C30}\x{9C32}\x{9C39}'
. '\x{9C3A}\x{9C3B}\x{9C3E}\x{9C46}\x{9C47}\x{9C48}\x{9C52}\x{9C57}\x{9C5A}'
. '\x{9C60}\x{9C67}\x{9C76}\x{9C78}\x{9CE5}\x{9CE7}\x{9CE9}\x{9CEB}\x{9CEC}'
. '\x{9CF0}\x{9CF3}\x{9CF4}\x{9CF6}\x{9D03}\x{9D06}\x{9D07}\x{9D08}\x{9D09}'
. '\x{9D0E}\x{9D12}\x{9D15}\x{9D1B}\x{9D1F}\x{9D23}\x{9D26}\x{9D28}\x{9D2A}'
. '\x{9D2B}\x{9D2C}\x{9D3B}\x{9D3E}\x{9D3F}\x{9D41}\x{9D44}\x{9D46}\x{9D48}'
. '\x{9D50}\x{9D51}\x{9D59}\x{9D5C}\x{9D5D}\x{9D5E}\x{9D60}\x{9D61}\x{9D64}'
. '\x{9D6C}\x{9D6F}\x{9D72}\x{9D7A}\x{9D87}\x{9D89}\x{9D8F}\x{9D9A}\x{9DA4}'
. '\x{9DA9}\x{9DAB}\x{9DAF}\x{9DB2}\x{9DB4}\x{9DB8}\x{9DBA}\x{9DBB}\x{9DC1}'
. '\x{9DC2}\x{9DC4}\x{9DC6}\x{9DCF}\x{9DD3}\x{9DD9}\x{9DE6}\x{9DED}\x{9DEF}'
. '\x{9DF2}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFD}\x{9E1A}\x{9E1B}\x{9E1E}\x{9E75}'
. '\x{9E78}\x{9E79}\x{9E7D}\x{9E7F}\x{9E81}\x{9E88}\x{9E8B}\x{9E8C}\x{9E91}'
. '\x{9E92}\x{9E93}\x{9E95}\x{9E97}\x{9E9D}\x{9E9F}\x{9EA5}\x{9EA6}\x{9EA9}'
. '\x{9EAA}\x{9EAD}\x{9EB8}\x{9EB9}\x{9EBA}\x{9EBB}\x{9EBC}\x{9EBE}\x{9EBF}'
. '\x{9EC4}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED2}\x{9ED4}\x{9ED8}'
. '\x{9ED9}\x{9EDB}\x{9EDC}\x{9EDD}\x{9EDE}\x{9EE0}\x{9EE5}\x{9EE8}\x{9EEF}'
. '\x{9EF4}\x{9EF6}\x{9EF7}\x{9EF9}\x{9EFB}\x{9EFC}\x{9EFD}\x{9F07}\x{9F08}'
. '\x{9F0E}\x{9F13}\x{9F15}\x{9F20}\x{9F21}\x{9F2C}\x{9F3B}\x{9F3E}\x{9F4A}'
. '\x{9F4B}\x{9F4E}\x{9F4F}\x{9F52}\x{9F54}\x{9F5F}\x{9F60}\x{9F61}\x{9F62}'
. '\x{9F63}\x{9F66}\x{9F67}\x{9F6A}\x{9F6C}\x{9F72}\x{9F76}\x{9F77}\x{9F8D}'
. '\x{9F95}\x{9F9C}\x{9F9D}\x{9FA0}]{1,15}$/iu',
];
laminas-validator/src/Hostname/Cn.php 0000644 00000560727 15240152635 0013615 0 ustar 00 <?php // phpcs:disable PSR12.Files.FileHeader.IncorrectOrder
namespace Laminas\Validator\Hostname;
/**
* Resource file for chinese idn validation
*/
return [
1 => '/^[\x{002d}0-9a-z\x{3447}\x{3473}\x{359E}\x{360E}\x{361A}\x{3918}\x{396E}\x{39CF}\x{39D0}'
. '\x{39DF}\x{3A73}\x{3B4E}\x{3C6E}\x{3CE0}\x{4056}\x{415F}\x{4337}\x{43AC}'
. '\x{43B1}\x{43DD}\x{44D6}\x{464C}\x{4661}\x{4723}\x{4729}\x{477C}\x{478D}'
. '\x{4947}\x{497A}\x{497D}\x{4982}\x{4983}\x{4985}\x{4986}\x{499B}\x{499F}'
. '\x{49B6}\x{49B7}\x{4C77}\x{4C9F}\x{4CA0}\x{4CA1}\x{4CA2}\x{4CA3}\x{4D13}'
. '\x{4D14}\x{4D15}\x{4D16}\x{4D17}\x{4D18}\x{4D19}\x{4DAE}\x{4E00}\x{4E01}'
. '\x{4E02}\x{4E03}\x{4E04}\x{4E05}\x{4E06}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}'
. '\x{4E0B}\x{4E0C}\x{4E0D}\x{4E0E}\x{4E0F}\x{4E10}\x{4E11}\x{4E13}\x{4E14}'
. '\x{4E15}\x{4E16}\x{4E17}\x{4E18}\x{4E19}\x{4E1A}\x{4E1B}\x{4E1C}\x{4E1D}'
. '\x{4E1E}\x{4E1F}\x{4E20}\x{4E21}\x{4E22}\x{4E23}\x{4E24}\x{4E25}\x{4E26}'
. '\x{4E27}\x{4E28}\x{4E2A}\x{4E2B}\x{4E2C}\x{4E2D}\x{4E2E}\x{4E2F}\x{4E30}'
. '\x{4E31}\x{4E32}\x{4E33}\x{4E34}\x{4E35}\x{4E36}\x{4E37}\x{4E38}\x{4E39}'
. '\x{4E3A}\x{4E3B}\x{4E3C}\x{4E3D}\x{4E3E}\x{4E3F}\x{4E40}\x{4E41}\x{4E42}'
. '\x{4E43}\x{4E44}\x{4E45}\x{4E46}\x{4E47}\x{4E48}\x{4E49}\x{4E4A}\x{4E4B}'
. '\x{4E4C}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E50}\x{4E51}\x{4E52}\x{4E53}\x{4E54}'
. '\x{4E56}\x{4E57}\x{4E58}\x{4E59}\x{4E5A}\x{4E5B}\x{4E5C}\x{4E5D}\x{4E5E}'
. '\x{4E5F}\x{4E60}\x{4E61}\x{4E62}\x{4E63}\x{4E64}\x{4E65}\x{4E66}\x{4E67}'
. '\x{4E69}\x{4E6A}\x{4E6B}\x{4E6C}\x{4E6D}\x{4E6E}\x{4E6F}\x{4E70}\x{4E71}'
. '\x{4E72}\x{4E73}\x{4E74}\x{4E75}\x{4E76}\x{4E77}\x{4E78}\x{4E7A}\x{4E7B}'
. '\x{4E7C}\x{4E7D}\x{4E7E}\x{4E7F}\x{4E80}\x{4E81}\x{4E82}\x{4E83}\x{4E84}'
. '\x{4E85}\x{4E86}\x{4E87}\x{4E88}\x{4E89}\x{4E8B}\x{4E8C}\x{4E8D}\x{4E8E}'
. '\x{4E8F}\x{4E90}\x{4E91}\x{4E92}\x{4E93}\x{4E94}\x{4E95}\x{4E97}\x{4E98}'
. '\x{4E99}\x{4E9A}\x{4E9B}\x{4E9C}\x{4E9D}\x{4E9E}\x{4E9F}\x{4EA0}\x{4EA1}'
. '\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA7}\x{4EA8}\x{4EA9}\x{4EAA}\x{4EAB}'
. '\x{4EAC}\x{4EAD}\x{4EAE}\x{4EAF}\x{4EB0}\x{4EB1}\x{4EB2}\x{4EB3}\x{4EB4}'
. '\x{4EB5}\x{4EB6}\x{4EB7}\x{4EB8}\x{4EB9}\x{4EBA}\x{4EBB}\x{4EBD}\x{4EBE}'
. '\x{4EBF}\x{4EC0}\x{4EC1}\x{4EC2}\x{4EC3}\x{4EC4}\x{4EC5}\x{4EC6}\x{4EC7}'
. '\x{4EC8}\x{4EC9}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED0}\x{4ED1}'
. '\x{4ED2}\x{4ED3}\x{4ED4}\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDA}'
. '\x{4EDB}\x{4EDC}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE0}\x{4EE1}\x{4EE2}\x{4EE3}'
. '\x{4EE4}\x{4EE5}\x{4EE6}\x{4EE8}\x{4EE9}\x{4EEA}\x{4EEB}\x{4EEC}\x{4EEF}'
. '\x{4EF0}\x{4EF1}\x{4EF2}\x{4EF3}\x{4EF4}\x{4EF5}\x{4EF6}\x{4EF7}\x{4EFB}'
. '\x{4EFD}\x{4EFF}\x{4F00}\x{4F01}\x{4F02}\x{4F03}\x{4F04}\x{4F05}\x{4F06}'
. '\x{4F08}\x{4F09}\x{4F0A}\x{4F0B}\x{4F0C}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}'
. '\x{4F11}\x{4F12}\x{4F13}\x{4F14}\x{4F15}\x{4F17}\x{4F18}\x{4F19}\x{4F1A}'
. '\x{4F1B}\x{4F1C}\x{4F1D}\x{4F1E}\x{4F1F}\x{4F20}\x{4F21}\x{4F22}\x{4F23}'
. '\x{4F24}\x{4F25}\x{4F26}\x{4F27}\x{4F29}\x{4F2A}\x{4F2B}\x{4F2C}\x{4F2D}'
. '\x{4F2E}\x{4F2F}\x{4F30}\x{4F32}\x{4F33}\x{4F34}\x{4F36}\x{4F38}\x{4F39}'
. '\x{4F3A}\x{4F3B}\x{4F3C}\x{4F3D}\x{4F3E}\x{4F3F}\x{4F41}\x{4F42}\x{4F43}'
. '\x{4F45}\x{4F46}\x{4F47}\x{4F48}\x{4F49}\x{4F4A}\x{4F4B}\x{4F4C}\x{4F4D}'
. '\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}\x{4F52}\x{4F53}\x{4F54}\x{4F55}\x{4F56}'
. '\x{4F57}\x{4F58}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}\x{4F5F}'
. '\x{4F60}\x{4F61}\x{4F62}\x{4F63}\x{4F64}\x{4F65}\x{4F66}\x{4F67}\x{4F68}'
. '\x{4F69}\x{4F6A}\x{4F6B}\x{4F6C}\x{4F6D}\x{4F6E}\x{4F6F}\x{4F70}\x{4F72}'
. '\x{4F73}\x{4F74}\x{4F75}\x{4F76}\x{4F77}\x{4F78}\x{4F79}\x{4F7A}\x{4F7B}'
. '\x{4F7C}\x{4F7D}\x{4F7E}\x{4F7F}\x{4F80}\x{4F81}\x{4F82}\x{4F83}\x{4F84}'
. '\x{4F85}\x{4F86}\x{4F87}\x{4F88}\x{4F89}\x{4F8A}\x{4F8B}\x{4F8D}\x{4F8F}'
. '\x{4F90}\x{4F91}\x{4F92}\x{4F93}\x{4F94}\x{4F95}\x{4F96}\x{4F97}\x{4F98}'
. '\x{4F99}\x{4F9A}\x{4F9B}\x{4F9C}\x{4F9D}\x{4F9E}\x{4F9F}\x{4FA0}\x{4FA1}'
. '\x{4FA3}\x{4FA4}\x{4FA5}\x{4FA6}\x{4FA7}\x{4FA8}\x{4FA9}\x{4FAA}\x{4FAB}'
. '\x{4FAC}\x{4FAE}\x{4FAF}\x{4FB0}\x{4FB1}\x{4FB2}\x{4FB3}\x{4FB4}\x{4FB5}'
. '\x{4FB6}\x{4FB7}\x{4FB8}\x{4FB9}\x{4FBA}\x{4FBB}\x{4FBC}\x{4FBE}\x{4FBF}'
. '\x{4FC0}\x{4FC1}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FC5}\x{4FC7}\x{4FC9}\x{4FCA}'
. '\x{4FCB}\x{4FCD}\x{4FCE}\x{4FCF}\x{4FD0}\x{4FD1}\x{4FD2}\x{4FD3}\x{4FD4}'
. '\x{4FD5}\x{4FD6}\x{4FD7}\x{4FD8}\x{4FD9}\x{4FDA}\x{4FDB}\x{4FDC}\x{4FDD}'
. '\x{4FDE}\x{4FDF}\x{4FE0}\x{4FE1}\x{4FE3}\x{4FE4}\x{4FE5}\x{4FE6}\x{4FE7}'
. '\x{4FE8}\x{4FE9}\x{4FEA}\x{4FEB}\x{4FEC}\x{4FED}\x{4FEE}\x{4FEF}\x{4FF0}'
. '\x{4FF1}\x{4FF2}\x{4FF3}\x{4FF4}\x{4FF5}\x{4FF6}\x{4FF7}\x{4FF8}\x{4FF9}'
. '\x{4FFA}\x{4FFB}\x{4FFE}\x{4FFF}\x{5000}\x{5001}\x{5002}\x{5003}\x{5004}'
. '\x{5005}\x{5006}\x{5007}\x{5008}\x{5009}\x{500A}\x{500B}\x{500C}\x{500D}'
. '\x{500E}\x{500F}\x{5011}\x{5012}\x{5013}\x{5014}\x{5015}\x{5016}\x{5017}'
. '\x{5018}\x{5019}\x{501A}\x{501B}\x{501C}\x{501D}\x{501E}\x{501F}\x{5020}'
. '\x{5021}\x{5022}\x{5023}\x{5024}\x{5025}\x{5026}\x{5027}\x{5028}\x{5029}'
. '\x{502A}\x{502B}\x{502C}\x{502D}\x{502E}\x{502F}\x{5030}\x{5031}\x{5032}'
. '\x{5033}\x{5035}\x{5036}\x{5037}\x{5039}\x{503A}\x{503B}\x{503C}\x{503E}'
. '\x{503F}\x{5040}\x{5041}\x{5043}\x{5044}\x{5045}\x{5046}\x{5047}\x{5048}'
. '\x{5049}\x{504A}\x{504B}\x{504C}\x{504D}\x{504E}\x{504F}\x{5051}\x{5053}'
. '\x{5054}\x{5055}\x{5056}\x{5057}\x{5059}\x{505A}\x{505B}\x{505C}\x{505D}'
. '\x{505E}\x{505F}\x{5060}\x{5061}\x{5062}\x{5063}\x{5064}\x{5065}\x{5066}'
. '\x{5067}\x{5068}\x{5069}\x{506A}\x{506B}\x{506C}\x{506D}\x{506E}\x{506F}'
. '\x{5070}\x{5071}\x{5072}\x{5073}\x{5074}\x{5075}\x{5076}\x{5077}\x{5078}'
. '\x{5079}\x{507A}\x{507B}\x{507D}\x{507E}\x{507F}\x{5080}\x{5082}\x{5083}'
. '\x{5084}\x{5085}\x{5086}\x{5087}\x{5088}\x{5089}\x{508A}\x{508B}\x{508C}'
. '\x{508D}\x{508E}\x{508F}\x{5090}\x{5091}\x{5092}\x{5094}\x{5095}\x{5096}'
. '\x{5098}\x{5099}\x{509A}\x{509B}\x{509C}\x{509D}\x{509E}\x{50A2}\x{50A3}'
. '\x{50A4}\x{50A5}\x{50A6}\x{50A7}\x{50A8}\x{50A9}\x{50AA}\x{50AB}\x{50AC}'
. '\x{50AD}\x{50AE}\x{50AF}\x{50B0}\x{50B1}\x{50B2}\x{50B3}\x{50B4}\x{50B5}'
. '\x{50B6}\x{50B7}\x{50B8}\x{50BA}\x{50BB}\x{50BC}\x{50BD}\x{50BE}\x{50BF}'
. '\x{50C0}\x{50C1}\x{50C2}\x{50C4}\x{50C5}\x{50C6}\x{50C7}\x{50C8}\x{50C9}'
. '\x{50CA}\x{50CB}\x{50CC}\x{50CD}\x{50CE}\x{50CF}\x{50D0}\x{50D1}\x{50D2}'
. '\x{50D3}\x{50D4}\x{50D5}\x{50D6}\x{50D7}\x{50D9}\x{50DA}\x{50DB}\x{50DC}'
. '\x{50DD}\x{50DE}\x{50E0}\x{50E3}\x{50E4}\x{50E5}\x{50E6}\x{50E7}\x{50E8}'
. '\x{50E9}\x{50EA}\x{50EC}\x{50ED}\x{50EE}\x{50EF}\x{50F0}\x{50F1}\x{50F2}'
. '\x{50F3}\x{50F5}\x{50F6}\x{50F8}\x{50F9}\x{50FA}\x{50FB}\x{50FC}\x{50FD}'
. '\x{50FE}\x{50FF}\x{5100}\x{5101}\x{5102}\x{5103}\x{5104}\x{5105}\x{5106}'
. '\x{5107}\x{5108}\x{5109}\x{510A}\x{510B}\x{510C}\x{510D}\x{510E}\x{510F}'
. '\x{5110}\x{5111}\x{5112}\x{5113}\x{5114}\x{5115}\x{5116}\x{5117}\x{5118}'
. '\x{5119}\x{511A}\x{511C}\x{511D}\x{511E}\x{511F}\x{5120}\x{5121}\x{5122}'
. '\x{5123}\x{5124}\x{5125}\x{5126}\x{5127}\x{5129}\x{512A}\x{512C}\x{512D}'
. '\x{512E}\x{512F}\x{5130}\x{5131}\x{5132}\x{5133}\x{5134}\x{5135}\x{5136}'
. '\x{5137}\x{5138}\x{5139}\x{513A}\x{513B}\x{513C}\x{513D}\x{513E}\x{513F}'
. '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}'
. '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5151}\x{5152}\x{5154}\x{5155}'
. '\x{5156}\x{5157}\x{5159}\x{515A}\x{515B}\x{515C}\x{515D}\x{515E}\x{515F}'
. '\x{5161}\x{5162}\x{5163}\x{5165}\x{5166}\x{5167}\x{5168}\x{5169}\x{516A}'
. '\x{516B}\x{516C}\x{516D}\x{516E}\x{516F}\x{5170}\x{5171}\x{5173}\x{5174}'
. '\x{5175}\x{5176}\x{5177}\x{5178}\x{5179}\x{517A}\x{517B}\x{517C}\x{517D}'
. '\x{517F}\x{5180}\x{5181}\x{5182}\x{5185}\x{5186}\x{5187}\x{5188}\x{5189}'
. '\x{518A}\x{518B}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}\x{5193}'
. '\x{5194}\x{5195}\x{5196}\x{5197}\x{5198}\x{5199}\x{519A}\x{519B}\x{519C}'
. '\x{519D}\x{519E}\x{519F}\x{51A0}\x{51A2}\x{51A4}\x{51A5}\x{51A6}\x{51A7}'
. '\x{51A8}\x{51AA}\x{51AB}\x{51AC}\x{51AE}\x{51AF}\x{51B0}\x{51B1}\x{51B2}'
. '\x{51B3}\x{51B5}\x{51B6}\x{51B7}\x{51B9}\x{51BB}\x{51BC}\x{51BD}\x{51BE}'
. '\x{51BF}\x{51C0}\x{51C1}\x{51C3}\x{51C4}\x{51C5}\x{51C6}\x{51C7}\x{51C8}'
. '\x{51C9}\x{51CA}\x{51CB}\x{51CC}\x{51CD}\x{51CE}\x{51CF}\x{51D0}\x{51D1}'
. '\x{51D4}\x{51D5}\x{51D6}\x{51D7}\x{51D8}\x{51D9}\x{51DA}\x{51DB}\x{51DC}'
. '\x{51DD}\x{51DE}\x{51E0}\x{51E1}\x{51E2}\x{51E3}\x{51E4}\x{51E5}\x{51E7}'
. '\x{51E8}\x{51E9}\x{51EA}\x{51EB}\x{51ED}\x{51EF}\x{51F0}\x{51F1}\x{51F3}'
. '\x{51F4}\x{51F5}\x{51F6}\x{51F7}\x{51F8}\x{51F9}\x{51FA}\x{51FB}\x{51FC}'
. '\x{51FD}\x{51FE}\x{51FF}\x{5200}\x{5201}\x{5202}\x{5203}\x{5204}\x{5205}'
. '\x{5206}\x{5207}\x{5208}\x{5209}\x{520A}\x{520B}\x{520C}\x{520D}\x{520E}'
. '\x{520F}\x{5210}\x{5211}\x{5212}\x{5213}\x{5214}\x{5215}\x{5216}\x{5217}'
. '\x{5218}\x{5219}\x{521A}\x{521B}\x{521C}\x{521D}\x{521E}\x{521F}\x{5220}'
. '\x{5221}\x{5222}\x{5223}\x{5224}\x{5225}\x{5226}\x{5228}\x{5229}\x{522A}'
. '\x{522B}\x{522C}\x{522D}\x{522E}\x{522F}\x{5230}\x{5231}\x{5232}\x{5233}'
. '\x{5234}\x{5235}\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{523C}'
. '\x{523D}\x{523E}\x{523F}\x{5240}\x{5241}\x{5242}\x{5243}\x{5244}\x{5245}'
. '\x{5246}\x{5247}\x{5248}\x{5249}\x{524A}\x{524B}\x{524C}\x{524D}\x{524E}'
. '\x{5250}\x{5251}\x{5252}\x{5254}\x{5255}\x{5256}\x{5257}\x{5258}\x{5259}'
. '\x{525A}\x{525B}\x{525C}\x{525D}\x{525E}\x{525F}\x{5260}\x{5261}\x{5262}'
. '\x{5263}\x{5264}\x{5265}\x{5267}\x{5268}\x{5269}\x{526A}\x{526B}\x{526C}'
. '\x{526D}\x{526E}\x{526F}\x{5270}\x{5272}\x{5273}\x{5274}\x{5275}\x{5276}'
. '\x{5277}\x{5278}\x{527A}\x{527B}\x{527C}\x{527D}\x{527E}\x{527F}\x{5280}'
. '\x{5281}\x{5282}\x{5283}\x{5284}\x{5286}\x{5287}\x{5288}\x{5289}\x{528A}'
. '\x{528B}\x{528C}\x{528D}\x{528F}\x{5290}\x{5291}\x{5292}\x{5293}\x{5294}'
. '\x{5295}\x{5296}\x{5297}\x{5298}\x{5299}\x{529A}\x{529B}\x{529C}\x{529D}'
. '\x{529E}\x{529F}\x{52A0}\x{52A1}\x{52A2}\x{52A3}\x{52A5}\x{52A6}\x{52A7}'
. '\x{52A8}\x{52A9}\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52AE}\x{52AF}\x{52B0}'
. '\x{52B1}\x{52B2}\x{52B3}\x{52B4}\x{52B5}\x{52B6}\x{52B7}\x{52B8}\x{52B9}'
. '\x{52BA}\x{52BB}\x{52BC}\x{52BD}\x{52BE}\x{52BF}\x{52C0}\x{52C1}\x{52C2}'
. '\x{52C3}\x{52C6}\x{52C7}\x{52C9}\x{52CA}\x{52CB}\x{52CD}\x{52CF}\x{52D0}'
. '\x{52D2}\x{52D3}\x{52D5}\x{52D6}\x{52D7}\x{52D8}\x{52D9}\x{52DA}\x{52DB}'
. '\x{52DC}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}\x{52E4}\x{52E6}'
. '\x{52E7}\x{52E8}\x{52E9}\x{52EA}\x{52EB}\x{52EC}\x{52ED}\x{52EF}\x{52F0}'
. '\x{52F1}\x{52F2}\x{52F3}\x{52F4}\x{52F5}\x{52F6}\x{52F7}\x{52F8}\x{52F9}'
. '\x{52FA}\x{52FB}\x{52FC}\x{52FD}\x{52FE}\x{52FF}\x{5300}\x{5301}\x{5302}'
. '\x{5305}\x{5306}\x{5307}\x{5308}\x{5309}\x{530A}\x{530B}\x{530C}\x{530D}'
. '\x{530E}\x{530F}\x{5310}\x{5311}\x{5312}\x{5313}\x{5314}\x{5315}\x{5316}'
. '\x{5317}\x{5319}\x{531A}\x{531C}\x{531D}\x{531F}\x{5320}\x{5321}\x{5322}'
. '\x{5323}\x{5324}\x{5325}\x{5326}\x{5328}\x{532A}\x{532B}\x{532C}\x{532D}'
. '\x{532E}\x{532F}\x{5330}\x{5331}\x{5333}\x{5334}\x{5337}\x{5339}\x{533A}'
. '\x{533B}\x{533C}\x{533D}\x{533E}\x{533F}\x{5340}\x{5341}\x{5343}\x{5344}'
. '\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}\x{534A}\x{534B}\x{534C}\x{534D}'
. '\x{534E}\x{534F}\x{5350}\x{5351}\x{5352}\x{5353}\x{5354}\x{5355}\x{5356}'
. '\x{5357}\x{5358}\x{5359}\x{535A}\x{535C}\x{535E}\x{535F}\x{5360}\x{5361}'
. '\x{5362}\x{5363}\x{5364}\x{5365}\x{5366}\x{5367}\x{5369}\x{536B}\x{536C}'
. '\x{536E}\x{536F}\x{5370}\x{5371}\x{5372}\x{5373}\x{5374}\x{5375}\x{5376}'
. '\x{5377}\x{5378}\x{5379}\x{537A}\x{537B}\x{537C}\x{537D}\x{537E}\x{537F}'
. '\x{5381}\x{5382}\x{5383}\x{5384}\x{5385}\x{5386}\x{5387}\x{5388}\x{5389}'
. '\x{538A}\x{538B}\x{538C}\x{538D}\x{538E}\x{538F}\x{5390}\x{5391}\x{5392}'
. '\x{5393}\x{5394}\x{5395}\x{5396}\x{5397}\x{5398}\x{5399}\x{539A}\x{539B}'
. '\x{539C}\x{539D}\x{539E}\x{539F}\x{53A0}\x{53A2}\x{53A3}\x{53A4}\x{53A5}'
. '\x{53A6}\x{53A7}\x{53A8}\x{53A9}\x{53AC}\x{53AD}\x{53AE}\x{53B0}\x{53B1}'
. '\x{53B2}\x{53B3}\x{53B4}\x{53B5}\x{53B6}\x{53B7}\x{53B8}\x{53B9}\x{53BB}'
. '\x{53BC}\x{53BD}\x{53BE}\x{53BF}\x{53C0}\x{53C1}\x{53C2}\x{53C3}\x{53C4}'
. '\x{53C6}\x{53C7}\x{53C8}\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}'
. '\x{53D0}\x{53D1}\x{53D2}\x{53D3}\x{53D4}\x{53D5}\x{53D6}\x{53D7}\x{53D8}'
. '\x{53D9}\x{53DB}\x{53DC}\x{53DF}\x{53E0}\x{53E1}\x{53E2}\x{53E3}\x{53E4}'
. '\x{53E5}\x{53E6}\x{53E8}\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}'
. '\x{53EF}\x{53F0}\x{53F1}\x{53F2}\x{53F3}\x{53F4}\x{53F5}\x{53F6}\x{53F7}'
. '\x{53F8}\x{53F9}\x{53FA}\x{53FB}\x{53FC}\x{53FD}\x{53FE}\x{5401}\x{5402}'
. '\x{5403}\x{5404}\x{5405}\x{5406}\x{5407}\x{5408}\x{5409}\x{540A}\x{540B}'
. '\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}\x{5411}\x{5412}\x{5413}\x{5414}'
. '\x{5415}\x{5416}\x{5417}\x{5418}\x{5419}\x{541B}\x{541C}\x{541D}\x{541E}'
. '\x{541F}\x{5420}\x{5421}\x{5423}\x{5424}\x{5425}\x{5426}\x{5427}\x{5428}'
. '\x{5429}\x{542A}\x{542B}\x{542C}\x{542D}\x{542E}\x{542F}\x{5430}\x{5431}'
. '\x{5432}\x{5433}\x{5434}\x{5435}\x{5436}\x{5437}\x{5438}\x{5439}\x{543A}'
. '\x{543B}\x{543C}\x{543D}\x{543E}\x{543F}\x{5440}\x{5441}\x{5442}\x{5443}'
. '\x{5444}\x{5445}\x{5446}\x{5447}\x{5448}\x{5449}\x{544A}\x{544B}\x{544D}'
. '\x{544E}\x{544F}\x{5450}\x{5451}\x{5452}\x{5453}\x{5454}\x{5455}\x{5456}'
. '\x{5457}\x{5458}\x{5459}\x{545A}\x{545B}\x{545C}\x{545E}\x{545F}\x{5460}'
. '\x{5461}\x{5462}\x{5463}\x{5464}\x{5465}\x{5466}\x{5467}\x{5468}\x{546A}'
. '\x{546B}\x{546C}\x{546D}\x{546E}\x{546F}\x{5470}\x{5471}\x{5472}\x{5473}'
. '\x{5474}\x{5475}\x{5476}\x{5477}\x{5478}\x{5479}\x{547A}\x{547B}\x{547C}'
. '\x{547D}\x{547E}\x{547F}\x{5480}\x{5481}\x{5482}\x{5483}\x{5484}\x{5485}'
. '\x{5486}\x{5487}\x{5488}\x{5489}\x{548B}\x{548C}\x{548D}\x{548E}\x{548F}'
. '\x{5490}\x{5491}\x{5492}\x{5493}\x{5494}\x{5495}\x{5496}\x{5497}\x{5498}'
. '\x{5499}\x{549A}\x{549B}\x{549C}\x{549D}\x{549E}\x{549F}\x{54A0}\x{54A1}'
. '\x{54A2}\x{54A3}\x{54A4}\x{54A5}\x{54A6}\x{54A7}\x{54A8}\x{54A9}\x{54AA}'
. '\x{54AB}\x{54AC}\x{54AD}\x{54AE}\x{54AF}\x{54B0}\x{54B1}\x{54B2}\x{54B3}'
. '\x{54B4}\x{54B6}\x{54B7}\x{54B8}\x{54B9}\x{54BA}\x{54BB}\x{54BC}\x{54BD}'
. '\x{54BE}\x{54BF}\x{54C0}\x{54C1}\x{54C2}\x{54C3}\x{54C4}\x{54C5}\x{54C6}'
. '\x{54C7}\x{54C8}\x{54C9}\x{54CA}\x{54CB}\x{54CC}\x{54CD}\x{54CE}\x{54CF}'
. '\x{54D0}\x{54D1}\x{54D2}\x{54D3}\x{54D4}\x{54D5}\x{54D6}\x{54D7}\x{54D8}'
. '\x{54D9}\x{54DA}\x{54DB}\x{54DC}\x{54DD}\x{54DE}\x{54DF}\x{54E0}\x{54E1}'
. '\x{54E2}\x{54E3}\x{54E4}\x{54E5}\x{54E6}\x{54E7}\x{54E8}\x{54E9}\x{54EA}'
. '\x{54EB}\x{54EC}\x{54ED}\x{54EE}\x{54EF}\x{54F0}\x{54F1}\x{54F2}\x{54F3}'
. '\x{54F4}\x{54F5}\x{54F7}\x{54F8}\x{54F9}\x{54FA}\x{54FB}\x{54FC}\x{54FD}'
. '\x{54FE}\x{54FF}\x{5500}\x{5501}\x{5502}\x{5503}\x{5504}\x{5505}\x{5506}'
. '\x{5507}\x{5508}\x{5509}\x{550A}\x{550B}\x{550C}\x{550D}\x{550E}\x{550F}'
. '\x{5510}\x{5511}\x{5512}\x{5513}\x{5514}\x{5516}\x{5517}\x{551A}\x{551B}'
. '\x{551C}\x{551D}\x{551E}\x{551F}\x{5520}\x{5521}\x{5522}\x{5523}\x{5524}'
. '\x{5525}\x{5526}\x{5527}\x{5528}\x{5529}\x{552A}\x{552B}\x{552C}\x{552D}'
. '\x{552E}\x{552F}\x{5530}\x{5531}\x{5532}\x{5533}\x{5534}\x{5535}\x{5536}'
. '\x{5537}\x{5538}\x{5539}\x{553A}\x{553B}\x{553C}\x{553D}\x{553E}\x{553F}'
. '\x{5540}\x{5541}\x{5542}\x{5543}\x{5544}\x{5545}\x{5546}\x{5548}\x{5549}'
. '\x{554A}\x{554B}\x{554C}\x{554D}\x{554E}\x{554F}\x{5550}\x{5551}\x{5552}'
. '\x{5553}\x{5554}\x{5555}\x{5556}\x{5557}\x{5558}\x{5559}\x{555A}\x{555B}'
. '\x{555C}\x{555D}\x{555E}\x{555F}\x{5561}\x{5562}\x{5563}\x{5564}\x{5565}'
. '\x{5566}\x{5567}\x{5568}\x{5569}\x{556A}\x{556B}\x{556C}\x{556D}\x{556E}'
. '\x{556F}\x{5570}\x{5571}\x{5572}\x{5573}\x{5574}\x{5575}\x{5576}\x{5577}'
. '\x{5578}\x{5579}\x{557B}\x{557C}\x{557D}\x{557E}\x{557F}\x{5580}\x{5581}'
. '\x{5582}\x{5583}\x{5584}\x{5585}\x{5586}\x{5587}\x{5588}\x{5589}\x{558A}'
. '\x{558B}\x{558C}\x{558D}\x{558E}\x{558F}\x{5590}\x{5591}\x{5592}\x{5593}'
. '\x{5594}\x{5595}\x{5596}\x{5597}\x{5598}\x{5599}\x{559A}\x{559B}\x{559C}'
. '\x{559D}\x{559E}\x{559F}\x{55A0}\x{55A1}\x{55A2}\x{55A3}\x{55A4}\x{55A5}'
. '\x{55A6}\x{55A7}\x{55A8}\x{55A9}\x{55AA}\x{55AB}\x{55AC}\x{55AD}\x{55AE}'
. '\x{55AF}\x{55B0}\x{55B1}\x{55B2}\x{55B3}\x{55B4}\x{55B5}\x{55B6}\x{55B7}'
. '\x{55B8}\x{55B9}\x{55BA}\x{55BB}\x{55BC}\x{55BD}\x{55BE}\x{55BF}\x{55C0}'
. '\x{55C1}\x{55C2}\x{55C3}\x{55C4}\x{55C5}\x{55C6}\x{55C7}\x{55C8}\x{55C9}'
. '\x{55CA}\x{55CB}\x{55CC}\x{55CD}\x{55CE}\x{55CF}\x{55D0}\x{55D1}\x{55D2}'
. '\x{55D3}\x{55D4}\x{55D5}\x{55D6}\x{55D7}\x{55D8}\x{55D9}\x{55DA}\x{55DB}'
. '\x{55DC}\x{55DD}\x{55DE}\x{55DF}\x{55E1}\x{55E2}\x{55E3}\x{55E4}\x{55E5}'
. '\x{55E6}\x{55E7}\x{55E8}\x{55E9}\x{55EA}\x{55EB}\x{55EC}\x{55ED}\x{55EE}'
. '\x{55EF}\x{55F0}\x{55F1}\x{55F2}\x{55F3}\x{55F4}\x{55F5}\x{55F6}\x{55F7}'
. '\x{55F9}\x{55FA}\x{55FB}\x{55FC}\x{55FD}\x{55FE}\x{55FF}\x{5600}\x{5601}'
. '\x{5602}\x{5603}\x{5604}\x{5606}\x{5607}\x{5608}\x{5609}\x{560C}\x{560D}'
. '\x{560E}\x{560F}\x{5610}\x{5611}\x{5612}\x{5613}\x{5614}\x{5615}\x{5616}'
. '\x{5617}\x{5618}\x{5619}\x{561A}\x{561B}\x{561C}\x{561D}\x{561E}\x{561F}'
. '\x{5621}\x{5622}\x{5623}\x{5624}\x{5625}\x{5626}\x{5627}\x{5628}\x{5629}'
. '\x{562A}\x{562C}\x{562D}\x{562E}\x{562F}\x{5630}\x{5631}\x{5632}\x{5633}'
. '\x{5634}\x{5635}\x{5636}\x{5638}\x{5639}\x{563A}\x{563B}\x{563D}\x{563E}'
. '\x{563F}\x{5640}\x{5641}\x{5642}\x{5643}\x{5645}\x{5646}\x{5647}\x{5648}'
. '\x{5649}\x{564A}\x{564C}\x{564D}\x{564E}\x{564F}\x{5650}\x{5652}\x{5653}'
. '\x{5654}\x{5655}\x{5657}\x{5658}\x{5659}\x{565A}\x{565B}\x{565C}\x{565D}'
. '\x{565E}\x{5660}\x{5662}\x{5663}\x{5664}\x{5665}\x{5666}\x{5667}\x{5668}'
. '\x{5669}\x{566A}\x{566B}\x{566C}\x{566D}\x{566E}\x{566F}\x{5670}\x{5671}'
. '\x{5672}\x{5673}\x{5674}\x{5676}\x{5677}\x{5678}\x{5679}\x{567A}\x{567B}'
. '\x{567C}\x{567E}\x{567F}\x{5680}\x{5681}\x{5682}\x{5683}\x{5684}\x{5685}'
. '\x{5686}\x{5687}\x{568A}\x{568C}\x{568D}\x{568E}\x{568F}\x{5690}\x{5691}'
. '\x{5692}\x{5693}\x{5694}\x{5695}\x{5697}\x{5698}\x{5699}\x{569A}\x{569B}'
. '\x{569C}\x{569D}\x{569F}\x{56A0}\x{56A1}\x{56A3}\x{56A4}\x{56A5}\x{56A6}'
. '\x{56A7}\x{56A8}\x{56A9}\x{56AA}\x{56AB}\x{56AC}\x{56AD}\x{56AE}\x{56AF}'
. '\x{56B0}\x{56B1}\x{56B2}\x{56B3}\x{56B4}\x{56B5}\x{56B6}\x{56B7}\x{56B8}'
. '\x{56B9}\x{56BB}\x{56BC}\x{56BD}\x{56BE}\x{56BF}\x{56C0}\x{56C1}\x{56C2}'
. '\x{56C3}\x{56C4}\x{56C5}\x{56C6}\x{56C7}\x{56C8}\x{56C9}\x{56CA}\x{56CB}'
. '\x{56CC}\x{56CD}\x{56CE}\x{56D0}\x{56D1}\x{56D2}\x{56D3}\x{56D4}\x{56D5}'
. '\x{56D6}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DC}\x{56DD}\x{56DE}\x{56DF}'
. '\x{56E0}\x{56E1}\x{56E2}\x{56E3}\x{56E4}\x{56E5}\x{56E7}\x{56E8}\x{56E9}'
. '\x{56EA}\x{56EB}\x{56EC}\x{56ED}\x{56EE}\x{56EF}\x{56F0}\x{56F1}\x{56F2}'
. '\x{56F3}\x{56F4}\x{56F5}\x{56F7}\x{56F9}\x{56FA}\x{56FD}\x{56FE}\x{56FF}'
. '\x{5700}\x{5701}\x{5702}\x{5703}\x{5704}\x{5706}\x{5707}\x{5708}\x{5709}'
. '\x{570A}\x{570B}\x{570C}\x{570D}\x{570E}\x{570F}\x{5710}\x{5712}\x{5713}'
. '\x{5714}\x{5715}\x{5716}\x{5718}\x{5719}\x{571A}\x{571B}\x{571C}\x{571D}'
. '\x{571E}\x{571F}\x{5720}\x{5722}\x{5723}\x{5725}\x{5726}\x{5727}\x{5728}'
. '\x{5729}\x{572A}\x{572B}\x{572C}\x{572D}\x{572E}\x{572F}\x{5730}\x{5731}'
. '\x{5732}\x{5733}\x{5734}\x{5735}\x{5736}\x{5737}\x{5738}\x{5739}\x{573A}'
. '\x{573B}\x{573C}\x{573E}\x{573F}\x{5740}\x{5741}\x{5742}\x{5744}\x{5745}'
. '\x{5746}\x{5747}\x{5749}\x{574A}\x{574B}\x{574C}\x{574D}\x{574E}\x{574F}'
. '\x{5750}\x{5751}\x{5752}\x{5753}\x{5754}\x{5757}\x{5759}\x{575A}\x{575B}'
. '\x{575C}\x{575D}\x{575E}\x{575F}\x{5760}\x{5761}\x{5762}\x{5764}\x{5765}'
. '\x{5766}\x{5767}\x{5768}\x{5769}\x{576A}\x{576B}\x{576C}\x{576D}\x{576F}'
. '\x{5770}\x{5771}\x{5772}\x{5773}\x{5774}\x{5775}\x{5776}\x{5777}\x{5779}'
. '\x{577A}\x{577B}\x{577C}\x{577D}\x{577E}\x{577F}\x{5780}\x{5782}\x{5783}'
. '\x{5784}\x{5785}\x{5786}\x{5788}\x{5789}\x{578A}\x{578B}\x{578C}\x{578D}'
. '\x{578E}\x{578F}\x{5790}\x{5791}\x{5792}\x{5793}\x{5794}\x{5795}\x{5797}'
. '\x{5798}\x{5799}\x{579A}\x{579B}\x{579C}\x{579D}\x{579E}\x{579F}\x{57A0}'
. '\x{57A1}\x{57A2}\x{57A3}\x{57A4}\x{57A5}\x{57A6}\x{57A7}\x{57A9}\x{57AA}'
. '\x{57AB}\x{57AC}\x{57AD}\x{57AE}\x{57AF}\x{57B0}\x{57B1}\x{57B2}\x{57B3}'
. '\x{57B4}\x{57B5}\x{57B6}\x{57B7}\x{57B8}\x{57B9}\x{57BA}\x{57BB}\x{57BC}'
. '\x{57BD}\x{57BE}\x{57BF}\x{57C0}\x{57C1}\x{57C2}\x{57C3}\x{57C4}\x{57C5}'
. '\x{57C6}\x{57C7}\x{57C8}\x{57C9}\x{57CB}\x{57CC}\x{57CD}\x{57CE}\x{57CF}'
. '\x{57D0}\x{57D2}\x{57D3}\x{57D4}\x{57D5}\x{57D6}\x{57D8}\x{57D9}\x{57DA}'
. '\x{57DC}\x{57DD}\x{57DF}\x{57E0}\x{57E1}\x{57E2}\x{57E3}\x{57E4}\x{57E5}'
. '\x{57E6}\x{57E7}\x{57E8}\x{57E9}\x{57EA}\x{57EB}\x{57EC}\x{57ED}\x{57EE}'
. '\x{57EF}\x{57F0}\x{57F1}\x{57F2}\x{57F3}\x{57F4}\x{57F5}\x{57F6}\x{57F7}'
. '\x{57F8}\x{57F9}\x{57FA}\x{57FB}\x{57FC}\x{57FD}\x{57FE}\x{57FF}\x{5800}'
. '\x{5801}\x{5802}\x{5803}\x{5804}\x{5805}\x{5806}\x{5807}\x{5808}\x{5809}'
. '\x{580A}\x{580B}\x{580C}\x{580D}\x{580E}\x{580F}\x{5810}\x{5811}\x{5812}'
. '\x{5813}\x{5814}\x{5815}\x{5816}\x{5819}\x{581A}\x{581B}\x{581C}\x{581D}'
. '\x{581E}\x{581F}\x{5820}\x{5821}\x{5822}\x{5823}\x{5824}\x{5825}\x{5826}'
. '\x{5827}\x{5828}\x{5829}\x{582A}\x{582B}\x{582C}\x{582D}\x{582E}\x{582F}'
. '\x{5830}\x{5831}\x{5832}\x{5833}\x{5834}\x{5835}\x{5836}\x{5837}\x{5838}'
. '\x{5839}\x{583A}\x{583B}\x{583C}\x{583D}\x{583E}\x{583F}\x{5840}\x{5842}'
. '\x{5843}\x{5844}\x{5845}\x{5846}\x{5847}\x{5848}\x{5849}\x{584A}\x{584B}'
. '\x{584C}\x{584D}\x{584E}\x{584F}\x{5851}\x{5852}\x{5853}\x{5854}\x{5855}'
. '\x{5857}\x{5858}\x{5859}\x{585A}\x{585B}\x{585C}\x{585D}\x{585E}\x{585F}'
. '\x{5861}\x{5862}\x{5863}\x{5864}\x{5865}\x{5868}\x{5869}\x{586A}\x{586B}'
. '\x{586C}\x{586D}\x{586E}\x{586F}\x{5870}\x{5871}\x{5872}\x{5873}\x{5874}'
. '\x{5875}\x{5876}\x{5878}\x{5879}\x{587A}\x{587B}\x{587C}\x{587D}\x{587E}'
. '\x{587F}\x{5880}\x{5881}\x{5882}\x{5883}\x{5884}\x{5885}\x{5886}\x{5887}'
. '\x{5888}\x{5889}\x{588A}\x{588B}\x{588C}\x{588D}\x{588E}\x{588F}\x{5890}'
. '\x{5891}\x{5892}\x{5893}\x{5894}\x{5896}\x{5897}\x{5898}\x{5899}\x{589A}'
. '\x{589B}\x{589C}\x{589D}\x{589E}\x{589F}\x{58A0}\x{58A1}\x{58A2}\x{58A3}'
. '\x{58A4}\x{58A5}\x{58A6}\x{58A7}\x{58A8}\x{58A9}\x{58AB}\x{58AC}\x{58AD}'
. '\x{58AE}\x{58AF}\x{58B0}\x{58B1}\x{58B2}\x{58B3}\x{58B4}\x{58B7}\x{58B8}'
. '\x{58B9}\x{58BA}\x{58BB}\x{58BC}\x{58BD}\x{58BE}\x{58BF}\x{58C1}\x{58C2}'
. '\x{58C5}\x{58C6}\x{58C7}\x{58C8}\x{58C9}\x{58CA}\x{58CB}\x{58CE}\x{58CF}'
. '\x{58D1}\x{58D2}\x{58D3}\x{58D4}\x{58D5}\x{58D6}\x{58D7}\x{58D8}\x{58D9}'
. '\x{58DA}\x{58DB}\x{58DD}\x{58DE}\x{58DF}\x{58E0}\x{58E2}\x{58E3}\x{58E4}'
. '\x{58E5}\x{58E7}\x{58E8}\x{58E9}\x{58EA}\x{58EB}\x{58EC}\x{58ED}\x{58EE}'
. '\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F3}\x{58F4}\x{58F6}\x{58F7}\x{58F8}'
. '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{58FE}\x{58FF}\x{5900}\x{5902}'
. '\x{5903}\x{5904}\x{5906}\x{5907}\x{5909}\x{590A}\x{590B}\x{590C}\x{590D}'
. '\x{590E}\x{590F}\x{5910}\x{5912}\x{5914}\x{5915}\x{5916}\x{5917}\x{5918}'
. '\x{5919}\x{591A}\x{591B}\x{591C}\x{591D}\x{591E}\x{591F}\x{5920}\x{5921}'
. '\x{5922}\x{5924}\x{5925}\x{5926}\x{5927}\x{5928}\x{5929}\x{592A}\x{592B}'
. '\x{592C}\x{592D}\x{592E}\x{592F}\x{5930}\x{5931}\x{5932}\x{5934}\x{5935}'
. '\x{5937}\x{5938}\x{5939}\x{593A}\x{593B}\x{593C}\x{593D}\x{593E}\x{593F}'
. '\x{5940}\x{5941}\x{5942}\x{5943}\x{5944}\x{5945}\x{5946}\x{5947}\x{5948}'
. '\x{5949}\x{594A}\x{594B}\x{594C}\x{594D}\x{594E}\x{594F}\x{5950}\x{5951}'
. '\x{5952}\x{5953}\x{5954}\x{5955}\x{5956}\x{5957}\x{5958}\x{595A}\x{595C}'
. '\x{595D}\x{595E}\x{595F}\x{5960}\x{5961}\x{5962}\x{5963}\x{5964}\x{5965}'
. '\x{5966}\x{5967}\x{5968}\x{5969}\x{596A}\x{596B}\x{596C}\x{596D}\x{596E}'
. '\x{596F}\x{5970}\x{5971}\x{5972}\x{5973}\x{5974}\x{5975}\x{5976}\x{5977}'
. '\x{5978}\x{5979}\x{597A}\x{597B}\x{597C}\x{597D}\x{597E}\x{597F}\x{5980}'
. '\x{5981}\x{5982}\x{5983}\x{5984}\x{5985}\x{5986}\x{5987}\x{5988}\x{5989}'
. '\x{598A}\x{598B}\x{598C}\x{598D}\x{598E}\x{598F}\x{5990}\x{5991}\x{5992}'
. '\x{5993}\x{5994}\x{5995}\x{5996}\x{5997}\x{5998}\x{5999}\x{599A}\x{599C}'
. '\x{599D}\x{599E}\x{599F}\x{59A0}\x{59A1}\x{59A2}\x{59A3}\x{59A4}\x{59A5}'
. '\x{59A6}\x{59A7}\x{59A8}\x{59A9}\x{59AA}\x{59AB}\x{59AC}\x{59AD}\x{59AE}'
. '\x{59AF}\x{59B0}\x{59B1}\x{59B2}\x{59B3}\x{59B4}\x{59B5}\x{59B6}\x{59B8}'
. '\x{59B9}\x{59BA}\x{59BB}\x{59BC}\x{59BD}\x{59BE}\x{59BF}\x{59C0}\x{59C1}'
. '\x{59C2}\x{59C3}\x{59C4}\x{59C5}\x{59C6}\x{59C7}\x{59C8}\x{59C9}\x{59CA}'
. '\x{59CB}\x{59CC}\x{59CD}\x{59CE}\x{59CF}\x{59D0}\x{59D1}\x{59D2}\x{59D3}'
. '\x{59D4}\x{59D5}\x{59D6}\x{59D7}\x{59D8}\x{59D9}\x{59DA}\x{59DB}\x{59DC}'
. '\x{59DD}\x{59DE}\x{59DF}\x{59E0}\x{59E1}\x{59E2}\x{59E3}\x{59E4}\x{59E5}'
. '\x{59E6}\x{59E8}\x{59E9}\x{59EA}\x{59EB}\x{59EC}\x{59ED}\x{59EE}\x{59EF}'
. '\x{59F0}\x{59F1}\x{59F2}\x{59F3}\x{59F4}\x{59F5}\x{59F6}\x{59F7}\x{59F8}'
. '\x{59F9}\x{59FA}\x{59FB}\x{59FC}\x{59FD}\x{59FE}\x{59FF}\x{5A00}\x{5A01}'
. '\x{5A02}\x{5A03}\x{5A04}\x{5A05}\x{5A06}\x{5A07}\x{5A08}\x{5A09}\x{5A0A}'
. '\x{5A0B}\x{5A0C}\x{5A0D}\x{5A0E}\x{5A0F}\x{5A10}\x{5A11}\x{5A12}\x{5A13}'
. '\x{5A14}\x{5A15}\x{5A16}\x{5A17}\x{5A18}\x{5A19}\x{5A1A}\x{5A1B}\x{5A1C}'
. '\x{5A1D}\x{5A1E}\x{5A1F}\x{5A20}\x{5A21}\x{5A22}\x{5A23}\x{5A25}\x{5A27}'
. '\x{5A28}\x{5A29}\x{5A2A}\x{5A2B}\x{5A2D}\x{5A2E}\x{5A2F}\x{5A31}\x{5A32}'
. '\x{5A33}\x{5A34}\x{5A35}\x{5A36}\x{5A37}\x{5A38}\x{5A39}\x{5A3A}\x{5A3B}'
. '\x{5A3C}\x{5A3D}\x{5A3E}\x{5A3F}\x{5A40}\x{5A41}\x{5A42}\x{5A43}\x{5A44}'
. '\x{5A45}\x{5A46}\x{5A47}\x{5A48}\x{5A49}\x{5A4A}\x{5A4B}\x{5A4C}\x{5A4D}'
. '\x{5A4E}\x{5A4F}\x{5A50}\x{5A51}\x{5A52}\x{5A53}\x{5A55}\x{5A56}\x{5A57}'
. '\x{5A58}\x{5A5A}\x{5A5B}\x{5A5C}\x{5A5D}\x{5A5E}\x{5A5F}\x{5A60}\x{5A61}'
. '\x{5A62}\x{5A63}\x{5A64}\x{5A65}\x{5A66}\x{5A67}\x{5A68}\x{5A69}\x{5A6A}'
. '\x{5A6B}\x{5A6C}\x{5A6D}\x{5A6E}\x{5A70}\x{5A72}\x{5A73}\x{5A74}\x{5A75}'
. '\x{5A76}\x{5A77}\x{5A78}\x{5A79}\x{5A7A}\x{5A7B}\x{5A7C}\x{5A7D}\x{5A7E}'
. '\x{5A7F}\x{5A80}\x{5A81}\x{5A82}\x{5A83}\x{5A84}\x{5A85}\x{5A86}\x{5A88}'
. '\x{5A89}\x{5A8A}\x{5A8B}\x{5A8C}\x{5A8E}\x{5A8F}\x{5A90}\x{5A91}\x{5A92}'
. '\x{5A93}\x{5A94}\x{5A95}\x{5A96}\x{5A97}\x{5A98}\x{5A99}\x{5A9A}\x{5A9B}'
. '\x{5A9C}\x{5A9D}\x{5A9E}\x{5A9F}\x{5AA0}\x{5AA1}\x{5AA2}\x{5AA3}\x{5AA4}'
. '\x{5AA5}\x{5AA6}\x{5AA7}\x{5AA8}\x{5AA9}\x{5AAA}\x{5AAC}\x{5AAD}\x{5AAE}'
. '\x{5AAF}\x{5AB0}\x{5AB1}\x{5AB2}\x{5AB3}\x{5AB4}\x{5AB5}\x{5AB6}\x{5AB7}'
. '\x{5AB8}\x{5AB9}\x{5ABA}\x{5ABB}\x{5ABC}\x{5ABD}\x{5ABE}\x{5ABF}\x{5AC0}'
. '\x{5AC1}\x{5AC2}\x{5AC3}\x{5AC4}\x{5AC5}\x{5AC6}\x{5AC7}\x{5AC8}\x{5AC9}'
. '\x{5ACA}\x{5ACB}\x{5ACC}\x{5ACD}\x{5ACE}\x{5ACF}\x{5AD1}\x{5AD2}\x{5AD4}'
. '\x{5AD5}\x{5AD6}\x{5AD7}\x{5AD8}\x{5AD9}\x{5ADA}\x{5ADB}\x{5ADC}\x{5ADD}'
. '\x{5ADE}\x{5ADF}\x{5AE0}\x{5AE1}\x{5AE2}\x{5AE3}\x{5AE4}\x{5AE5}\x{5AE6}'
. '\x{5AE7}\x{5AE8}\x{5AE9}\x{5AEA}\x{5AEB}\x{5AEC}\x{5AED}\x{5AEE}\x{5AF1}'
. '\x{5AF2}\x{5AF3}\x{5AF4}\x{5AF5}\x{5AF6}\x{5AF7}\x{5AF8}\x{5AF9}\x{5AFA}'
. '\x{5AFB}\x{5AFC}\x{5AFD}\x{5AFE}\x{5AFF}\x{5B00}\x{5B01}\x{5B02}\x{5B03}'
. '\x{5B04}\x{5B05}\x{5B06}\x{5B07}\x{5B08}\x{5B09}\x{5B0B}\x{5B0C}\x{5B0E}'
. '\x{5B0F}\x{5B10}\x{5B11}\x{5B12}\x{5B13}\x{5B14}\x{5B15}\x{5B16}\x{5B17}'
. '\x{5B18}\x{5B19}\x{5B1A}\x{5B1B}\x{5B1C}\x{5B1D}\x{5B1E}\x{5B1F}\x{5B20}'
. '\x{5B21}\x{5B22}\x{5B23}\x{5B24}\x{5B25}\x{5B26}\x{5B27}\x{5B28}\x{5B29}'
. '\x{5B2A}\x{5B2B}\x{5B2C}\x{5B2D}\x{5B2E}\x{5B2F}\x{5B30}\x{5B31}\x{5B32}'
. '\x{5B33}\x{5B34}\x{5B35}\x{5B36}\x{5B37}\x{5B38}\x{5B3A}\x{5B3B}\x{5B3C}'
. '\x{5B3D}\x{5B3E}\x{5B3F}\x{5B40}\x{5B41}\x{5B42}\x{5B43}\x{5B44}\x{5B45}'
. '\x{5B47}\x{5B48}\x{5B49}\x{5B4A}\x{5B4B}\x{5B4C}\x{5B4D}\x{5B4E}\x{5B50}'
. '\x{5B51}\x{5B53}\x{5B54}\x{5B55}\x{5B56}\x{5B57}\x{5B58}\x{5B59}\x{5B5A}'
. '\x{5B5B}\x{5B5C}\x{5B5D}\x{5B5E}\x{5B5F}\x{5B62}\x{5B63}\x{5B64}\x{5B65}'
. '\x{5B66}\x{5B67}\x{5B68}\x{5B69}\x{5B6A}\x{5B6B}\x{5B6C}\x{5B6D}\x{5B6E}'
. '\x{5B70}\x{5B71}\x{5B72}\x{5B73}\x{5B74}\x{5B75}\x{5B76}\x{5B77}\x{5B78}'
. '\x{5B7A}\x{5B7B}\x{5B7C}\x{5B7D}\x{5B7F}\x{5B80}\x{5B81}\x{5B82}\x{5B83}'
. '\x{5B84}\x{5B85}\x{5B87}\x{5B88}\x{5B89}\x{5B8A}\x{5B8B}\x{5B8C}\x{5B8D}'
. '\x{5B8E}\x{5B8F}\x{5B91}\x{5B92}\x{5B93}\x{5B94}\x{5B95}\x{5B96}\x{5B97}'
. '\x{5B98}\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9E}\x{5B9F}\x{5BA0}'
. '\x{5BA1}\x{5BA2}\x{5BA3}\x{5BA4}\x{5BA5}\x{5BA6}\x{5BA7}\x{5BA8}\x{5BAA}'
. '\x{5BAB}\x{5BAC}\x{5BAD}\x{5BAE}\x{5BAF}\x{5BB0}\x{5BB1}\x{5BB3}\x{5BB4}'
. '\x{5BB5}\x{5BB6}\x{5BB8}\x{5BB9}\x{5BBA}\x{5BBB}\x{5BBD}\x{5BBE}\x{5BBF}'
. '\x{5BC0}\x{5BC1}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BCA}'
. '\x{5BCB}\x{5BCC}\x{5BCD}\x{5BCE}\x{5BCF}\x{5BD0}\x{5BD1}\x{5BD2}\x{5BD3}'
. '\x{5BD4}\x{5BD5}\x{5BD6}\x{5BD8}\x{5BD9}\x{5BDB}\x{5BDC}\x{5BDD}\x{5BDE}'
. '\x{5BDF}\x{5BE0}\x{5BE1}\x{5BE2}\x{5BE3}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}'
. '\x{5BE8}\x{5BE9}\x{5BEA}\x{5BEB}\x{5BEC}\x{5BED}\x{5BEE}\x{5BEF}\x{5BF0}'
. '\x{5BF1}\x{5BF2}\x{5BF3}\x{5BF4}\x{5BF5}\x{5BF6}\x{5BF7}\x{5BF8}\x{5BF9}'
. '\x{5BFA}\x{5BFB}\x{5BFC}\x{5BFD}\x{5BFF}\x{5C01}\x{5C03}\x{5C04}\x{5C05}'
. '\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}\x{5C0B}\x{5C0C}\x{5C0D}\x{5C0E}'
. '\x{5C0F}\x{5C10}\x{5C11}\x{5C12}\x{5C13}\x{5C14}\x{5C15}\x{5C16}\x{5C17}'
. '\x{5C18}\x{5C19}\x{5C1A}\x{5C1C}\x{5C1D}\x{5C1E}\x{5C1F}\x{5C20}\x{5C21}'
. '\x{5C22}\x{5C24}\x{5C25}\x{5C27}\x{5C28}\x{5C2A}\x{5C2B}\x{5C2C}\x{5C2D}'
. '\x{5C2E}\x{5C2F}\x{5C30}\x{5C31}\x{5C32}\x{5C33}\x{5C34}\x{5C35}\x{5C37}'
. '\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}'
. '\x{5C41}\x{5C42}\x{5C43}\x{5C44}\x{5C45}\x{5C46}\x{5C47}\x{5C48}\x{5C49}'
. '\x{5C4A}\x{5C4B}\x{5C4C}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C52}'
. '\x{5C53}\x{5C54}\x{5C55}\x{5C56}\x{5C57}\x{5C58}\x{5C59}\x{5C5B}\x{5C5C}'
. '\x{5C5D}\x{5C5E}\x{5C5F}\x{5C60}\x{5C61}\x{5C62}\x{5C63}\x{5C64}\x{5C65}'
. '\x{5C66}\x{5C67}\x{5C68}\x{5C69}\x{5C6A}\x{5C6B}\x{5C6C}\x{5C6D}\x{5C6E}'
. '\x{5C6F}\x{5C70}\x{5C71}\x{5C72}\x{5C73}\x{5C74}\x{5C75}\x{5C76}\x{5C77}'
. '\x{5C78}\x{5C79}\x{5C7A}\x{5C7B}\x{5C7C}\x{5C7D}\x{5C7E}\x{5C7F}\x{5C80}'
. '\x{5C81}\x{5C82}\x{5C83}\x{5C84}\x{5C86}\x{5C87}\x{5C88}\x{5C89}\x{5C8A}'
. '\x{5C8B}\x{5C8C}\x{5C8D}\x{5C8E}\x{5C8F}\x{5C90}\x{5C91}\x{5C92}\x{5C93}'
. '\x{5C94}\x{5C95}\x{5C96}\x{5C97}\x{5C98}\x{5C99}\x{5C9A}\x{5C9B}\x{5C9C}'
. '\x{5C9D}\x{5C9E}\x{5C9F}\x{5CA0}\x{5CA1}\x{5CA2}\x{5CA3}\x{5CA4}\x{5CA5}'
. '\x{5CA6}\x{5CA7}\x{5CA8}\x{5CA9}\x{5CAA}\x{5CAB}\x{5CAC}\x{5CAD}\x{5CAE}'
. '\x{5CAF}\x{5CB0}\x{5CB1}\x{5CB2}\x{5CB3}\x{5CB5}\x{5CB6}\x{5CB7}\x{5CB8}'
. '\x{5CBA}\x{5CBB}\x{5CBC}\x{5CBD}\x{5CBE}\x{5CBF}\x{5CC1}\x{5CC2}\x{5CC3}'
. '\x{5CC4}\x{5CC5}\x{5CC6}\x{5CC7}\x{5CC8}\x{5CC9}\x{5CCA}\x{5CCB}\x{5CCC}'
. '\x{5CCD}\x{5CCE}\x{5CCF}\x{5CD0}\x{5CD1}\x{5CD2}\x{5CD3}\x{5CD4}\x{5CD6}'
. '\x{5CD7}\x{5CD8}\x{5CD9}\x{5CDA}\x{5CDB}\x{5CDC}\x{5CDE}\x{5CDF}\x{5CE0}'
. '\x{5CE1}\x{5CE2}\x{5CE3}\x{5CE4}\x{5CE5}\x{5CE6}\x{5CE7}\x{5CE8}\x{5CE9}'
. '\x{5CEA}\x{5CEB}\x{5CEC}\x{5CED}\x{5CEE}\x{5CEF}\x{5CF0}\x{5CF1}\x{5CF2}'
. '\x{5CF3}\x{5CF4}\x{5CF6}\x{5CF7}\x{5CF8}\x{5CF9}\x{5CFA}\x{5CFB}\x{5CFC}'
. '\x{5CFD}\x{5CFE}\x{5CFF}\x{5D00}\x{5D01}\x{5D02}\x{5D03}\x{5D04}\x{5D05}'
. '\x{5D06}\x{5D07}\x{5D08}\x{5D09}\x{5D0A}\x{5D0B}\x{5D0C}\x{5D0D}\x{5D0E}'
. '\x{5D0F}\x{5D10}\x{5D11}\x{5D12}\x{5D13}\x{5D14}\x{5D15}\x{5D16}\x{5D17}'
. '\x{5D18}\x{5D19}\x{5D1A}\x{5D1B}\x{5D1C}\x{5D1D}\x{5D1E}\x{5D1F}\x{5D20}'
. '\x{5D21}\x{5D22}\x{5D23}\x{5D24}\x{5D25}\x{5D26}\x{5D27}\x{5D28}\x{5D29}'
. '\x{5D2A}\x{5D2C}\x{5D2D}\x{5D2E}\x{5D30}\x{5D31}\x{5D32}\x{5D33}\x{5D34}'
. '\x{5D35}\x{5D36}\x{5D37}\x{5D38}\x{5D39}\x{5D3A}\x{5D3C}\x{5D3D}\x{5D3E}'
. '\x{5D3F}\x{5D40}\x{5D41}\x{5D42}\x{5D43}\x{5D44}\x{5D45}\x{5D46}\x{5D47}'
. '\x{5D48}\x{5D49}\x{5D4A}\x{5D4B}\x{5D4C}\x{5D4D}\x{5D4E}\x{5D4F}\x{5D50}'
. '\x{5D51}\x{5D52}\x{5D54}\x{5D55}\x{5D56}\x{5D58}\x{5D59}\x{5D5A}\x{5D5B}'
. '\x{5D5D}\x{5D5E}\x{5D5F}\x{5D61}\x{5D62}\x{5D63}\x{5D64}\x{5D65}\x{5D66}'
. '\x{5D67}\x{5D68}\x{5D69}\x{5D6A}\x{5D6B}\x{5D6C}\x{5D6D}\x{5D6E}\x{5D6F}'
. '\x{5D70}\x{5D71}\x{5D72}\x{5D73}\x{5D74}\x{5D75}\x{5D76}\x{5D77}\x{5D78}'
. '\x{5D79}\x{5D7A}\x{5D7B}\x{5D7C}\x{5D7D}\x{5D7E}\x{5D7F}\x{5D80}\x{5D81}'
. '\x{5D82}\x{5D84}\x{5D85}\x{5D86}\x{5D87}\x{5D88}\x{5D89}\x{5D8A}\x{5D8B}'
. '\x{5D8C}\x{5D8D}\x{5D8E}\x{5D8F}\x{5D90}\x{5D91}\x{5D92}\x{5D93}\x{5D94}'
. '\x{5D95}\x{5D97}\x{5D98}\x{5D99}\x{5D9A}\x{5D9B}\x{5D9C}\x{5D9D}\x{5D9E}'
. '\x{5D9F}\x{5DA0}\x{5DA1}\x{5DA2}\x{5DA5}\x{5DA6}\x{5DA7}\x{5DA8}\x{5DA9}'
. '\x{5DAA}\x{5DAC}\x{5DAD}\x{5DAE}\x{5DAF}\x{5DB0}\x{5DB1}\x{5DB2}\x{5DB4}'
. '\x{5DB5}\x{5DB6}\x{5DB7}\x{5DB8}\x{5DBA}\x{5DBB}\x{5DBC}\x{5DBD}\x{5DBE}'
. '\x{5DBF}\x{5DC0}\x{5DC1}\x{5DC2}\x{5DC3}\x{5DC5}\x{5DC6}\x{5DC7}\x{5DC8}'
. '\x{5DC9}\x{5DCA}\x{5DCB}\x{5DCC}\x{5DCD}\x{5DCE}\x{5DCF}\x{5DD0}\x{5DD1}'
. '\x{5DD2}\x{5DD3}\x{5DD4}\x{5DD5}\x{5DD6}\x{5DD8}\x{5DD9}\x{5DDB}\x{5DDD}'
. '\x{5DDE}\x{5DDF}\x{5DE0}\x{5DE1}\x{5DE2}\x{5DE3}\x{5DE4}\x{5DE5}\x{5DE6}'
. '\x{5DE7}\x{5DE8}\x{5DE9}\x{5DEA}\x{5DEB}\x{5DEC}\x{5DED}\x{5DEE}\x{5DEF}'
. '\x{5DF0}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DF8}\x{5DF9}'
. '\x{5DFA}\x{5DFB}\x{5DFC}\x{5DFD}\x{5DFE}\x{5DFF}\x{5E00}\x{5E01}\x{5E02}'
. '\x{5E03}\x{5E04}\x{5E05}\x{5E06}\x{5E07}\x{5E08}\x{5E09}\x{5E0A}\x{5E0B}'
. '\x{5E0C}\x{5E0D}\x{5E0E}\x{5E0F}\x{5E10}\x{5E11}\x{5E13}\x{5E14}\x{5E15}'
. '\x{5E16}\x{5E17}\x{5E18}\x{5E19}\x{5E1A}\x{5E1B}\x{5E1C}\x{5E1D}\x{5E1E}'
. '\x{5E1F}\x{5E20}\x{5E21}\x{5E22}\x{5E23}\x{5E24}\x{5E25}\x{5E26}\x{5E27}'
. '\x{5E28}\x{5E29}\x{5E2A}\x{5E2B}\x{5E2C}\x{5E2D}\x{5E2E}\x{5E2F}\x{5E30}'
. '\x{5E31}\x{5E32}\x{5E33}\x{5E34}\x{5E35}\x{5E36}\x{5E37}\x{5E38}\x{5E39}'
. '\x{5E3A}\x{5E3B}\x{5E3C}\x{5E3D}\x{5E3E}\x{5E40}\x{5E41}\x{5E42}\x{5E43}'
. '\x{5E44}\x{5E45}\x{5E46}\x{5E47}\x{5E49}\x{5E4A}\x{5E4B}\x{5E4C}\x{5E4D}'
. '\x{5E4E}\x{5E4F}\x{5E50}\x{5E52}\x{5E53}\x{5E54}\x{5E55}\x{5E56}\x{5E57}'
. '\x{5E58}\x{5E59}\x{5E5A}\x{5E5B}\x{5E5C}\x{5E5D}\x{5E5E}\x{5E5F}\x{5E60}'
. '\x{5E61}\x{5E62}\x{5E63}\x{5E64}\x{5E65}\x{5E66}\x{5E67}\x{5E68}\x{5E69}'
. '\x{5E6A}\x{5E6B}\x{5E6C}\x{5E6D}\x{5E6E}\x{5E6F}\x{5E70}\x{5E71}\x{5E72}'
. '\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E77}\x{5E78}\x{5E79}\x{5E7A}\x{5E7B}'
. '\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E80}\x{5E81}\x{5E82}\x{5E83}\x{5E84}'
. '\x{5E85}\x{5E86}\x{5E87}\x{5E88}\x{5E89}\x{5E8A}\x{5E8B}\x{5E8C}\x{5E8D}'
. '\x{5E8E}\x{5E8F}\x{5E90}\x{5E91}\x{5E93}\x{5E94}\x{5E95}\x{5E96}\x{5E97}'
. '\x{5E98}\x{5E99}\x{5E9A}\x{5E9B}\x{5E9C}\x{5E9D}\x{5E9E}\x{5E9F}\x{5EA0}'
. '\x{5EA1}\x{5EA2}\x{5EA3}\x{5EA4}\x{5EA5}\x{5EA6}\x{5EA7}\x{5EA8}\x{5EA9}'
. '\x{5EAA}\x{5EAB}\x{5EAC}\x{5EAD}\x{5EAE}\x{5EAF}\x{5EB0}\x{5EB1}\x{5EB2}'
. '\x{5EB3}\x{5EB4}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EB9}\x{5EBB}\x{5EBC}'
. '\x{5EBD}\x{5EBE}\x{5EBF}\x{5EC1}\x{5EC2}\x{5EC3}\x{5EC4}\x{5EC5}\x{5EC6}'
. '\x{5EC7}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECB}\x{5ECC}\x{5ECD}\x{5ECE}\x{5ECF}'
. '\x{5ED0}\x{5ED1}\x{5ED2}\x{5ED3}\x{5ED4}\x{5ED5}\x{5ED6}\x{5ED7}\x{5ED8}'
. '\x{5ED9}\x{5EDA}\x{5EDB}\x{5EDC}\x{5EDD}\x{5EDE}\x{5EDF}\x{5EE0}\x{5EE1}'
. '\x{5EE2}\x{5EE3}\x{5EE4}\x{5EE5}\x{5EE6}\x{5EE7}\x{5EE8}\x{5EE9}\x{5EEA}'
. '\x{5EEC}\x{5EED}\x{5EEE}\x{5EEF}\x{5EF0}\x{5EF1}\x{5EF2}\x{5EF3}\x{5EF4}'
. '\x{5EF5}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}\x{5EFB}\x{5EFC}\x{5EFD}\x{5EFE}'
. '\x{5EFF}\x{5F00}\x{5F01}\x{5F02}\x{5F03}\x{5F04}\x{5F05}\x{5F06}\x{5F07}'
. '\x{5F08}\x{5F0A}\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F11}\x{5F12}\x{5F13}'
. '\x{5F14}\x{5F15}\x{5F16}\x{5F17}\x{5F18}\x{5F19}\x{5F1A}\x{5F1B}\x{5F1C}'
. '\x{5F1D}\x{5F1E}\x{5F1F}\x{5F20}\x{5F21}\x{5F22}\x{5F23}\x{5F24}\x{5F25}'
. '\x{5F26}\x{5F27}\x{5F28}\x{5F29}\x{5F2A}\x{5F2B}\x{5F2C}\x{5F2D}\x{5F2E}'
. '\x{5F2F}\x{5F30}\x{5F31}\x{5F32}\x{5F33}\x{5F34}\x{5F35}\x{5F36}\x{5F37}'
. '\x{5F38}\x{5F39}\x{5F3A}\x{5F3C}\x{5F3E}\x{5F3F}\x{5F40}\x{5F41}\x{5F42}'
. '\x{5F43}\x{5F44}\x{5F45}\x{5F46}\x{5F47}\x{5F48}\x{5F49}\x{5F4A}\x{5F4B}'
. '\x{5F4C}\x{5F4D}\x{5F4E}\x{5F4F}\x{5F50}\x{5F51}\x{5F52}\x{5F53}\x{5F54}'
. '\x{5F55}\x{5F56}\x{5F57}\x{5F58}\x{5F59}\x{5F5A}\x{5F5B}\x{5F5C}\x{5F5D}'
. '\x{5F5E}\x{5F5F}\x{5F60}\x{5F61}\x{5F62}\x{5F63}\x{5F64}\x{5F65}\x{5F66}'
. '\x{5F67}\x{5F68}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}\x{5F6D}\x{5F6E}\x{5F6F}'
. '\x{5F70}\x{5F71}\x{5F72}\x{5F73}\x{5F74}\x{5F75}\x{5F76}\x{5F77}\x{5F78}'
. '\x{5F79}\x{5F7A}\x{5F7B}\x{5F7C}\x{5F7D}\x{5F7E}\x{5F7F}\x{5F80}\x{5F81}'
. '\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F86}\x{5F87}\x{5F88}\x{5F89}\x{5F8A}'
. '\x{5F8B}\x{5F8C}\x{5F8D}\x{5F8E}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F94}'
. '\x{5F95}\x{5F96}\x{5F97}\x{5F98}\x{5F99}\x{5F9B}\x{5F9C}\x{5F9D}\x{5F9E}'
. '\x{5F9F}\x{5FA0}\x{5FA1}\x{5FA2}\x{5FA5}\x{5FA6}\x{5FA7}\x{5FA8}\x{5FA9}'
. '\x{5FAA}\x{5FAB}\x{5FAC}\x{5FAD}\x{5FAE}\x{5FAF}\x{5FB1}\x{5FB2}\x{5FB3}'
. '\x{5FB4}\x{5FB5}\x{5FB6}\x{5FB7}\x{5FB8}\x{5FB9}\x{5FBA}\x{5FBB}\x{5FBC}'
. '\x{5FBD}\x{5FBE}\x{5FBF}\x{5FC0}\x{5FC1}\x{5FC3}\x{5FC4}\x{5FC5}\x{5FC6}'
. '\x{5FC7}\x{5FC8}\x{5FC9}\x{5FCA}\x{5FCB}\x{5FCC}\x{5FCD}\x{5FCF}\x{5FD0}'
. '\x{5FD1}\x{5FD2}\x{5FD3}\x{5FD4}\x{5FD5}\x{5FD6}\x{5FD7}\x{5FD8}\x{5FD9}'
. '\x{5FDA}\x{5FDC}\x{5FDD}\x{5FDE}\x{5FE0}\x{5FE1}\x{5FE3}\x{5FE4}\x{5FE5}'
. '\x{5FE6}\x{5FE7}\x{5FE8}\x{5FE9}\x{5FEA}\x{5FEB}\x{5FED}\x{5FEE}\x{5FEF}'
. '\x{5FF0}\x{5FF1}\x{5FF2}\x{5FF3}\x{5FF4}\x{5FF5}\x{5FF6}\x{5FF7}\x{5FF8}'
. '\x{5FF9}\x{5FFA}\x{5FFB}\x{5FFD}\x{5FFE}\x{5FFF}\x{6000}\x{6001}\x{6002}'
. '\x{6003}\x{6004}\x{6005}\x{6006}\x{6007}\x{6008}\x{6009}\x{600A}\x{600B}'
. '\x{600C}\x{600D}\x{600E}\x{600F}\x{6010}\x{6011}\x{6012}\x{6013}\x{6014}'
. '\x{6015}\x{6016}\x{6017}\x{6018}\x{6019}\x{601A}\x{601B}\x{601C}\x{601D}'
. '\x{601E}\x{601F}\x{6020}\x{6021}\x{6022}\x{6024}\x{6025}\x{6026}\x{6027}'
. '\x{6028}\x{6029}\x{602A}\x{602B}\x{602C}\x{602D}\x{602E}\x{602F}\x{6030}'
. '\x{6031}\x{6032}\x{6033}\x{6034}\x{6035}\x{6036}\x{6037}\x{6038}\x{6039}'
. '\x{603A}\x{603B}\x{603C}\x{603D}\x{603E}\x{603F}\x{6040}\x{6041}\x{6042}'
. '\x{6043}\x{6044}\x{6045}\x{6046}\x{6047}\x{6048}\x{6049}\x{604A}\x{604B}'
. '\x{604C}\x{604D}\x{604E}\x{604F}\x{6050}\x{6051}\x{6052}\x{6053}\x{6054}'
. '\x{6055}\x{6057}\x{6058}\x{6059}\x{605A}\x{605B}\x{605C}\x{605D}\x{605E}'
. '\x{605F}\x{6062}\x{6063}\x{6064}\x{6065}\x{6066}\x{6067}\x{6068}\x{6069}'
. '\x{606A}\x{606B}\x{606C}\x{606D}\x{606E}\x{606F}\x{6070}\x{6072}\x{6073}'
. '\x{6075}\x{6076}\x{6077}\x{6078}\x{6079}\x{607A}\x{607B}\x{607C}\x{607D}'
. '\x{607E}\x{607F}\x{6080}\x{6081}\x{6082}\x{6083}\x{6084}\x{6085}\x{6086}'
. '\x{6087}\x{6088}\x{6089}\x{608A}\x{608B}\x{608C}\x{608D}\x{608E}\x{608F}'
. '\x{6090}\x{6092}\x{6094}\x{6095}\x{6096}\x{6097}\x{6098}\x{6099}\x{609A}'
. '\x{609B}\x{609C}\x{609D}\x{609E}\x{609F}\x{60A0}\x{60A1}\x{60A2}\x{60A3}'
. '\x{60A4}\x{60A6}\x{60A7}\x{60A8}\x{60AA}\x{60AB}\x{60AC}\x{60AD}\x{60AE}'
. '\x{60AF}\x{60B0}\x{60B1}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B7}'
. '\x{60B8}\x{60B9}\x{60BA}\x{60BB}\x{60BC}\x{60BD}\x{60BE}\x{60BF}\x{60C0}'
. '\x{60C1}\x{60C2}\x{60C3}\x{60C4}\x{60C5}\x{60C6}\x{60C7}\x{60C8}\x{60C9}'
. '\x{60CA}\x{60CB}\x{60CC}\x{60CD}\x{60CE}\x{60CF}\x{60D0}\x{60D1}\x{60D3}'
. '\x{60D4}\x{60D5}\x{60D7}\x{60D8}\x{60D9}\x{60DA}\x{60DB}\x{60DC}\x{60DD}'
. '\x{60DF}\x{60E0}\x{60E1}\x{60E2}\x{60E4}\x{60E6}\x{60E7}\x{60E8}\x{60E9}'
. '\x{60EA}\x{60EB}\x{60EC}\x{60ED}\x{60EE}\x{60EF}\x{60F0}\x{60F1}\x{60F2}'
. '\x{60F3}\x{60F4}\x{60F5}\x{60F6}\x{60F7}\x{60F8}\x{60F9}\x{60FA}\x{60FB}'
. '\x{60FC}\x{60FE}\x{60FF}\x{6100}\x{6101}\x{6103}\x{6104}\x{6105}\x{6106}'
. '\x{6108}\x{6109}\x{610A}\x{610B}\x{610C}\x{610D}\x{610E}\x{610F}\x{6110}'
. '\x{6112}\x{6113}\x{6114}\x{6115}\x{6116}\x{6117}\x{6118}\x{6119}\x{611A}'
. '\x{611B}\x{611C}\x{611D}\x{611F}\x{6120}\x{6122}\x{6123}\x{6124}\x{6125}'
. '\x{6126}\x{6127}\x{6128}\x{6129}\x{612A}\x{612B}\x{612C}\x{612D}\x{612E}'
. '\x{612F}\x{6130}\x{6132}\x{6134}\x{6136}\x{6137}\x{613A}\x{613B}\x{613C}'
. '\x{613D}\x{613E}\x{613F}\x{6140}\x{6141}\x{6142}\x{6143}\x{6144}\x{6145}'
. '\x{6146}\x{6147}\x{6148}\x{6149}\x{614A}\x{614B}\x{614C}\x{614D}\x{614E}'
. '\x{614F}\x{6150}\x{6151}\x{6152}\x{6153}\x{6154}\x{6155}\x{6156}\x{6157}'
. '\x{6158}\x{6159}\x{615A}\x{615B}\x{615C}\x{615D}\x{615E}\x{615F}\x{6161}'
. '\x{6162}\x{6163}\x{6164}\x{6165}\x{6166}\x{6167}\x{6168}\x{6169}\x{616A}'
. '\x{616B}\x{616C}\x{616D}\x{616E}\x{6170}\x{6171}\x{6172}\x{6173}\x{6174}'
. '\x{6175}\x{6176}\x{6177}\x{6178}\x{6179}\x{617A}\x{617C}\x{617E}\x{6180}'
. '\x{6181}\x{6182}\x{6183}\x{6184}\x{6185}\x{6187}\x{6188}\x{6189}\x{618A}'
. '\x{618B}\x{618C}\x{618D}\x{618E}\x{618F}\x{6190}\x{6191}\x{6192}\x{6193}'
. '\x{6194}\x{6195}\x{6196}\x{6198}\x{6199}\x{619A}\x{619B}\x{619D}\x{619E}'
. '\x{619F}\x{61A0}\x{61A1}\x{61A2}\x{61A3}\x{61A4}\x{61A5}\x{61A6}\x{61A7}'
. '\x{61A8}\x{61A9}\x{61AA}\x{61AB}\x{61AC}\x{61AD}\x{61AE}\x{61AF}\x{61B0}'
. '\x{61B1}\x{61B2}\x{61B3}\x{61B4}\x{61B5}\x{61B6}\x{61B7}\x{61B8}\x{61BA}'
. '\x{61BC}\x{61BD}\x{61BE}\x{61BF}\x{61C0}\x{61C1}\x{61C2}\x{61C3}\x{61C4}'
. '\x{61C5}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}'
. '\x{61CE}\x{61CF}\x{61D0}\x{61D1}\x{61D2}\x{61D4}\x{61D6}\x{61D7}\x{61D8}'
. '\x{61D9}\x{61DA}\x{61DB}\x{61DC}\x{61DD}\x{61DE}\x{61DF}\x{61E0}\x{61E1}'
. '\x{61E2}\x{61E3}\x{61E4}\x{61E5}\x{61E6}\x{61E7}\x{61E8}\x{61E9}\x{61EA}'
. '\x{61EB}\x{61ED}\x{61EE}\x{61F0}\x{61F1}\x{61F2}\x{61F3}\x{61F5}\x{61F6}'
. '\x{61F7}\x{61F8}\x{61F9}\x{61FA}\x{61FB}\x{61FC}\x{61FD}\x{61FE}\x{61FF}'
. '\x{6200}\x{6201}\x{6202}\x{6203}\x{6204}\x{6206}\x{6207}\x{6208}\x{6209}'
. '\x{620A}\x{620B}\x{620C}\x{620D}\x{620E}\x{620F}\x{6210}\x{6211}\x{6212}'
. '\x{6213}\x{6214}\x{6215}\x{6216}\x{6217}\x{6218}\x{6219}\x{621A}\x{621B}'
. '\x{621C}\x{621D}\x{621E}\x{621F}\x{6220}\x{6221}\x{6222}\x{6223}\x{6224}'
. '\x{6225}\x{6226}\x{6227}\x{6228}\x{6229}\x{622A}\x{622B}\x{622C}\x{622D}'
. '\x{622E}\x{622F}\x{6230}\x{6231}\x{6232}\x{6233}\x{6234}\x{6236}\x{6237}'
. '\x{6238}\x{623A}\x{623B}\x{623C}\x{623D}\x{623E}\x{623F}\x{6240}\x{6241}'
. '\x{6242}\x{6243}\x{6244}\x{6245}\x{6246}\x{6247}\x{6248}\x{6249}\x{624A}'
. '\x{624B}\x{624C}\x{624D}\x{624E}\x{624F}\x{6250}\x{6251}\x{6252}\x{6253}'
. '\x{6254}\x{6255}\x{6256}\x{6258}\x{6259}\x{625A}\x{625B}\x{625C}\x{625D}'
. '\x{625E}\x{625F}\x{6260}\x{6261}\x{6262}\x{6263}\x{6264}\x{6265}\x{6266}'
. '\x{6267}\x{6268}\x{6269}\x{626A}\x{626B}\x{626C}\x{626D}\x{626E}\x{626F}'
. '\x{6270}\x{6271}\x{6272}\x{6273}\x{6274}\x{6275}\x{6276}\x{6277}\x{6278}'
. '\x{6279}\x{627A}\x{627B}\x{627C}\x{627D}\x{627E}\x{627F}\x{6280}\x{6281}'
. '\x{6283}\x{6284}\x{6285}\x{6286}\x{6287}\x{6288}\x{6289}\x{628A}\x{628B}'
. '\x{628C}\x{628E}\x{628F}\x{6290}\x{6291}\x{6292}\x{6293}\x{6294}\x{6295}'
. '\x{6296}\x{6297}\x{6298}\x{6299}\x{629A}\x{629B}\x{629C}\x{629E}\x{629F}'
. '\x{62A0}\x{62A1}\x{62A2}\x{62A3}\x{62A4}\x{62A5}\x{62A7}\x{62A8}\x{62A9}'
. '\x{62AA}\x{62AB}\x{62AC}\x{62AD}\x{62AE}\x{62AF}\x{62B0}\x{62B1}\x{62B2}'
. '\x{62B3}\x{62B4}\x{62B5}\x{62B6}\x{62B7}\x{62B8}\x{62B9}\x{62BA}\x{62BB}'
. '\x{62BC}\x{62BD}\x{62BE}\x{62BF}\x{62C0}\x{62C1}\x{62C2}\x{62C3}\x{62C4}'
. '\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CB}\x{62CC}\x{62CD}'
. '\x{62CE}\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D5}\x{62D6}'
. '\x{62D7}\x{62D8}\x{62D9}\x{62DA}\x{62DB}\x{62DC}\x{62DD}\x{62DF}\x{62E0}'
. '\x{62E1}\x{62E2}\x{62E3}\x{62E4}\x{62E5}\x{62E6}\x{62E7}\x{62E8}\x{62E9}'
. '\x{62EB}\x{62EC}\x{62ED}\x{62EE}\x{62EF}\x{62F0}\x{62F1}\x{62F2}\x{62F3}'
. '\x{62F4}\x{62F5}\x{62F6}\x{62F7}\x{62F8}\x{62F9}\x{62FA}\x{62FB}\x{62FC}'
. '\x{62FD}\x{62FE}\x{62FF}\x{6300}\x{6301}\x{6302}\x{6303}\x{6304}\x{6305}'
. '\x{6306}\x{6307}\x{6308}\x{6309}\x{630B}\x{630C}\x{630D}\x{630E}\x{630F}'
. '\x{6310}\x{6311}\x{6312}\x{6313}\x{6314}\x{6315}\x{6316}\x{6318}\x{6319}'
. '\x{631A}\x{631B}\x{631C}\x{631D}\x{631E}\x{631F}\x{6320}\x{6321}\x{6322}'
. '\x{6323}\x{6324}\x{6325}\x{6326}\x{6327}\x{6328}\x{6329}\x{632A}\x{632B}'
. '\x{632C}\x{632D}\x{632E}\x{632F}\x{6330}\x{6332}\x{6333}\x{6334}\x{6336}'
. '\x{6338}\x{6339}\x{633A}\x{633B}\x{633C}\x{633D}\x{633E}\x{6340}\x{6341}'
. '\x{6342}\x{6343}\x{6344}\x{6345}\x{6346}\x{6347}\x{6348}\x{6349}\x{634A}'
. '\x{634B}\x{634C}\x{634D}\x{634E}\x{634F}\x{6350}\x{6351}\x{6352}\x{6353}'
. '\x{6354}\x{6355}\x{6356}\x{6357}\x{6358}\x{6359}\x{635A}\x{635C}\x{635D}'
. '\x{635E}\x{635F}\x{6360}\x{6361}\x{6362}\x{6363}\x{6364}\x{6365}\x{6366}'
. '\x{6367}\x{6368}\x{6369}\x{636A}\x{636B}\x{636C}\x{636D}\x{636E}\x{636F}'
. '\x{6370}\x{6371}\x{6372}\x{6373}\x{6374}\x{6375}\x{6376}\x{6377}\x{6378}'
. '\x{6379}\x{637A}\x{637B}\x{637C}\x{637D}\x{637E}\x{6380}\x{6381}\x{6382}'
. '\x{6383}\x{6384}\x{6385}\x{6386}\x{6387}\x{6388}\x{6389}\x{638A}\x{638C}'
. '\x{638D}\x{638E}\x{638F}\x{6390}\x{6391}\x{6392}\x{6394}\x{6395}\x{6396}'
. '\x{6397}\x{6398}\x{6399}\x{639A}\x{639B}\x{639C}\x{639D}\x{639E}\x{639F}'
. '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A4}\x{63A5}\x{63A6}\x{63A7}\x{63A8}'
. '\x{63A9}\x{63AA}\x{63AB}\x{63AC}\x{63AD}\x{63AE}\x{63AF}\x{63B0}\x{63B1}'
. '\x{63B2}\x{63B3}\x{63B4}\x{63B5}\x{63B6}\x{63B7}\x{63B8}\x{63B9}\x{63BA}'
. '\x{63BC}\x{63BD}\x{63BE}\x{63BF}\x{63C0}\x{63C1}\x{63C2}\x{63C3}\x{63C4}'
. '\x{63C5}\x{63C6}\x{63C7}\x{63C8}\x{63C9}\x{63CA}\x{63CB}\x{63CC}\x{63CD}'
. '\x{63CE}\x{63CF}\x{63D0}\x{63D2}\x{63D3}\x{63D4}\x{63D5}\x{63D6}\x{63D7}'
. '\x{63D8}\x{63D9}\x{63DA}\x{63DB}\x{63DC}\x{63DD}\x{63DE}\x{63DF}\x{63E0}'
. '\x{63E1}\x{63E2}\x{63E3}\x{63E4}\x{63E5}\x{63E6}\x{63E7}\x{63E8}\x{63E9}'
. '\x{63EA}\x{63EB}\x{63EC}\x{63ED}\x{63EE}\x{63EF}\x{63F0}\x{63F1}\x{63F2}'
. '\x{63F3}\x{63F4}\x{63F5}\x{63F6}\x{63F7}\x{63F8}\x{63F9}\x{63FA}\x{63FB}'
. '\x{63FC}\x{63FD}\x{63FE}\x{63FF}\x{6400}\x{6401}\x{6402}\x{6403}\x{6404}'
. '\x{6405}\x{6406}\x{6408}\x{6409}\x{640A}\x{640B}\x{640C}\x{640D}\x{640E}'
. '\x{640F}\x{6410}\x{6411}\x{6412}\x{6413}\x{6414}\x{6415}\x{6416}\x{6417}'
. '\x{6418}\x{6419}\x{641A}\x{641B}\x{641C}\x{641D}\x{641E}\x{641F}\x{6420}'
. '\x{6421}\x{6422}\x{6423}\x{6424}\x{6425}\x{6426}\x{6427}\x{6428}\x{6429}'
. '\x{642A}\x{642B}\x{642C}\x{642D}\x{642E}\x{642F}\x{6430}\x{6431}\x{6432}'
. '\x{6433}\x{6434}\x{6435}\x{6436}\x{6437}\x{6438}\x{6439}\x{643A}\x{643D}'
. '\x{643E}\x{643F}\x{6440}\x{6441}\x{6443}\x{6444}\x{6445}\x{6446}\x{6447}'
. '\x{6448}\x{644A}\x{644B}\x{644C}\x{644D}\x{644E}\x{644F}\x{6450}\x{6451}'
. '\x{6452}\x{6453}\x{6454}\x{6455}\x{6456}\x{6457}\x{6458}\x{6459}\x{645B}'
. '\x{645C}\x{645D}\x{645E}\x{645F}\x{6460}\x{6461}\x{6462}\x{6463}\x{6464}'
. '\x{6465}\x{6466}\x{6467}\x{6468}\x{6469}\x{646A}\x{646B}\x{646C}\x{646D}'
. '\x{646E}\x{646F}\x{6470}\x{6471}\x{6472}\x{6473}\x{6474}\x{6475}\x{6476}'
. '\x{6477}\x{6478}\x{6479}\x{647A}\x{647B}\x{647C}\x{647D}\x{647F}\x{6480}'
. '\x{6481}\x{6482}\x{6483}\x{6484}\x{6485}\x{6487}\x{6488}\x{6489}\x{648A}'
. '\x{648B}\x{648C}\x{648D}\x{648E}\x{648F}\x{6490}\x{6491}\x{6492}\x{6493}'
. '\x{6494}\x{6495}\x{6496}\x{6497}\x{6498}\x{6499}\x{649A}\x{649B}\x{649C}'
. '\x{649D}\x{649E}\x{649F}\x{64A0}\x{64A2}\x{64A3}\x{64A4}\x{64A5}\x{64A6}'
. '\x{64A7}\x{64A8}\x{64A9}\x{64AA}\x{64AB}\x{64AC}\x{64AD}\x{64AE}\x{64B0}'
. '\x{64B1}\x{64B2}\x{64B3}\x{64B4}\x{64B5}\x{64B7}\x{64B8}\x{64B9}\x{64BA}'
. '\x{64BB}\x{64BC}\x{64BD}\x{64BE}\x{64BF}\x{64C0}\x{64C1}\x{64C2}\x{64C3}'
. '\x{64C4}\x{64C5}\x{64C6}\x{64C7}\x{64C9}\x{64CA}\x{64CB}\x{64CC}\x{64CD}'
. '\x{64CE}\x{64CF}\x{64D0}\x{64D1}\x{64D2}\x{64D3}\x{64D4}\x{64D6}\x{64D7}'
. '\x{64D8}\x{64D9}\x{64DA}\x{64DB}\x{64DC}\x{64DD}\x{64DE}\x{64DF}\x{64E0}'
. '\x{64E2}\x{64E3}\x{64E4}\x{64E6}\x{64E7}\x{64E8}\x{64E9}\x{64EA}\x{64EB}'
. '\x{64EC}\x{64ED}\x{64EF}\x{64F0}\x{64F1}\x{64F2}\x{64F3}\x{64F4}\x{64F6}'
. '\x{64F7}\x{64F8}\x{64FA}\x{64FB}\x{64FC}\x{64FD}\x{64FE}\x{64FF}\x{6500}'
. '\x{6501}\x{6503}\x{6504}\x{6505}\x{6506}\x{6507}\x{6508}\x{6509}\x{650B}'
. '\x{650C}\x{650D}\x{650E}\x{650F}\x{6510}\x{6511}\x{6512}\x{6513}\x{6514}'
. '\x{6515}\x{6516}\x{6517}\x{6518}\x{6519}\x{651A}\x{651B}\x{651C}\x{651D}'
. '\x{651E}\x{6520}\x{6521}\x{6522}\x{6523}\x{6524}\x{6525}\x{6526}\x{6527}'
. '\x{6529}\x{652A}\x{652B}\x{652C}\x{652D}\x{652E}\x{652F}\x{6530}\x{6531}'
. '\x{6532}\x{6533}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}\x{653A}'
. '\x{653B}\x{653C}\x{653D}\x{653E}\x{653F}\x{6541}\x{6543}\x{6544}\x{6545}'
. '\x{6546}\x{6547}\x{6548}\x{6549}\x{654A}\x{654B}\x{654C}\x{654D}\x{654E}'
. '\x{654F}\x{6550}\x{6551}\x{6552}\x{6553}\x{6554}\x{6555}\x{6556}\x{6557}'
. '\x{6558}\x{6559}\x{655B}\x{655C}\x{655D}\x{655E}\x{6560}\x{6561}\x{6562}'
. '\x{6563}\x{6564}\x{6565}\x{6566}\x{6567}\x{6568}\x{6569}\x{656A}\x{656B}'
. '\x{656C}\x{656E}\x{656F}\x{6570}\x{6571}\x{6572}\x{6573}\x{6574}\x{6575}'
. '\x{6576}\x{6577}\x{6578}\x{6579}\x{657A}\x{657B}\x{657C}\x{657E}\x{657F}'
. '\x{6580}\x{6581}\x{6582}\x{6583}\x{6584}\x{6585}\x{6586}\x{6587}\x{6588}'
. '\x{6589}\x{658B}\x{658C}\x{658D}\x{658E}\x{658F}\x{6590}\x{6591}\x{6592}'
. '\x{6593}\x{6594}\x{6595}\x{6596}\x{6597}\x{6598}\x{6599}\x{659B}\x{659C}'
. '\x{659D}\x{659E}\x{659F}\x{65A0}\x{65A1}\x{65A2}\x{65A3}\x{65A4}\x{65A5}'
. '\x{65A6}\x{65A7}\x{65A8}\x{65A9}\x{65AA}\x{65AB}\x{65AC}\x{65AD}\x{65AE}'
. '\x{65AF}\x{65B0}\x{65B1}\x{65B2}\x{65B3}\x{65B4}\x{65B6}\x{65B7}\x{65B8}'
. '\x{65B9}\x{65BA}\x{65BB}\x{65BC}\x{65BD}\x{65BF}\x{65C0}\x{65C1}\x{65C2}'
. '\x{65C3}\x{65C4}\x{65C5}\x{65C6}\x{65C7}\x{65CA}\x{65CB}\x{65CC}\x{65CD}'
. '\x{65CE}\x{65CF}\x{65D0}\x{65D2}\x{65D3}\x{65D4}\x{65D5}\x{65D6}\x{65D7}'
. '\x{65DA}\x{65DB}\x{65DD}\x{65DE}\x{65DF}\x{65E0}\x{65E1}\x{65E2}\x{65E3}'
. '\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}\x{65EB}\x{65EC}\x{65ED}\x{65EE}'
. '\x{65EF}\x{65F0}\x{65F1}\x{65F2}\x{65F3}\x{65F4}\x{65F5}\x{65F6}\x{65F7}'
. '\x{65F8}\x{65FA}\x{65FB}\x{65FC}\x{65FD}\x{6600}\x{6601}\x{6602}\x{6603}'
. '\x{6604}\x{6605}\x{6606}\x{6607}\x{6608}\x{6609}\x{660A}\x{660B}\x{660C}'
. '\x{660D}\x{660E}\x{660F}\x{6610}\x{6611}\x{6612}\x{6613}\x{6614}\x{6615}'
. '\x{6616}\x{6618}\x{6619}\x{661A}\x{661B}\x{661C}\x{661D}\x{661F}\x{6620}'
. '\x{6621}\x{6622}\x{6623}\x{6624}\x{6625}\x{6626}\x{6627}\x{6628}\x{6629}'
. '\x{662A}\x{662B}\x{662D}\x{662E}\x{662F}\x{6630}\x{6631}\x{6632}\x{6633}'
. '\x{6634}\x{6635}\x{6636}\x{6639}\x{663A}\x{663C}\x{663D}\x{663E}\x{6640}'
. '\x{6641}\x{6642}\x{6643}\x{6644}\x{6645}\x{6646}\x{6647}\x{6649}\x{664A}'
. '\x{664B}\x{664C}\x{664E}\x{664F}\x{6650}\x{6651}\x{6652}\x{6653}\x{6654}'
. '\x{6655}\x{6656}\x{6657}\x{6658}\x{6659}\x{665A}\x{665B}\x{665C}\x{665D}'
. '\x{665E}\x{665F}\x{6661}\x{6662}\x{6664}\x{6665}\x{6666}\x{6668}\x{6669}'
. '\x{666A}\x{666B}\x{666C}\x{666D}\x{666E}\x{666F}\x{6670}\x{6671}\x{6672}'
. '\x{6673}\x{6674}\x{6675}\x{6676}\x{6677}\x{6678}\x{6679}\x{667A}\x{667B}'
. '\x{667C}\x{667D}\x{667E}\x{667F}\x{6680}\x{6681}\x{6682}\x{6683}\x{6684}'
. '\x{6685}\x{6686}\x{6687}\x{6688}\x{6689}\x{668A}\x{668B}\x{668C}\x{668D}'
. '\x{668E}\x{668F}\x{6690}\x{6691}\x{6693}\x{6694}\x{6695}\x{6696}\x{6697}'
. '\x{6698}\x{6699}\x{669A}\x{669B}\x{669D}\x{669F}\x{66A0}\x{66A1}\x{66A2}'
. '\x{66A3}\x{66A4}\x{66A5}\x{66A6}\x{66A7}\x{66A8}\x{66A9}\x{66AA}\x{66AB}'
. '\x{66AE}\x{66AF}\x{66B0}\x{66B1}\x{66B2}\x{66B3}\x{66B4}\x{66B5}\x{66B6}'
. '\x{66B7}\x{66B8}\x{66B9}\x{66BA}\x{66BB}\x{66BC}\x{66BD}\x{66BE}\x{66BF}'
. '\x{66C0}\x{66C1}\x{66C2}\x{66C3}\x{66C4}\x{66C5}\x{66C6}\x{66C7}\x{66C8}'
. '\x{66C9}\x{66CA}\x{66CB}\x{66CC}\x{66CD}\x{66CE}\x{66CF}\x{66D1}\x{66D2}'
. '\x{66D4}\x{66D5}\x{66D6}\x{66D8}\x{66D9}\x{66DA}\x{66DB}\x{66DC}\x{66DD}'
. '\x{66DE}\x{66E0}\x{66E1}\x{66E2}\x{66E3}\x{66E4}\x{66E5}\x{66E6}\x{66E7}'
. '\x{66E8}\x{66E9}\x{66EA}\x{66EB}\x{66EC}\x{66ED}\x{66EE}\x{66F0}\x{66F1}'
. '\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F6}\x{66F7}\x{66F8}\x{66F9}\x{66FA}'
. '\x{66FB}\x{66FC}\x{66FE}\x{66FF}\x{6700}\x{6701}\x{6703}\x{6704}\x{6705}'
. '\x{6706}\x{6708}\x{6709}\x{670A}\x{670B}\x{670C}\x{670D}\x{670E}\x{670F}'
. '\x{6710}\x{6711}\x{6712}\x{6713}\x{6714}\x{6715}\x{6716}\x{6717}\x{6718}'
. '\x{671A}\x{671B}\x{671C}\x{671D}\x{671E}\x{671F}\x{6720}\x{6721}\x{6722}'
. '\x{6723}\x{6725}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}\x{672D}'
. '\x{672E}\x{672F}\x{6730}\x{6731}\x{6732}\x{6733}\x{6734}\x{6735}\x{6736}'
. '\x{6737}\x{6738}\x{6739}\x{673A}\x{673B}\x{673C}\x{673D}\x{673E}\x{673F}'
. '\x{6740}\x{6741}\x{6742}\x{6743}\x{6744}\x{6745}\x{6746}\x{6747}\x{6748}'
. '\x{6749}\x{674A}\x{674B}\x{674C}\x{674D}\x{674E}\x{674F}\x{6750}\x{6751}'
. '\x{6752}\x{6753}\x{6754}\x{6755}\x{6756}\x{6757}\x{6758}\x{6759}\x{675A}'
. '\x{675B}\x{675C}\x{675D}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}'
. '\x{6764}\x{6765}\x{6766}\x{6768}\x{6769}\x{676A}\x{676B}\x{676C}\x{676D}'
. '\x{676E}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}\x{6774}\x{6775}\x{6776}'
. '\x{6777}\x{6778}\x{6779}\x{677A}\x{677B}\x{677C}\x{677D}\x{677E}\x{677F}'
. '\x{6780}\x{6781}\x{6782}\x{6783}\x{6784}\x{6785}\x{6786}\x{6787}\x{6789}'
. '\x{678A}\x{678B}\x{678C}\x{678D}\x{678E}\x{678F}\x{6790}\x{6791}\x{6792}'
. '\x{6793}\x{6794}\x{6795}\x{6797}\x{6798}\x{6799}\x{679A}\x{679B}\x{679C}'
. '\x{679D}\x{679E}\x{679F}\x{67A0}\x{67A1}\x{67A2}\x{67A3}\x{67A4}\x{67A5}'
. '\x{67A6}\x{67A7}\x{67A8}\x{67AA}\x{67AB}\x{67AC}\x{67AD}\x{67AE}\x{67AF}'
. '\x{67B0}\x{67B1}\x{67B2}\x{67B3}\x{67B4}\x{67B5}\x{67B6}\x{67B7}\x{67B8}'
. '\x{67B9}\x{67BA}\x{67BB}\x{67BC}\x{67BE}\x{67C0}\x{67C1}\x{67C2}\x{67C3}'
. '\x{67C4}\x{67C5}\x{67C6}\x{67C7}\x{67C8}\x{67C9}\x{67CA}\x{67CB}\x{67CC}'
. '\x{67CD}\x{67CE}\x{67CF}\x{67D0}\x{67D1}\x{67D2}\x{67D3}\x{67D4}\x{67D6}'
. '\x{67D8}\x{67D9}\x{67DA}\x{67DB}\x{67DC}\x{67DD}\x{67DE}\x{67DF}\x{67E0}'
. '\x{67E1}\x{67E2}\x{67E3}\x{67E4}\x{67E5}\x{67E6}\x{67E7}\x{67E8}\x{67E9}'
. '\x{67EA}\x{67EB}\x{67EC}\x{67ED}\x{67EE}\x{67EF}\x{67F0}\x{67F1}\x{67F2}'
. '\x{67F3}\x{67F4}\x{67F5}\x{67F6}\x{67F7}\x{67F8}\x{67FA}\x{67FB}\x{67FC}'
. '\x{67FD}\x{67FE}\x{67FF}\x{6800}\x{6802}\x{6803}\x{6804}\x{6805}\x{6806}'
. '\x{6807}\x{6808}\x{6809}\x{680A}\x{680B}\x{680C}\x{680D}\x{680E}\x{680F}'
. '\x{6810}\x{6811}\x{6812}\x{6813}\x{6814}\x{6816}\x{6817}\x{6818}\x{6819}'
. '\x{681A}\x{681B}\x{681C}\x{681D}\x{681F}\x{6820}\x{6821}\x{6822}\x{6823}'
. '\x{6824}\x{6825}\x{6826}\x{6828}\x{6829}\x{682A}\x{682B}\x{682C}\x{682D}'
. '\x{682E}\x{682F}\x{6831}\x{6832}\x{6833}\x{6834}\x{6835}\x{6836}\x{6837}'
. '\x{6838}\x{6839}\x{683A}\x{683B}\x{683C}\x{683D}\x{683E}\x{683F}\x{6840}'
. '\x{6841}\x{6842}\x{6843}\x{6844}\x{6845}\x{6846}\x{6847}\x{6848}\x{6849}'
. '\x{684A}\x{684B}\x{684C}\x{684D}\x{684E}\x{684F}\x{6850}\x{6851}\x{6852}'
. '\x{6853}\x{6854}\x{6855}\x{6856}\x{6857}\x{685B}\x{685D}\x{6860}\x{6861}'
. '\x{6862}\x{6863}\x{6864}\x{6865}\x{6866}\x{6867}\x{6868}\x{6869}\x{686A}'
. '\x{686B}\x{686C}\x{686D}\x{686E}\x{686F}\x{6870}\x{6871}\x{6872}\x{6873}'
. '\x{6874}\x{6875}\x{6876}\x{6877}\x{6878}\x{6879}\x{687B}\x{687C}\x{687D}'
. '\x{687E}\x{687F}\x{6880}\x{6881}\x{6882}\x{6883}\x{6884}\x{6885}\x{6886}'
. '\x{6887}\x{6888}\x{6889}\x{688A}\x{688B}\x{688C}\x{688D}\x{688E}\x{688F}'
. '\x{6890}\x{6891}\x{6892}\x{6893}\x{6894}\x{6896}\x{6897}\x{6898}\x{689A}'
. '\x{689B}\x{689C}\x{689D}\x{689E}\x{689F}\x{68A0}\x{68A1}\x{68A2}\x{68A3}'
. '\x{68A4}\x{68A6}\x{68A7}\x{68A8}\x{68A9}\x{68AA}\x{68AB}\x{68AC}\x{68AD}'
. '\x{68AE}\x{68AF}\x{68B0}\x{68B1}\x{68B2}\x{68B3}\x{68B4}\x{68B5}\x{68B6}'
. '\x{68B7}\x{68B9}\x{68BB}\x{68BC}\x{68BD}\x{68BE}\x{68BF}\x{68C0}\x{68C1}'
. '\x{68C2}\x{68C4}\x{68C6}\x{68C7}\x{68C8}\x{68C9}\x{68CA}\x{68CB}\x{68CC}'
. '\x{68CD}\x{68CE}\x{68CF}\x{68D0}\x{68D1}\x{68D2}\x{68D3}\x{68D4}\x{68D5}'
. '\x{68D6}\x{68D7}\x{68D8}\x{68DA}\x{68DB}\x{68DC}\x{68DD}\x{68DE}\x{68DF}'
. '\x{68E0}\x{68E1}\x{68E3}\x{68E4}\x{68E6}\x{68E7}\x{68E8}\x{68E9}\x{68EA}'
. '\x{68EB}\x{68EC}\x{68ED}\x{68EE}\x{68EF}\x{68F0}\x{68F1}\x{68F2}\x{68F3}'
. '\x{68F4}\x{68F5}\x{68F6}\x{68F7}\x{68F8}\x{68F9}\x{68FA}\x{68FB}\x{68FC}'
. '\x{68FD}\x{68FE}\x{68FF}\x{6901}\x{6902}\x{6903}\x{6904}\x{6905}\x{6906}'
. '\x{6907}\x{6908}\x{690A}\x{690B}\x{690C}\x{690D}\x{690E}\x{690F}\x{6910}'
. '\x{6911}\x{6912}\x{6913}\x{6914}\x{6915}\x{6916}\x{6917}\x{6918}\x{6919}'
. '\x{691A}\x{691B}\x{691C}\x{691D}\x{691E}\x{691F}\x{6920}\x{6921}\x{6922}'
. '\x{6923}\x{6924}\x{6925}\x{6926}\x{6927}\x{6928}\x{6929}\x{692A}\x{692B}'
. '\x{692C}\x{692D}\x{692E}\x{692F}\x{6930}\x{6931}\x{6932}\x{6933}\x{6934}'
. '\x{6935}\x{6936}\x{6937}\x{6938}\x{6939}\x{693A}\x{693B}\x{693C}\x{693D}'
. '\x{693F}\x{6940}\x{6941}\x{6942}\x{6943}\x{6944}\x{6945}\x{6946}\x{6947}'
. '\x{6948}\x{6949}\x{694A}\x{694B}\x{694C}\x{694E}\x{694F}\x{6950}\x{6951}'
. '\x{6952}\x{6953}\x{6954}\x{6955}\x{6956}\x{6957}\x{6958}\x{6959}\x{695A}'
. '\x{695B}\x{695C}\x{695D}\x{695E}\x{695F}\x{6960}\x{6961}\x{6962}\x{6963}'
. '\x{6964}\x{6965}\x{6966}\x{6967}\x{6968}\x{6969}\x{696A}\x{696B}\x{696C}'
. '\x{696D}\x{696E}\x{696F}\x{6970}\x{6971}\x{6972}\x{6973}\x{6974}\x{6975}'
. '\x{6976}\x{6977}\x{6978}\x{6979}\x{697A}\x{697B}\x{697C}\x{697D}\x{697E}'
. '\x{697F}\x{6980}\x{6981}\x{6982}\x{6983}\x{6984}\x{6985}\x{6986}\x{6987}'
. '\x{6988}\x{6989}\x{698A}\x{698B}\x{698C}\x{698D}\x{698E}\x{698F}\x{6990}'
. '\x{6991}\x{6992}\x{6993}\x{6994}\x{6995}\x{6996}\x{6997}\x{6998}\x{6999}'
. '\x{699A}\x{699B}\x{699C}\x{699D}\x{699E}\x{69A0}\x{69A1}\x{69A3}\x{69A4}'
. '\x{69A5}\x{69A6}\x{69A7}\x{69A8}\x{69A9}\x{69AA}\x{69AB}\x{69AC}\x{69AD}'
. '\x{69AE}\x{69AF}\x{69B0}\x{69B1}\x{69B2}\x{69B3}\x{69B4}\x{69B5}\x{69B6}'
. '\x{69B7}\x{69B8}\x{69B9}\x{69BA}\x{69BB}\x{69BC}\x{69BD}\x{69BE}\x{69BF}'
. '\x{69C1}\x{69C2}\x{69C3}\x{69C4}\x{69C5}\x{69C6}\x{69C7}\x{69C8}\x{69C9}'
. '\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}\x{69CF}\x{69D0}\x{69D3}\x{69D4}'
. '\x{69D8}\x{69D9}\x{69DA}\x{69DB}\x{69DC}\x{69DD}\x{69DE}\x{69DF}\x{69E0}'
. '\x{69E1}\x{69E2}\x{69E3}\x{69E4}\x{69E5}\x{69E6}\x{69E7}\x{69E8}\x{69E9}'
. '\x{69EA}\x{69EB}\x{69EC}\x{69ED}\x{69EE}\x{69EF}\x{69F0}\x{69F1}\x{69F2}'
. '\x{69F3}\x{69F4}\x{69F5}\x{69F6}\x{69F7}\x{69F8}\x{69FA}\x{69FB}\x{69FC}'
. '\x{69FD}\x{69FE}\x{69FF}\x{6A00}\x{6A01}\x{6A02}\x{6A04}\x{6A05}\x{6A06}'
. '\x{6A07}\x{6A08}\x{6A09}\x{6A0A}\x{6A0B}\x{6A0D}\x{6A0E}\x{6A0F}\x{6A10}'
. '\x{6A11}\x{6A12}\x{6A13}\x{6A14}\x{6A15}\x{6A16}\x{6A17}\x{6A18}\x{6A19}'
. '\x{6A1A}\x{6A1B}\x{6A1D}\x{6A1E}\x{6A1F}\x{6A20}\x{6A21}\x{6A22}\x{6A23}'
. '\x{6A25}\x{6A26}\x{6A27}\x{6A28}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2C}\x{6A2D}'
. '\x{6A2E}\x{6A2F}\x{6A30}\x{6A31}\x{6A32}\x{6A33}\x{6A34}\x{6A35}\x{6A36}'
. '\x{6A38}\x{6A39}\x{6A3A}\x{6A3B}\x{6A3C}\x{6A3D}\x{6A3E}\x{6A3F}\x{6A40}'
. '\x{6A41}\x{6A42}\x{6A43}\x{6A44}\x{6A45}\x{6A46}\x{6A47}\x{6A48}\x{6A49}'
. '\x{6A4B}\x{6A4C}\x{6A4D}\x{6A4E}\x{6A4F}\x{6A50}\x{6A51}\x{6A52}\x{6A54}'
. '\x{6A55}\x{6A56}\x{6A57}\x{6A58}\x{6A59}\x{6A5A}\x{6A5B}\x{6A5D}\x{6A5E}'
. '\x{6A5F}\x{6A60}\x{6A61}\x{6A62}\x{6A63}\x{6A64}\x{6A65}\x{6A66}\x{6A67}'
. '\x{6A68}\x{6A69}\x{6A6A}\x{6A6B}\x{6A6C}\x{6A6D}\x{6A6F}\x{6A71}\x{6A72}'
. '\x{6A73}\x{6A74}\x{6A75}\x{6A76}\x{6A77}\x{6A78}\x{6A79}\x{6A7A}\x{6A7B}'
. '\x{6A7C}\x{6A7D}\x{6A7E}\x{6A7F}\x{6A80}\x{6A81}\x{6A82}\x{6A83}\x{6A84}'
. '\x{6A85}\x{6A87}\x{6A88}\x{6A89}\x{6A8B}\x{6A8C}\x{6A8D}\x{6A8E}\x{6A90}'
. '\x{6A91}\x{6A92}\x{6A93}\x{6A94}\x{6A95}\x{6A96}\x{6A97}\x{6A98}\x{6A9A}'
. '\x{6A9B}\x{6A9C}\x{6A9E}\x{6A9F}\x{6AA0}\x{6AA1}\x{6AA2}\x{6AA3}\x{6AA4}'
. '\x{6AA5}\x{6AA6}\x{6AA7}\x{6AA8}\x{6AA9}\x{6AAB}\x{6AAC}\x{6AAD}\x{6AAE}'
. '\x{6AAF}\x{6AB0}\x{6AB2}\x{6AB3}\x{6AB4}\x{6AB5}\x{6AB6}\x{6AB7}\x{6AB8}'
. '\x{6AB9}\x{6ABA}\x{6ABB}\x{6ABC}\x{6ABD}\x{6ABF}\x{6AC1}\x{6AC2}\x{6AC3}'
. '\x{6AC5}\x{6AC6}\x{6AC7}\x{6ACA}\x{6ACB}\x{6ACC}\x{6ACD}\x{6ACE}\x{6ACF}'
. '\x{6AD0}\x{6AD1}\x{6AD2}\x{6AD3}\x{6AD4}\x{6AD5}\x{6AD6}\x{6AD7}\x{6AD9}'
. '\x{6ADA}\x{6ADB}\x{6ADC}\x{6ADD}\x{6ADE}\x{6ADF}\x{6AE0}\x{6AE1}\x{6AE2}'
. '\x{6AE3}\x{6AE4}\x{6AE5}\x{6AE6}\x{6AE7}\x{6AE8}\x{6AEA}\x{6AEB}\x{6AEC}'
. '\x{6AED}\x{6AEE}\x{6AEF}\x{6AF0}\x{6AF1}\x{6AF2}\x{6AF3}\x{6AF4}\x{6AF5}'
. '\x{6AF6}\x{6AF7}\x{6AF8}\x{6AF9}\x{6AFA}\x{6AFB}\x{6AFC}\x{6AFD}\x{6AFE}'
. '\x{6AFF}\x{6B00}\x{6B01}\x{6B02}\x{6B03}\x{6B04}\x{6B05}\x{6B06}\x{6B07}'
. '\x{6B08}\x{6B09}\x{6B0A}\x{6B0B}\x{6B0C}\x{6B0D}\x{6B0F}\x{6B10}\x{6B11}'
. '\x{6B12}\x{6B13}\x{6B14}\x{6B15}\x{6B16}\x{6B17}\x{6B18}\x{6B19}\x{6B1A}'
. '\x{6B1C}\x{6B1D}\x{6B1E}\x{6B1F}\x{6B20}\x{6B21}\x{6B22}\x{6B23}\x{6B24}'
. '\x{6B25}\x{6B26}\x{6B27}\x{6B28}\x{6B29}\x{6B2A}\x{6B2B}\x{6B2C}\x{6B2D}'
. '\x{6B2F}\x{6B30}\x{6B31}\x{6B32}\x{6B33}\x{6B34}\x{6B36}\x{6B37}\x{6B38}'
. '\x{6B39}\x{6B3A}\x{6B3B}\x{6B3C}\x{6B3D}\x{6B3E}\x{6B3F}\x{6B41}\x{6B42}'
. '\x{6B43}\x{6B44}\x{6B45}\x{6B46}\x{6B47}\x{6B48}\x{6B49}\x{6B4A}\x{6B4B}'
. '\x{6B4C}\x{6B4D}\x{6B4E}\x{6B4F}\x{6B50}\x{6B51}\x{6B52}\x{6B53}\x{6B54}'
. '\x{6B55}\x{6B56}\x{6B59}\x{6B5A}\x{6B5B}\x{6B5C}\x{6B5E}\x{6B5F}\x{6B60}'
. '\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B65}\x{6B66}\x{6B67}\x{6B69}\x{6B6A}'
. '\x{6B6B}\x{6B6D}\x{6B6F}\x{6B70}\x{6B72}\x{6B73}\x{6B74}\x{6B76}\x{6B77}'
. '\x{6B78}\x{6B79}\x{6B7A}\x{6B7B}\x{6B7C}\x{6B7E}\x{6B7F}\x{6B80}\x{6B81}'
. '\x{6B82}\x{6B83}\x{6B84}\x{6B85}\x{6B86}\x{6B87}\x{6B88}\x{6B89}\x{6B8A}'
. '\x{6B8B}\x{6B8C}\x{6B8D}\x{6B8E}\x{6B8F}\x{6B90}\x{6B91}\x{6B92}\x{6B93}'
. '\x{6B94}\x{6B95}\x{6B96}\x{6B97}\x{6B98}\x{6B99}\x{6B9A}\x{6B9B}\x{6B9C}'
. '\x{6B9D}\x{6B9E}\x{6B9F}\x{6BA0}\x{6BA1}\x{6BA2}\x{6BA3}\x{6BA4}\x{6BA5}'
. '\x{6BA6}\x{6BA7}\x{6BA8}\x{6BA9}\x{6BAA}\x{6BAB}\x{6BAC}\x{6BAD}\x{6BAE}'
. '\x{6BAF}\x{6BB0}\x{6BB2}\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB6}\x{6BB7}\x{6BB9}'
. '\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBD}\x{6BBE}\x{6BBF}\x{6BC0}\x{6BC1}\x{6BC2}'
. '\x{6BC3}\x{6BC4}\x{6BC5}\x{6BC6}\x{6BC7}\x{6BC8}\x{6BC9}\x{6BCA}\x{6BCB}'
. '\x{6BCC}\x{6BCD}\x{6BCE}\x{6BCF}\x{6BD0}\x{6BD1}\x{6BD2}\x{6BD3}\x{6BD4}'
. '\x{6BD5}\x{6BD6}\x{6BD7}\x{6BD8}\x{6BD9}\x{6BDA}\x{6BDB}\x{6BDC}\x{6BDD}'
. '\x{6BDE}\x{6BDF}\x{6BE0}\x{6BE1}\x{6BE2}\x{6BE3}\x{6BE4}\x{6BE5}\x{6BE6}'
. '\x{6BE7}\x{6BE8}\x{6BEA}\x{6BEB}\x{6BEC}\x{6BED}\x{6BEE}\x{6BEF}\x{6BF0}'
. '\x{6BF2}\x{6BF3}\x{6BF5}\x{6BF6}\x{6BF7}\x{6BF8}\x{6BF9}\x{6BFB}\x{6BFC}'
. '\x{6BFD}\x{6BFE}\x{6BFF}\x{6C00}\x{6C01}\x{6C02}\x{6C03}\x{6C04}\x{6C05}'
. '\x{6C06}\x{6C07}\x{6C08}\x{6C09}\x{6C0B}\x{6C0C}\x{6C0D}\x{6C0E}\x{6C0F}'
. '\x{6C10}\x{6C11}\x{6C12}\x{6C13}\x{6C14}\x{6C15}\x{6C16}\x{6C18}\x{6C19}'
. '\x{6C1A}\x{6C1B}\x{6C1D}\x{6C1E}\x{6C1F}\x{6C20}\x{6C21}\x{6C22}\x{6C23}'
. '\x{6C24}\x{6C25}\x{6C26}\x{6C27}\x{6C28}\x{6C29}\x{6C2A}\x{6C2B}\x{6C2C}'
. '\x{6C2E}\x{6C2F}\x{6C30}\x{6C31}\x{6C32}\x{6C33}\x{6C34}\x{6C35}\x{6C36}'
. '\x{6C37}\x{6C38}\x{6C3A}\x{6C3B}\x{6C3D}\x{6C3E}\x{6C3F}\x{6C40}\x{6C41}'
. '\x{6C42}\x{6C43}\x{6C44}\x{6C46}\x{6C47}\x{6C48}\x{6C49}\x{6C4A}\x{6C4B}'
. '\x{6C4C}\x{6C4D}\x{6C4E}\x{6C4F}\x{6C50}\x{6C51}\x{6C52}\x{6C53}\x{6C54}'
. '\x{6C55}\x{6C56}\x{6C57}\x{6C58}\x{6C59}\x{6C5A}\x{6C5B}\x{6C5C}\x{6C5D}'
. '\x{6C5E}\x{6C5F}\x{6C60}\x{6C61}\x{6C62}\x{6C63}\x{6C64}\x{6C65}\x{6C66}'
. '\x{6C67}\x{6C68}\x{6C69}\x{6C6A}\x{6C6B}\x{6C6D}\x{6C6F}\x{6C70}\x{6C71}'
. '\x{6C72}\x{6C73}\x{6C74}\x{6C75}\x{6C76}\x{6C77}\x{6C78}\x{6C79}\x{6C7A}'
. '\x{6C7B}\x{6C7C}\x{6C7D}\x{6C7E}\x{6C7F}\x{6C80}\x{6C81}\x{6C82}\x{6C83}'
. '\x{6C84}\x{6C85}\x{6C86}\x{6C87}\x{6C88}\x{6C89}\x{6C8A}\x{6C8B}\x{6C8C}'
. '\x{6C8D}\x{6C8E}\x{6C8F}\x{6C90}\x{6C91}\x{6C92}\x{6C93}\x{6C94}\x{6C95}'
. '\x{6C96}\x{6C97}\x{6C98}\x{6C99}\x{6C9A}\x{6C9B}\x{6C9C}\x{6C9D}\x{6C9E}'
. '\x{6C9F}\x{6CA1}\x{6CA2}\x{6CA3}\x{6CA4}\x{6CA5}\x{6CA6}\x{6CA7}\x{6CA8}'
. '\x{6CA9}\x{6CAA}\x{6CAB}\x{6CAC}\x{6CAD}\x{6CAE}\x{6CAF}\x{6CB0}\x{6CB1}'
. '\x{6CB2}\x{6CB3}\x{6CB4}\x{6CB5}\x{6CB6}\x{6CB7}\x{6CB8}\x{6CB9}\x{6CBA}'
. '\x{6CBB}\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC0}\x{6CC1}\x{6CC2}\x{6CC3}'
. '\x{6CC4}\x{6CC5}\x{6CC6}\x{6CC7}\x{6CC8}\x{6CC9}\x{6CCA}\x{6CCB}\x{6CCC}'
. '\x{6CCD}\x{6CCE}\x{6CCF}\x{6CD0}\x{6CD1}\x{6CD2}\x{6CD3}\x{6CD4}\x{6CD5}'
. '\x{6CD6}\x{6CD7}\x{6CD9}\x{6CDA}\x{6CDB}\x{6CDC}\x{6CDD}\x{6CDE}\x{6CDF}'
. '\x{6CE0}\x{6CE1}\x{6CE2}\x{6CE3}\x{6CE4}\x{6CE5}\x{6CE6}\x{6CE7}\x{6CE8}'
. '\x{6CE9}\x{6CEA}\x{6CEB}\x{6CEC}\x{6CED}\x{6CEE}\x{6CEF}\x{6CF0}\x{6CF1}'
. '\x{6CF2}\x{6CF3}\x{6CF5}\x{6CF6}\x{6CF7}\x{6CF8}\x{6CF9}\x{6CFA}\x{6CFB}'
. '\x{6CFC}\x{6CFD}\x{6CFE}\x{6CFF}\x{6D00}\x{6D01}\x{6D03}\x{6D04}\x{6D05}'
. '\x{6D06}\x{6D07}\x{6D08}\x{6D09}\x{6D0A}\x{6D0B}\x{6D0C}\x{6D0D}\x{6D0E}'
. '\x{6D0F}\x{6D10}\x{6D11}\x{6D12}\x{6D13}\x{6D14}\x{6D15}\x{6D16}\x{6D17}'
. '\x{6D18}\x{6D19}\x{6D1A}\x{6D1B}\x{6D1D}\x{6D1E}\x{6D1F}\x{6D20}\x{6D21}'
. '\x{6D22}\x{6D23}\x{6D25}\x{6D26}\x{6D27}\x{6D28}\x{6D29}\x{6D2A}\x{6D2B}'
. '\x{6D2C}\x{6D2D}\x{6D2E}\x{6D2F}\x{6D30}\x{6D31}\x{6D32}\x{6D33}\x{6D34}'
. '\x{6D35}\x{6D36}\x{6D37}\x{6D38}\x{6D39}\x{6D3A}\x{6D3B}\x{6D3C}\x{6D3D}'
. '\x{6D3E}\x{6D3F}\x{6D40}\x{6D41}\x{6D42}\x{6D43}\x{6D44}\x{6D45}\x{6D46}'
. '\x{6D47}\x{6D48}\x{6D49}\x{6D4A}\x{6D4B}\x{6D4C}\x{6D4D}\x{6D4E}\x{6D4F}'
. '\x{6D50}\x{6D51}\x{6D52}\x{6D53}\x{6D54}\x{6D55}\x{6D56}\x{6D57}\x{6D58}'
. '\x{6D59}\x{6D5A}\x{6D5B}\x{6D5C}\x{6D5D}\x{6D5E}\x{6D5F}\x{6D60}\x{6D61}'
. '\x{6D62}\x{6D63}\x{6D64}\x{6D65}\x{6D66}\x{6D67}\x{6D68}\x{6D69}\x{6D6A}'
. '\x{6D6B}\x{6D6C}\x{6D6D}\x{6D6E}\x{6D6F}\x{6D70}\x{6D72}\x{6D73}\x{6D74}'
. '\x{6D75}\x{6D76}\x{6D77}\x{6D78}\x{6D79}\x{6D7A}\x{6D7B}\x{6D7C}\x{6D7D}'
. '\x{6D7E}\x{6D7F}\x{6D80}\x{6D82}\x{6D83}\x{6D84}\x{6D85}\x{6D86}\x{6D87}'
. '\x{6D88}\x{6D89}\x{6D8A}\x{6D8B}\x{6D8C}\x{6D8D}\x{6D8E}\x{6D8F}\x{6D90}'
. '\x{6D91}\x{6D92}\x{6D93}\x{6D94}\x{6D95}\x{6D97}\x{6D98}\x{6D99}\x{6D9A}'
. '\x{6D9B}\x{6D9D}\x{6D9E}\x{6D9F}\x{6DA0}\x{6DA1}\x{6DA2}\x{6DA3}\x{6DA4}'
. '\x{6DA5}\x{6DA6}\x{6DA7}\x{6DA8}\x{6DA9}\x{6DAA}\x{6DAB}\x{6DAC}\x{6DAD}'
. '\x{6DAE}\x{6DAF}\x{6DB2}\x{6DB3}\x{6DB4}\x{6DB5}\x{6DB7}\x{6DB8}\x{6DB9}'
. '\x{6DBA}\x{6DBB}\x{6DBC}\x{6DBD}\x{6DBE}\x{6DBF}\x{6DC0}\x{6DC1}\x{6DC2}'
. '\x{6DC3}\x{6DC4}\x{6DC5}\x{6DC6}\x{6DC7}\x{6DC8}\x{6DC9}\x{6DCA}\x{6DCB}'
. '\x{6DCC}\x{6DCD}\x{6DCE}\x{6DCF}\x{6DD0}\x{6DD1}\x{6DD2}\x{6DD3}\x{6DD4}'
. '\x{6DD5}\x{6DD6}\x{6DD7}\x{6DD8}\x{6DD9}\x{6DDA}\x{6DDB}\x{6DDC}\x{6DDD}'
. '\x{6DDE}\x{6DDF}\x{6DE0}\x{6DE1}\x{6DE2}\x{6DE3}\x{6DE4}\x{6DE5}\x{6DE6}'
. '\x{6DE7}\x{6DE8}\x{6DE9}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DED}\x{6DEE}\x{6DEF}'
. '\x{6DF0}\x{6DF1}\x{6DF2}\x{6DF3}\x{6DF4}\x{6DF5}\x{6DF6}\x{6DF7}\x{6DF8}'
. '\x{6DF9}\x{6DFA}\x{6DFB}\x{6DFC}\x{6DFD}\x{6E00}\x{6E03}\x{6E04}\x{6E05}'
. '\x{6E07}\x{6E08}\x{6E09}\x{6E0A}\x{6E0B}\x{6E0C}\x{6E0D}\x{6E0E}\x{6E0F}'
. '\x{6E10}\x{6E11}\x{6E14}\x{6E15}\x{6E16}\x{6E17}\x{6E19}\x{6E1A}\x{6E1B}'
. '\x{6E1C}\x{6E1D}\x{6E1E}\x{6E1F}\x{6E20}\x{6E21}\x{6E22}\x{6E23}\x{6E24}'
. '\x{6E25}\x{6E26}\x{6E27}\x{6E28}\x{6E29}\x{6E2B}\x{6E2C}\x{6E2D}\x{6E2E}'
. '\x{6E2F}\x{6E30}\x{6E31}\x{6E32}\x{6E33}\x{6E34}\x{6E35}\x{6E36}\x{6E37}'
. '\x{6E38}\x{6E39}\x{6E3A}\x{6E3B}\x{6E3C}\x{6E3D}\x{6E3E}\x{6E3F}\x{6E40}'
. '\x{6E41}\x{6E42}\x{6E43}\x{6E44}\x{6E45}\x{6E46}\x{6E47}\x{6E48}\x{6E49}'
. '\x{6E4A}\x{6E4B}\x{6E4D}\x{6E4E}\x{6E4F}\x{6E50}\x{6E51}\x{6E52}\x{6E53}'
. '\x{6E54}\x{6E55}\x{6E56}\x{6E57}\x{6E58}\x{6E59}\x{6E5A}\x{6E5B}\x{6E5C}'
. '\x{6E5D}\x{6E5E}\x{6E5F}\x{6E60}\x{6E61}\x{6E62}\x{6E63}\x{6E64}\x{6E65}'
. '\x{6E66}\x{6E67}\x{6E68}\x{6E69}\x{6E6A}\x{6E6B}\x{6E6D}\x{6E6E}\x{6E6F}'
. '\x{6E70}\x{6E71}\x{6E72}\x{6E73}\x{6E74}\x{6E75}\x{6E77}\x{6E78}\x{6E79}'
. '\x{6E7E}\x{6E7F}\x{6E80}\x{6E81}\x{6E82}\x{6E83}\x{6E84}\x{6E85}\x{6E86}'
. '\x{6E87}\x{6E88}\x{6E89}\x{6E8A}\x{6E8D}\x{6E8E}\x{6E8F}\x{6E90}\x{6E91}'
. '\x{6E92}\x{6E93}\x{6E94}\x{6E96}\x{6E97}\x{6E98}\x{6E99}\x{6E9A}\x{6E9B}'
. '\x{6E9C}\x{6E9D}\x{6E9E}\x{6E9F}\x{6EA0}\x{6EA1}\x{6EA2}\x{6EA3}\x{6EA4}'
. '\x{6EA5}\x{6EA6}\x{6EA7}\x{6EA8}\x{6EA9}\x{6EAA}\x{6EAB}\x{6EAC}\x{6EAD}'
. '\x{6EAE}\x{6EAF}\x{6EB0}\x{6EB1}\x{6EB2}\x{6EB3}\x{6EB4}\x{6EB5}\x{6EB6}'
. '\x{6EB7}\x{6EB8}\x{6EB9}\x{6EBA}\x{6EBB}\x{6EBC}\x{6EBD}\x{6EBE}\x{6EBF}'
. '\x{6EC0}\x{6EC1}\x{6EC2}\x{6EC3}\x{6EC4}\x{6EC5}\x{6EC6}\x{6EC7}\x{6EC8}'
. '\x{6EC9}\x{6ECA}\x{6ECB}\x{6ECC}\x{6ECD}\x{6ECE}\x{6ECF}\x{6ED0}\x{6ED1}'
. '\x{6ED2}\x{6ED3}\x{6ED4}\x{6ED5}\x{6ED6}\x{6ED7}\x{6ED8}\x{6ED9}\x{6EDA}'
. '\x{6EDC}\x{6EDE}\x{6EDF}\x{6EE0}\x{6EE1}\x{6EE2}\x{6EE4}\x{6EE5}\x{6EE6}'
. '\x{6EE7}\x{6EE8}\x{6EE9}\x{6EEA}\x{6EEB}\x{6EEC}\x{6EED}\x{6EEE}\x{6EEF}'
. '\x{6EF0}\x{6EF1}\x{6EF2}\x{6EF3}\x{6EF4}\x{6EF5}\x{6EF6}\x{6EF7}\x{6EF8}'
. '\x{6EF9}\x{6EFA}\x{6EFB}\x{6EFC}\x{6EFD}\x{6EFE}\x{6EFF}\x{6F00}\x{6F01}'
. '\x{6F02}\x{6F03}\x{6F05}\x{6F06}\x{6F07}\x{6F08}\x{6F09}\x{6F0A}\x{6F0C}'
. '\x{6F0D}\x{6F0E}\x{6F0F}\x{6F10}\x{6F11}\x{6F12}\x{6F13}\x{6F14}\x{6F15}'
. '\x{6F16}\x{6F17}\x{6F18}\x{6F19}\x{6F1A}\x{6F1B}\x{6F1C}\x{6F1D}\x{6F1E}'
. '\x{6F1F}\x{6F20}\x{6F21}\x{6F22}\x{6F23}\x{6F24}\x{6F25}\x{6F26}\x{6F27}'
. '\x{6F28}\x{6F29}\x{6F2A}\x{6F2B}\x{6F2C}\x{6F2D}\x{6F2E}\x{6F2F}\x{6F30}'
. '\x{6F31}\x{6F32}\x{6F33}\x{6F34}\x{6F35}\x{6F36}\x{6F37}\x{6F38}\x{6F39}'
. '\x{6F3A}\x{6F3B}\x{6F3C}\x{6F3D}\x{6F3E}\x{6F3F}\x{6F40}\x{6F41}\x{6F43}'
. '\x{6F44}\x{6F45}\x{6F46}\x{6F47}\x{6F49}\x{6F4B}\x{6F4C}\x{6F4D}\x{6F4E}'
. '\x{6F4F}\x{6F50}\x{6F51}\x{6F52}\x{6F53}\x{6F54}\x{6F55}\x{6F56}\x{6F57}'
. '\x{6F58}\x{6F59}\x{6F5A}\x{6F5B}\x{6F5C}\x{6F5D}\x{6F5E}\x{6F5F}\x{6F60}'
. '\x{6F61}\x{6F62}\x{6F63}\x{6F64}\x{6F65}\x{6F66}\x{6F67}\x{6F68}\x{6F69}'
. '\x{6F6A}\x{6F6B}\x{6F6C}\x{6F6D}\x{6F6E}\x{6F6F}\x{6F70}\x{6F71}\x{6F72}'
. '\x{6F73}\x{6F74}\x{6F75}\x{6F76}\x{6F77}\x{6F78}\x{6F7A}\x{6F7B}\x{6F7C}'
. '\x{6F7D}\x{6F7E}\x{6F7F}\x{6F80}\x{6F81}\x{6F82}\x{6F83}\x{6F84}\x{6F85}'
. '\x{6F86}\x{6F87}\x{6F88}\x{6F89}\x{6F8A}\x{6F8B}\x{6F8C}\x{6F8D}\x{6F8E}'
. '\x{6F8F}\x{6F90}\x{6F91}\x{6F92}\x{6F93}\x{6F94}\x{6F95}\x{6F96}\x{6F97}'
. '\x{6F99}\x{6F9B}\x{6F9C}\x{6F9D}\x{6F9E}\x{6FA0}\x{6FA1}\x{6FA2}\x{6FA3}'
. '\x{6FA4}\x{6FA5}\x{6FA6}\x{6FA7}\x{6FA8}\x{6FA9}\x{6FAA}\x{6FAB}\x{6FAC}'
. '\x{6FAD}\x{6FAE}\x{6FAF}\x{6FB0}\x{6FB1}\x{6FB2}\x{6FB3}\x{6FB4}\x{6FB5}'
. '\x{6FB6}\x{6FB8}\x{6FB9}\x{6FBA}\x{6FBB}\x{6FBC}\x{6FBD}\x{6FBE}\x{6FBF}'
. '\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC4}\x{6FC6}\x{6FC7}\x{6FC8}\x{6FC9}'
. '\x{6FCA}\x{6FCB}\x{6FCC}\x{6FCD}\x{6FCE}\x{6FCF}\x{6FD1}\x{6FD2}\x{6FD4}'
. '\x{6FD5}\x{6FD6}\x{6FD7}\x{6FD8}\x{6FD9}\x{6FDA}\x{6FDB}\x{6FDC}\x{6FDD}'
. '\x{6FDE}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE2}\x{6FE3}\x{6FE4}\x{6FE5}\x{6FE6}'
. '\x{6FE7}\x{6FE8}\x{6FE9}\x{6FEA}\x{6FEB}\x{6FEC}\x{6FED}\x{6FEE}\x{6FEF}'
. '\x{6FF0}\x{6FF1}\x{6FF2}\x{6FF3}\x{6FF4}\x{6FF6}\x{6FF7}\x{6FF8}\x{6FF9}'
. '\x{6FFA}\x{6FFB}\x{6FFC}\x{6FFE}\x{6FFF}\x{7000}\x{7001}\x{7002}\x{7003}'
. '\x{7004}\x{7005}\x{7006}\x{7007}\x{7008}\x{7009}\x{700A}\x{700B}\x{700C}'
. '\x{700D}\x{700E}\x{700F}\x{7011}\x{7012}\x{7014}\x{7015}\x{7016}\x{7017}'
. '\x{7018}\x{7019}\x{701A}\x{701B}\x{701C}\x{701D}\x{701F}\x{7020}\x{7021}'
. '\x{7022}\x{7023}\x{7024}\x{7025}\x{7026}\x{7027}\x{7028}\x{7029}\x{702A}'
. '\x{702B}\x{702C}\x{702D}\x{702E}\x{702F}\x{7030}\x{7031}\x{7032}\x{7033}'
. '\x{7034}\x{7035}\x{7036}\x{7037}\x{7038}\x{7039}\x{703A}\x{703B}\x{703C}'
. '\x{703D}\x{703E}\x{703F}\x{7040}\x{7041}\x{7042}\x{7043}\x{7044}\x{7045}'
. '\x{7046}\x{7048}\x{7049}\x{704A}\x{704C}\x{704D}\x{704F}\x{7050}\x{7051}'
. '\x{7052}\x{7053}\x{7054}\x{7055}\x{7056}\x{7057}\x{7058}\x{7059}\x{705A}'
. '\x{705B}\x{705C}\x{705D}\x{705E}\x{705F}\x{7060}\x{7061}\x{7062}\x{7063}'
. '\x{7064}\x{7065}\x{7066}\x{7067}\x{7068}\x{7069}\x{706A}\x{706B}\x{706C}'
. '\x{706D}\x{706E}\x{706F}\x{7070}\x{7071}\x{7074}\x{7075}\x{7076}\x{7077}'
. '\x{7078}\x{7079}\x{707A}\x{707C}\x{707D}\x{707E}\x{707F}\x{7080}\x{7082}'
. '\x{7083}\x{7084}\x{7085}\x{7086}\x{7087}\x{7088}\x{7089}\x{708A}\x{708B}'
. '\x{708C}\x{708E}\x{708F}\x{7090}\x{7091}\x{7092}\x{7093}\x{7094}\x{7095}'
. '\x{7096}\x{7098}\x{7099}\x{709A}\x{709C}\x{709D}\x{709E}\x{709F}\x{70A0}'
. '\x{70A1}\x{70A2}\x{70A3}\x{70A4}\x{70A5}\x{70A6}\x{70A7}\x{70A8}\x{70A9}'
. '\x{70AB}\x{70AC}\x{70AD}\x{70AE}\x{70AF}\x{70B0}\x{70B1}\x{70B3}\x{70B4}'
. '\x{70B5}\x{70B7}\x{70B8}\x{70B9}\x{70BA}\x{70BB}\x{70BC}\x{70BD}\x{70BE}'
. '\x{70BF}\x{70C0}\x{70C1}\x{70C2}\x{70C3}\x{70C4}\x{70C5}\x{70C6}\x{70C7}'
. '\x{70C8}\x{70C9}\x{70CA}\x{70CB}\x{70CC}\x{70CD}\x{70CE}\x{70CF}\x{70D0}'
. '\x{70D1}\x{70D2}\x{70D3}\x{70D4}\x{70D6}\x{70D7}\x{70D8}\x{70D9}\x{70DA}'
. '\x{70DB}\x{70DC}\x{70DD}\x{70DE}\x{70DF}\x{70E0}\x{70E1}\x{70E2}\x{70E3}'
. '\x{70E4}\x{70E5}\x{70E6}\x{70E7}\x{70E8}\x{70E9}\x{70EA}\x{70EB}\x{70EC}'
. '\x{70ED}\x{70EE}\x{70EF}\x{70F0}\x{70F1}\x{70F2}\x{70F3}\x{70F4}\x{70F5}'
. '\x{70F6}\x{70F7}\x{70F8}\x{70F9}\x{70FA}\x{70FB}\x{70FC}\x{70FD}\x{70FF}'
. '\x{7100}\x{7101}\x{7102}\x{7103}\x{7104}\x{7105}\x{7106}\x{7107}\x{7109}'
. '\x{710A}\x{710B}\x{710C}\x{710D}\x{710E}\x{710F}\x{7110}\x{7111}\x{7112}'
. '\x{7113}\x{7115}\x{7116}\x{7117}\x{7118}\x{7119}\x{711A}\x{711B}\x{711C}'
. '\x{711D}\x{711E}\x{711F}\x{7120}\x{7121}\x{7122}\x{7123}\x{7125}\x{7126}'
. '\x{7127}\x{7128}\x{7129}\x{712A}\x{712B}\x{712C}\x{712D}\x{712E}\x{712F}'
. '\x{7130}\x{7131}\x{7132}\x{7135}\x{7136}\x{7137}\x{7138}\x{7139}\x{713A}'
. '\x{713B}\x{713D}\x{713E}\x{713F}\x{7140}\x{7141}\x{7142}\x{7143}\x{7144}'
. '\x{7145}\x{7146}\x{7147}\x{7148}\x{7149}\x{714A}\x{714B}\x{714C}\x{714D}'
. '\x{714E}\x{714F}\x{7150}\x{7151}\x{7152}\x{7153}\x{7154}\x{7156}\x{7158}'
. '\x{7159}\x{715A}\x{715B}\x{715C}\x{715D}\x{715E}\x{715F}\x{7160}\x{7161}'
. '\x{7162}\x{7163}\x{7164}\x{7165}\x{7166}\x{7167}\x{7168}\x{7169}\x{716A}'
. '\x{716C}\x{716E}\x{716F}\x{7170}\x{7171}\x{7172}\x{7173}\x{7174}\x{7175}'
. '\x{7176}\x{7177}\x{7178}\x{7179}\x{717A}\x{717B}\x{717C}\x{717D}\x{717E}'
. '\x{717F}\x{7180}\x{7181}\x{7182}\x{7183}\x{7184}\x{7185}\x{7186}\x{7187}'
. '\x{7188}\x{7189}\x{718A}\x{718B}\x{718C}\x{718E}\x{718F}\x{7190}\x{7191}'
. '\x{7192}\x{7193}\x{7194}\x{7195}\x{7197}\x{7198}\x{7199}\x{719A}\x{719B}'
. '\x{719C}\x{719D}\x{719E}\x{719F}\x{71A0}\x{71A1}\x{71A2}\x{71A3}\x{71A4}'
. '\x{71A5}\x{71A7}\x{71A8}\x{71A9}\x{71AA}\x{71AC}\x{71AD}\x{71AE}\x{71AF}'
. '\x{71B0}\x{71B1}\x{71B2}\x{71B3}\x{71B4}\x{71B5}\x{71B7}\x{71B8}\x{71B9}'
. '\x{71BA}\x{71BB}\x{71BC}\x{71BD}\x{71BE}\x{71BF}\x{71C0}\x{71C1}\x{71C2}'
. '\x{71C3}\x{71C4}\x{71C5}\x{71C6}\x{71C7}\x{71C8}\x{71C9}\x{71CA}\x{71CB}'
. '\x{71CD}\x{71CE}\x{71CF}\x{71D0}\x{71D1}\x{71D2}\x{71D4}\x{71D5}\x{71D6}'
. '\x{71D7}\x{71D8}\x{71D9}\x{71DA}\x{71DB}\x{71DC}\x{71DD}\x{71DE}\x{71DF}'
. '\x{71E0}\x{71E1}\x{71E2}\x{71E3}\x{71E4}\x{71E5}\x{71E6}\x{71E7}\x{71E8}'
. '\x{71E9}\x{71EA}\x{71EB}\x{71EC}\x{71ED}\x{71EE}\x{71EF}\x{71F0}\x{71F1}'
. '\x{71F2}\x{71F4}\x{71F5}\x{71F6}\x{71F7}\x{71F8}\x{71F9}\x{71FB}\x{71FC}'
. '\x{71FD}\x{71FE}\x{71FF}\x{7201}\x{7202}\x{7203}\x{7204}\x{7205}\x{7206}'
. '\x{7207}\x{7208}\x{7209}\x{720A}\x{720C}\x{720D}\x{720E}\x{720F}\x{7210}'
. '\x{7212}\x{7213}\x{7214}\x{7216}\x{7218}\x{7219}\x{721A}\x{721B}\x{721C}'
. '\x{721D}\x{721E}\x{721F}\x{7221}\x{7222}\x{7223}\x{7226}\x{7227}\x{7228}'
. '\x{7229}\x{722A}\x{722B}\x{722C}\x{722D}\x{722E}\x{7230}\x{7231}\x{7232}'
. '\x{7233}\x{7235}\x{7236}\x{7237}\x{7238}\x{7239}\x{723A}\x{723B}\x{723C}'
. '\x{723D}\x{723E}\x{723F}\x{7240}\x{7241}\x{7242}\x{7243}\x{7244}\x{7246}'
. '\x{7247}\x{7248}\x{7249}\x{724A}\x{724B}\x{724C}\x{724D}\x{724F}\x{7251}'
. '\x{7252}\x{7253}\x{7254}\x{7256}\x{7257}\x{7258}\x{7259}\x{725A}\x{725B}'
. '\x{725C}\x{725D}\x{725E}\x{725F}\x{7260}\x{7261}\x{7262}\x{7263}\x{7264}'
. '\x{7265}\x{7266}\x{7267}\x{7268}\x{7269}\x{726A}\x{726B}\x{726C}\x{726D}'
. '\x{726E}\x{726F}\x{7270}\x{7271}\x{7272}\x{7273}\x{7274}\x{7275}\x{7276}'
. '\x{7277}\x{7278}\x{7279}\x{727A}\x{727B}\x{727C}\x{727D}\x{727E}\x{727F}'
. '\x{7280}\x{7281}\x{7282}\x{7283}\x{7284}\x{7285}\x{7286}\x{7287}\x{7288}'
. '\x{7289}\x{728A}\x{728B}\x{728C}\x{728D}\x{728E}\x{728F}\x{7290}\x{7291}'
. '\x{7292}\x{7293}\x{7294}\x{7295}\x{7296}\x{7297}\x{7298}\x{7299}\x{729A}'
. '\x{729B}\x{729C}\x{729D}\x{729E}\x{729F}\x{72A1}\x{72A2}\x{72A3}\x{72A4}'
. '\x{72A5}\x{72A6}\x{72A7}\x{72A8}\x{72A9}\x{72AA}\x{72AC}\x{72AD}\x{72AE}'
. '\x{72AF}\x{72B0}\x{72B1}\x{72B2}\x{72B3}\x{72B4}\x{72B5}\x{72B6}\x{72B7}'
. '\x{72B8}\x{72B9}\x{72BA}\x{72BB}\x{72BC}\x{72BD}\x{72BF}\x{72C0}\x{72C1}'
. '\x{72C2}\x{72C3}\x{72C4}\x{72C5}\x{72C6}\x{72C7}\x{72C8}\x{72C9}\x{72CA}'
. '\x{72CB}\x{72CC}\x{72CD}\x{72CE}\x{72CF}\x{72D0}\x{72D1}\x{72D2}\x{72D3}'
. '\x{72D4}\x{72D5}\x{72D6}\x{72D7}\x{72D8}\x{72D9}\x{72DA}\x{72DB}\x{72DC}'
. '\x{72DD}\x{72DE}\x{72DF}\x{72E0}\x{72E1}\x{72E2}\x{72E3}\x{72E4}\x{72E5}'
. '\x{72E6}\x{72E7}\x{72E8}\x{72E9}\x{72EA}\x{72EB}\x{72EC}\x{72ED}\x{72EE}'
. '\x{72EF}\x{72F0}\x{72F1}\x{72F2}\x{72F3}\x{72F4}\x{72F5}\x{72F6}\x{72F7}'
. '\x{72F8}\x{72F9}\x{72FA}\x{72FB}\x{72FC}\x{72FD}\x{72FE}\x{72FF}\x{7300}'
. '\x{7301}\x{7303}\x{7304}\x{7305}\x{7306}\x{7307}\x{7308}\x{7309}\x{730A}'
. '\x{730B}\x{730C}\x{730D}\x{730E}\x{730F}\x{7311}\x{7312}\x{7313}\x{7314}'
. '\x{7315}\x{7316}\x{7317}\x{7318}\x{7319}\x{731A}\x{731B}\x{731C}\x{731D}'
. '\x{731E}\x{7320}\x{7321}\x{7322}\x{7323}\x{7324}\x{7325}\x{7326}\x{7327}'
. '\x{7329}\x{732A}\x{732B}\x{732C}\x{732D}\x{732E}\x{7330}\x{7331}\x{7332}'
. '\x{7333}\x{7334}\x{7335}\x{7336}\x{7337}\x{7338}\x{7339}\x{733A}\x{733B}'
. '\x{733C}\x{733D}\x{733E}\x{733F}\x{7340}\x{7341}\x{7342}\x{7343}\x{7344}'
. '\x{7345}\x{7346}\x{7347}\x{7348}\x{7349}\x{734A}\x{734B}\x{734C}\x{734D}'
. '\x{734E}\x{7350}\x{7351}\x{7352}\x{7354}\x{7355}\x{7356}\x{7357}\x{7358}'
. '\x{7359}\x{735A}\x{735B}\x{735C}\x{735D}\x{735E}\x{735F}\x{7360}\x{7361}'
. '\x{7362}\x{7364}\x{7365}\x{7366}\x{7367}\x{7368}\x{7369}\x{736A}\x{736B}'
. '\x{736C}\x{736D}\x{736E}\x{736F}\x{7370}\x{7371}\x{7372}\x{7373}\x{7374}'
. '\x{7375}\x{7376}\x{7377}\x{7378}\x{7379}\x{737A}\x{737B}\x{737C}\x{737D}'
. '\x{737E}\x{737F}\x{7380}\x{7381}\x{7382}\x{7383}\x{7384}\x{7385}\x{7386}'
. '\x{7387}\x{7388}\x{7389}\x{738A}\x{738B}\x{738C}\x{738D}\x{738E}\x{738F}'
. '\x{7390}\x{7391}\x{7392}\x{7393}\x{7394}\x{7395}\x{7396}\x{7397}\x{7398}'
. '\x{7399}\x{739A}\x{739B}\x{739D}\x{739E}\x{739F}\x{73A0}\x{73A1}\x{73A2}'
. '\x{73A3}\x{73A4}\x{73A5}\x{73A6}\x{73A7}\x{73A8}\x{73A9}\x{73AA}\x{73AB}'
. '\x{73AC}\x{73AD}\x{73AE}\x{73AF}\x{73B0}\x{73B1}\x{73B2}\x{73B3}\x{73B4}'
. '\x{73B5}\x{73B6}\x{73B7}\x{73B8}\x{73B9}\x{73BA}\x{73BB}\x{73BC}\x{73BD}'
. '\x{73BE}\x{73BF}\x{73C0}\x{73C2}\x{73C3}\x{73C4}\x{73C5}\x{73C6}\x{73C7}'
. '\x{73C8}\x{73C9}\x{73CA}\x{73CB}\x{73CC}\x{73CD}\x{73CE}\x{73CF}\x{73D0}'
. '\x{73D1}\x{73D2}\x{73D3}\x{73D4}\x{73D5}\x{73D6}\x{73D7}\x{73D8}\x{73D9}'
. '\x{73DA}\x{73DB}\x{73DC}\x{73DD}\x{73DE}\x{73DF}\x{73E0}\x{73E2}\x{73E3}'
. '\x{73E5}\x{73E6}\x{73E7}\x{73E8}\x{73E9}\x{73EA}\x{73EB}\x{73EC}\x{73ED}'
. '\x{73EE}\x{73EF}\x{73F0}\x{73F1}\x{73F2}\x{73F4}\x{73F5}\x{73F6}\x{73F7}'
. '\x{73F8}\x{73F9}\x{73FA}\x{73FC}\x{73FD}\x{73FE}\x{73FF}\x{7400}\x{7401}'
. '\x{7402}\x{7403}\x{7404}\x{7405}\x{7406}\x{7407}\x{7408}\x{7409}\x{740A}'
. '\x{740B}\x{740C}\x{740D}\x{740E}\x{740F}\x{7410}\x{7411}\x{7412}\x{7413}'
. '\x{7414}\x{7415}\x{7416}\x{7417}\x{7419}\x{741A}\x{741B}\x{741C}\x{741D}'
. '\x{741E}\x{741F}\x{7420}\x{7421}\x{7422}\x{7423}\x{7424}\x{7425}\x{7426}'
. '\x{7427}\x{7428}\x{7429}\x{742A}\x{742B}\x{742C}\x{742D}\x{742E}\x{742F}'
. '\x{7430}\x{7431}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{7437}\x{7438}'
. '\x{743A}\x{743B}\x{743C}\x{743D}\x{743F}\x{7440}\x{7441}\x{7442}\x{7443}'
. '\x{7444}\x{7445}\x{7446}\x{7448}\x{744A}\x{744B}\x{744C}\x{744D}\x{744E}'
. '\x{744F}\x{7450}\x{7451}\x{7452}\x{7453}\x{7454}\x{7455}\x{7456}\x{7457}'
. '\x{7459}\x{745A}\x{745B}\x{745C}\x{745D}\x{745E}\x{745F}\x{7461}\x{7462}'
. '\x{7463}\x{7464}\x{7465}\x{7466}\x{7467}\x{7468}\x{7469}\x{746A}\x{746B}'
. '\x{746C}\x{746D}\x{746E}\x{746F}\x{7470}\x{7471}\x{7472}\x{7473}\x{7474}'
. '\x{7475}\x{7476}\x{7477}\x{7478}\x{7479}\x{747A}\x{747C}\x{747D}\x{747E}'
. '\x{747F}\x{7480}\x{7481}\x{7482}\x{7483}\x{7485}\x{7486}\x{7487}\x{7488}'
. '\x{7489}\x{748A}\x{748B}\x{748C}\x{748D}\x{748E}\x{748F}\x{7490}\x{7491}'
. '\x{7492}\x{7493}\x{7494}\x{7495}\x{7497}\x{7498}\x{7499}\x{749A}\x{749B}'
. '\x{749C}\x{749E}\x{749F}\x{74A0}\x{74A1}\x{74A3}\x{74A4}\x{74A5}\x{74A6}'
. '\x{74A7}\x{74A8}\x{74A9}\x{74AA}\x{74AB}\x{74AC}\x{74AD}\x{74AE}\x{74AF}'
. '\x{74B0}\x{74B1}\x{74B2}\x{74B3}\x{74B4}\x{74B5}\x{74B6}\x{74B7}\x{74B8}'
. '\x{74B9}\x{74BA}\x{74BB}\x{74BC}\x{74BD}\x{74BE}\x{74BF}\x{74C0}\x{74C1}'
. '\x{74C2}\x{74C3}\x{74C4}\x{74C5}\x{74C6}\x{74CA}\x{74CB}\x{74CD}\x{74CE}'
. '\x{74CF}\x{74D0}\x{74D1}\x{74D2}\x{74D3}\x{74D4}\x{74D5}\x{74D6}\x{74D7}'
. '\x{74D8}\x{74D9}\x{74DA}\x{74DB}\x{74DC}\x{74DD}\x{74DE}\x{74DF}\x{74E0}'
. '\x{74E1}\x{74E2}\x{74E3}\x{74E4}\x{74E5}\x{74E6}\x{74E7}\x{74E8}\x{74E9}'
. '\x{74EA}\x{74EC}\x{74ED}\x{74EE}\x{74EF}\x{74F0}\x{74F1}\x{74F2}\x{74F3}'
. '\x{74F4}\x{74F5}\x{74F6}\x{74F7}\x{74F8}\x{74F9}\x{74FA}\x{74FB}\x{74FC}'
. '\x{74FD}\x{74FE}\x{74FF}\x{7500}\x{7501}\x{7502}\x{7503}\x{7504}\x{7505}'
. '\x{7506}\x{7507}\x{7508}\x{7509}\x{750A}\x{750B}\x{750C}\x{750D}\x{750F}'
. '\x{7510}\x{7511}\x{7512}\x{7513}\x{7514}\x{7515}\x{7516}\x{7517}\x{7518}'
. '\x{7519}\x{751A}\x{751B}\x{751C}\x{751D}\x{751E}\x{751F}\x{7521}\x{7522}'
. '\x{7523}\x{7524}\x{7525}\x{7526}\x{7527}\x{7528}\x{7529}\x{752A}\x{752B}'
. '\x{752C}\x{752D}\x{752E}\x{752F}\x{7530}\x{7531}\x{7532}\x{7533}\x{7535}'
. '\x{7536}\x{7537}\x{7538}\x{7539}\x{753A}\x{753B}\x{753C}\x{753D}\x{753E}'
. '\x{753F}\x{7540}\x{7542}\x{7543}\x{7544}\x{7545}\x{7546}\x{7547}\x{7548}'
. '\x{7549}\x{754B}\x{754C}\x{754D}\x{754E}\x{754F}\x{7550}\x{7551}\x{7553}'
. '\x{7554}\x{7556}\x{7557}\x{7558}\x{7559}\x{755A}\x{755B}\x{755C}\x{755D}'
. '\x{755F}\x{7560}\x{7562}\x{7563}\x{7564}\x{7565}\x{7566}\x{7567}\x{7568}'
. '\x{7569}\x{756A}\x{756B}\x{756C}\x{756D}\x{756E}\x{756F}\x{7570}\x{7572}'
. '\x{7574}\x{7575}\x{7576}\x{7577}\x{7578}\x{7579}\x{757C}\x{757D}\x{757E}'
. '\x{757F}\x{7580}\x{7581}\x{7582}\x{7583}\x{7584}\x{7586}\x{7587}\x{7588}'
. '\x{7589}\x{758A}\x{758B}\x{758C}\x{758D}\x{758F}\x{7590}\x{7591}\x{7592}'
. '\x{7593}\x{7594}\x{7595}\x{7596}\x{7597}\x{7598}\x{7599}\x{759A}\x{759B}'
. '\x{759C}\x{759D}\x{759E}\x{759F}\x{75A0}\x{75A1}\x{75A2}\x{75A3}\x{75A4}'
. '\x{75A5}\x{75A6}\x{75A7}\x{75A8}\x{75AA}\x{75AB}\x{75AC}\x{75AD}\x{75AE}'
. '\x{75AF}\x{75B0}\x{75B1}\x{75B2}\x{75B3}\x{75B4}\x{75B5}\x{75B6}\x{75B8}'
. '\x{75B9}\x{75BA}\x{75BB}\x{75BC}\x{75BD}\x{75BE}\x{75BF}\x{75C0}\x{75C1}'
. '\x{75C2}\x{75C3}\x{75C4}\x{75C5}\x{75C6}\x{75C7}\x{75C8}\x{75C9}\x{75CA}'
. '\x{75CB}\x{75CC}\x{75CD}\x{75CE}\x{75CF}\x{75D0}\x{75D1}\x{75D2}\x{75D3}'
. '\x{75D4}\x{75D5}\x{75D6}\x{75D7}\x{75D8}\x{75D9}\x{75DA}\x{75DB}\x{75DD}'
. '\x{75DE}\x{75DF}\x{75E0}\x{75E1}\x{75E2}\x{75E3}\x{75E4}\x{75E5}\x{75E6}'
. '\x{75E7}\x{75E8}\x{75EA}\x{75EB}\x{75EC}\x{75ED}\x{75EF}\x{75F0}\x{75F1}'
. '\x{75F2}\x{75F3}\x{75F4}\x{75F5}\x{75F6}\x{75F7}\x{75F8}\x{75F9}\x{75FA}'
. '\x{75FB}\x{75FC}\x{75FD}\x{75FE}\x{75FF}\x{7600}\x{7601}\x{7602}\x{7603}'
. '\x{7604}\x{7605}\x{7606}\x{7607}\x{7608}\x{7609}\x{760A}\x{760B}\x{760C}'
. '\x{760D}\x{760E}\x{760F}\x{7610}\x{7611}\x{7612}\x{7613}\x{7614}\x{7615}'
. '\x{7616}\x{7617}\x{7618}\x{7619}\x{761A}\x{761B}\x{761C}\x{761D}\x{761E}'
. '\x{761F}\x{7620}\x{7621}\x{7622}\x{7623}\x{7624}\x{7625}\x{7626}\x{7627}'
. '\x{7628}\x{7629}\x{762A}\x{762B}\x{762D}\x{762E}\x{762F}\x{7630}\x{7631}'
. '\x{7632}\x{7633}\x{7634}\x{7635}\x{7636}\x{7637}\x{7638}\x{7639}\x{763A}'
. '\x{763B}\x{763C}\x{763D}\x{763E}\x{763F}\x{7640}\x{7641}\x{7642}\x{7643}'
. '\x{7646}\x{7647}\x{7648}\x{7649}\x{764A}\x{764B}\x{764C}\x{764D}\x{764F}'
. '\x{7650}\x{7652}\x{7653}\x{7654}\x{7656}\x{7657}\x{7658}\x{7659}\x{765A}'
. '\x{765B}\x{765C}\x{765D}\x{765E}\x{765F}\x{7660}\x{7661}\x{7662}\x{7663}'
. '\x{7664}\x{7665}\x{7666}\x{7667}\x{7668}\x{7669}\x{766A}\x{766B}\x{766C}'
. '\x{766D}\x{766E}\x{766F}\x{7670}\x{7671}\x{7672}\x{7674}\x{7675}\x{7676}'
. '\x{7677}\x{7678}\x{7679}\x{767B}\x{767C}\x{767D}\x{767E}\x{767F}\x{7680}'
. '\x{7681}\x{7682}\x{7683}\x{7684}\x{7685}\x{7686}\x{7687}\x{7688}\x{7689}'
. '\x{768A}\x{768B}\x{768C}\x{768E}\x{768F}\x{7690}\x{7691}\x{7692}\x{7693}'
. '\x{7694}\x{7695}\x{7696}\x{7697}\x{7698}\x{7699}\x{769A}\x{769B}\x{769C}'
. '\x{769D}\x{769E}\x{769F}\x{76A0}\x{76A3}\x{76A4}\x{76A6}\x{76A7}\x{76A9}'
. '\x{76AA}\x{76AB}\x{76AC}\x{76AD}\x{76AE}\x{76AF}\x{76B0}\x{76B1}\x{76B2}'
. '\x{76B4}\x{76B5}\x{76B7}\x{76B8}\x{76BA}\x{76BB}\x{76BC}\x{76BD}\x{76BE}'
. '\x{76BF}\x{76C0}\x{76C2}\x{76C3}\x{76C4}\x{76C5}\x{76C6}\x{76C7}\x{76C8}'
. '\x{76C9}\x{76CA}\x{76CD}\x{76CE}\x{76CF}\x{76D0}\x{76D1}\x{76D2}\x{76D3}'
. '\x{76D4}\x{76D5}\x{76D6}\x{76D7}\x{76D8}\x{76DA}\x{76DB}\x{76DC}\x{76DD}'
. '\x{76DE}\x{76DF}\x{76E0}\x{76E1}\x{76E2}\x{76E3}\x{76E4}\x{76E5}\x{76E6}'
. '\x{76E7}\x{76E8}\x{76E9}\x{76EA}\x{76EC}\x{76ED}\x{76EE}\x{76EF}\x{76F0}'
. '\x{76F1}\x{76F2}\x{76F3}\x{76F4}\x{76F5}\x{76F6}\x{76F7}\x{76F8}\x{76F9}'
. '\x{76FA}\x{76FB}\x{76FC}\x{76FD}\x{76FE}\x{76FF}\x{7701}\x{7703}\x{7704}'
. '\x{7705}\x{7706}\x{7707}\x{7708}\x{7709}\x{770A}\x{770B}\x{770C}\x{770D}'
. '\x{770F}\x{7710}\x{7711}\x{7712}\x{7713}\x{7714}\x{7715}\x{7716}\x{7717}'
. '\x{7718}\x{7719}\x{771A}\x{771B}\x{771C}\x{771D}\x{771E}\x{771F}\x{7720}'
. '\x{7722}\x{7723}\x{7725}\x{7726}\x{7727}\x{7728}\x{7729}\x{772A}\x{772C}'
. '\x{772D}\x{772E}\x{772F}\x{7730}\x{7731}\x{7732}\x{7733}\x{7734}\x{7735}'
. '\x{7736}\x{7737}\x{7738}\x{7739}\x{773A}\x{773B}\x{773C}\x{773D}\x{773E}'
. '\x{7740}\x{7741}\x{7743}\x{7744}\x{7745}\x{7746}\x{7747}\x{7748}\x{7749}'
. '\x{774A}\x{774B}\x{774C}\x{774D}\x{774E}\x{774F}\x{7750}\x{7751}\x{7752}'
. '\x{7753}\x{7754}\x{7755}\x{7756}\x{7757}\x{7758}\x{7759}\x{775A}\x{775B}'
. '\x{775C}\x{775D}\x{775E}\x{775F}\x{7760}\x{7761}\x{7762}\x{7763}\x{7765}'
. '\x{7766}\x{7767}\x{7768}\x{7769}\x{776A}\x{776B}\x{776C}\x{776D}\x{776E}'
. '\x{776F}\x{7770}\x{7771}\x{7772}\x{7773}\x{7774}\x{7775}\x{7776}\x{7777}'
. '\x{7778}\x{7779}\x{777A}\x{777B}\x{777C}\x{777D}\x{777E}\x{777F}\x{7780}'
. '\x{7781}\x{7782}\x{7783}\x{7784}\x{7785}\x{7786}\x{7787}\x{7788}\x{7789}'
. '\x{778A}\x{778B}\x{778C}\x{778D}\x{778E}\x{778F}\x{7790}\x{7791}\x{7792}'
. '\x{7793}\x{7794}\x{7795}\x{7797}\x{7798}\x{7799}\x{779A}\x{779B}\x{779C}'
. '\x{779D}\x{779E}\x{779F}\x{77A0}\x{77A1}\x{77A2}\x{77A3}\x{77A5}\x{77A6}'
. '\x{77A7}\x{77A8}\x{77A9}\x{77AA}\x{77AB}\x{77AC}\x{77AD}\x{77AE}\x{77AF}'
. '\x{77B0}\x{77B1}\x{77B2}\x{77B3}\x{77B4}\x{77B5}\x{77B6}\x{77B7}\x{77B8}'
. '\x{77B9}\x{77BA}\x{77BB}\x{77BC}\x{77BD}\x{77BF}\x{77C0}\x{77C2}\x{77C3}'
. '\x{77C4}\x{77C5}\x{77C6}\x{77C7}\x{77C8}\x{77C9}\x{77CA}\x{77CB}\x{77CC}'
. '\x{77CD}\x{77CE}\x{77CF}\x{77D0}\x{77D1}\x{77D3}\x{77D4}\x{77D5}\x{77D6}'
. '\x{77D7}\x{77D8}\x{77D9}\x{77DA}\x{77DB}\x{77DC}\x{77DE}\x{77DF}\x{77E0}'
. '\x{77E1}\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E8}\x{77E9}\x{77EA}\x{77EB}'
. '\x{77EC}\x{77ED}\x{77EE}\x{77EF}\x{77F0}\x{77F1}\x{77F2}\x{77F3}\x{77F6}'
. '\x{77F7}\x{77F8}\x{77F9}\x{77FA}\x{77FB}\x{77FC}\x{77FD}\x{77FE}\x{77FF}'
. '\x{7800}\x{7801}\x{7802}\x{7803}\x{7804}\x{7805}\x{7806}\x{7808}\x{7809}'
. '\x{780A}\x{780B}\x{780C}\x{780D}\x{780E}\x{780F}\x{7810}\x{7811}\x{7812}'
. '\x{7813}\x{7814}\x{7815}\x{7816}\x{7817}\x{7818}\x{7819}\x{781A}\x{781B}'
. '\x{781C}\x{781D}\x{781E}\x{781F}\x{7820}\x{7821}\x{7822}\x{7823}\x{7825}'
. '\x{7826}\x{7827}\x{7828}\x{7829}\x{782A}\x{782B}\x{782C}\x{782D}\x{782E}'
. '\x{782F}\x{7830}\x{7831}\x{7832}\x{7833}\x{7834}\x{7835}\x{7837}\x{7838}'
. '\x{7839}\x{783A}\x{783B}\x{783C}\x{783D}\x{783E}\x{7840}\x{7841}\x{7843}'
. '\x{7844}\x{7845}\x{7847}\x{7848}\x{7849}\x{784A}\x{784C}\x{784D}\x{784E}'
. '\x{7850}\x{7851}\x{7852}\x{7853}\x{7854}\x{7855}\x{7856}\x{7857}\x{7858}'
. '\x{7859}\x{785A}\x{785B}\x{785C}\x{785D}\x{785E}\x{785F}\x{7860}\x{7861}'
. '\x{7862}\x{7863}\x{7864}\x{7865}\x{7866}\x{7867}\x{7868}\x{7869}\x{786A}'
. '\x{786B}\x{786C}\x{786D}\x{786E}\x{786F}\x{7870}\x{7871}\x{7872}\x{7873}'
. '\x{7874}\x{7875}\x{7877}\x{7878}\x{7879}\x{787A}\x{787B}\x{787C}\x{787D}'
. '\x{787E}\x{787F}\x{7880}\x{7881}\x{7882}\x{7883}\x{7884}\x{7885}\x{7886}'
. '\x{7887}\x{7889}\x{788A}\x{788B}\x{788C}\x{788D}\x{788E}\x{788F}\x{7890}'
. '\x{7891}\x{7892}\x{7893}\x{7894}\x{7895}\x{7896}\x{7897}\x{7898}\x{7899}'
. '\x{789A}\x{789B}\x{789C}\x{789D}\x{789E}\x{789F}\x{78A0}\x{78A1}\x{78A2}'
. '\x{78A3}\x{78A4}\x{78A5}\x{78A6}\x{78A7}\x{78A8}\x{78A9}\x{78AA}\x{78AB}'
. '\x{78AC}\x{78AD}\x{78AE}\x{78AF}\x{78B0}\x{78B1}\x{78B2}\x{78B3}\x{78B4}'
. '\x{78B5}\x{78B6}\x{78B7}\x{78B8}\x{78B9}\x{78BA}\x{78BB}\x{78BC}\x{78BD}'
. '\x{78BE}\x{78BF}\x{78C0}\x{78C1}\x{78C3}\x{78C4}\x{78C5}\x{78C6}\x{78C8}'
. '\x{78C9}\x{78CA}\x{78CB}\x{78CC}\x{78CD}\x{78CE}\x{78CF}\x{78D0}\x{78D1}'
. '\x{78D3}\x{78D4}\x{78D5}\x{78D6}\x{78D7}\x{78D8}\x{78D9}\x{78DA}\x{78DB}'
. '\x{78DC}\x{78DD}\x{78DE}\x{78DF}\x{78E0}\x{78E1}\x{78E2}\x{78E3}\x{78E4}'
. '\x{78E5}\x{78E6}\x{78E7}\x{78E8}\x{78E9}\x{78EA}\x{78EB}\x{78EC}\x{78ED}'
. '\x{78EE}\x{78EF}\x{78F1}\x{78F2}\x{78F3}\x{78F4}\x{78F5}\x{78F6}\x{78F7}'
. '\x{78F9}\x{78FA}\x{78FB}\x{78FC}\x{78FD}\x{78FE}\x{78FF}\x{7901}\x{7902}'
. '\x{7903}\x{7904}\x{7905}\x{7906}\x{7907}\x{7909}\x{790A}\x{790B}\x{790C}'
. '\x{790E}\x{790F}\x{7910}\x{7911}\x{7912}\x{7913}\x{7914}\x{7916}\x{7917}'
. '\x{7918}\x{7919}\x{791A}\x{791B}\x{791C}\x{791D}\x{791E}\x{7921}\x{7922}'
. '\x{7923}\x{7924}\x{7925}\x{7926}\x{7927}\x{7928}\x{7929}\x{792A}\x{792B}'
. '\x{792C}\x{792D}\x{792E}\x{792F}\x{7930}\x{7931}\x{7933}\x{7934}\x{7935}'
. '\x{7937}\x{7938}\x{7939}\x{793A}\x{793B}\x{793C}\x{793D}\x{793E}\x{793F}'
. '\x{7940}\x{7941}\x{7942}\x{7943}\x{7944}\x{7945}\x{7946}\x{7947}\x{7948}'
. '\x{7949}\x{794A}\x{794B}\x{794C}\x{794D}\x{794E}\x{794F}\x{7950}\x{7951}'
. '\x{7952}\x{7953}\x{7954}\x{7955}\x{7956}\x{7957}\x{7958}\x{795A}\x{795B}'
. '\x{795C}\x{795D}\x{795E}\x{795F}\x{7960}\x{7961}\x{7962}\x{7963}\x{7964}'
. '\x{7965}\x{7966}\x{7967}\x{7968}\x{7969}\x{796A}\x{796B}\x{796D}\x{796F}'
. '\x{7970}\x{7971}\x{7972}\x{7973}\x{7974}\x{7977}\x{7978}\x{7979}\x{797A}'
. '\x{797B}\x{797C}\x{797D}\x{797E}\x{797F}\x{7980}\x{7981}\x{7982}\x{7983}'
. '\x{7984}\x{7985}\x{7988}\x{7989}\x{798A}\x{798B}\x{798C}\x{798D}\x{798E}'
. '\x{798F}\x{7990}\x{7991}\x{7992}\x{7993}\x{7994}\x{7995}\x{7996}\x{7997}'
. '\x{7998}\x{7999}\x{799A}\x{799B}\x{799C}\x{799F}\x{79A0}\x{79A1}\x{79A2}'
. '\x{79A3}\x{79A4}\x{79A5}\x{79A6}\x{79A7}\x{79A8}\x{79AA}\x{79AB}\x{79AC}'
. '\x{79AD}\x{79AE}\x{79AF}\x{79B0}\x{79B1}\x{79B2}\x{79B3}\x{79B4}\x{79B5}'
. '\x{79B6}\x{79B7}\x{79B8}\x{79B9}\x{79BA}\x{79BB}\x{79BD}\x{79BE}\x{79BF}'
. '\x{79C0}\x{79C1}\x{79C2}\x{79C3}\x{79C5}\x{79C6}\x{79C8}\x{79C9}\x{79CA}'
. '\x{79CB}\x{79CD}\x{79CE}\x{79CF}\x{79D0}\x{79D1}\x{79D2}\x{79D3}\x{79D5}'
. '\x{79D6}\x{79D8}\x{79D9}\x{79DA}\x{79DB}\x{79DC}\x{79DD}\x{79DE}\x{79DF}'
. '\x{79E0}\x{79E1}\x{79E2}\x{79E3}\x{79E4}\x{79E5}\x{79E6}\x{79E7}\x{79E8}'
. '\x{79E9}\x{79EA}\x{79EB}\x{79EC}\x{79ED}\x{79EE}\x{79EF}\x{79F0}\x{79F1}'
. '\x{79F2}\x{79F3}\x{79F4}\x{79F5}\x{79F6}\x{79F7}\x{79F8}\x{79F9}\x{79FA}'
. '\x{79FB}\x{79FC}\x{79FD}\x{79FE}\x{79FF}\x{7A00}\x{7A02}\x{7A03}\x{7A04}'
. '\x{7A05}\x{7A06}\x{7A08}\x{7A0A}\x{7A0B}\x{7A0C}\x{7A0D}\x{7A0E}\x{7A0F}'
. '\x{7A10}\x{7A11}\x{7A12}\x{7A13}\x{7A14}\x{7A15}\x{7A16}\x{7A17}\x{7A18}'
. '\x{7A19}\x{7A1A}\x{7A1B}\x{7A1C}\x{7A1D}\x{7A1E}\x{7A1F}\x{7A20}\x{7A21}'
. '\x{7A22}\x{7A23}\x{7A24}\x{7A25}\x{7A26}\x{7A27}\x{7A28}\x{7A29}\x{7A2A}'
. '\x{7A2B}\x{7A2D}\x{7A2E}\x{7A2F}\x{7A30}\x{7A31}\x{7A32}\x{7A33}\x{7A34}'
. '\x{7A35}\x{7A37}\x{7A39}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}'
. '\x{7A41}\x{7A42}\x{7A43}\x{7A44}\x{7A45}\x{7A46}\x{7A47}\x{7A48}\x{7A49}'
. '\x{7A4A}\x{7A4B}\x{7A4C}\x{7A4D}\x{7A4E}\x{7A50}\x{7A51}\x{7A52}\x{7A53}'
. '\x{7A54}\x{7A55}\x{7A56}\x{7A57}\x{7A58}\x{7A59}\x{7A5A}\x{7A5B}\x{7A5C}'
. '\x{7A5D}\x{7A5E}\x{7A5F}\x{7A60}\x{7A61}\x{7A62}\x{7A65}\x{7A66}\x{7A67}'
. '\x{7A68}\x{7A69}\x{7A6B}\x{7A6C}\x{7A6D}\x{7A6E}\x{7A70}\x{7A71}\x{7A72}'
. '\x{7A73}\x{7A74}\x{7A75}\x{7A76}\x{7A77}\x{7A78}\x{7A79}\x{7A7A}\x{7A7B}'
. '\x{7A7C}\x{7A7D}\x{7A7E}\x{7A7F}\x{7A80}\x{7A81}\x{7A83}\x{7A84}\x{7A85}'
. '\x{7A86}\x{7A87}\x{7A88}\x{7A89}\x{7A8A}\x{7A8B}\x{7A8C}\x{7A8D}\x{7A8E}'
. '\x{7A8F}\x{7A90}\x{7A91}\x{7A92}\x{7A93}\x{7A94}\x{7A95}\x{7A96}\x{7A97}'
. '\x{7A98}\x{7A99}\x{7A9C}\x{7A9D}\x{7A9E}\x{7A9F}\x{7AA0}\x{7AA1}\x{7AA2}'
. '\x{7AA3}\x{7AA4}\x{7AA5}\x{7AA6}\x{7AA7}\x{7AA8}\x{7AA9}\x{7AAA}\x{7AAB}'
. '\x{7AAC}\x{7AAD}\x{7AAE}\x{7AAF}\x{7AB0}\x{7AB1}\x{7AB2}\x{7AB3}\x{7AB4}'
. '\x{7AB5}\x{7AB6}\x{7AB7}\x{7AB8}\x{7ABA}\x{7ABE}\x{7ABF}\x{7AC0}\x{7AC1}'
. '\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}\x{7AC9}\x{7ACA}\x{7ACB}\x{7ACC}\x{7ACD}'
. '\x{7ACE}\x{7ACF}\x{7AD0}\x{7AD1}\x{7AD2}\x{7AD3}\x{7AD4}\x{7AD5}\x{7AD6}'
. '\x{7AD8}\x{7AD9}\x{7ADB}\x{7ADC}\x{7ADD}\x{7ADE}\x{7ADF}\x{7AE0}\x{7AE1}'
. '\x{7AE2}\x{7AE3}\x{7AE4}\x{7AE5}\x{7AE6}\x{7AE7}\x{7AE8}\x{7AEA}\x{7AEB}'
. '\x{7AEC}\x{7AED}\x{7AEE}\x{7AEF}\x{7AF0}\x{7AF1}\x{7AF2}\x{7AF3}\x{7AF4}'
. '\x{7AF6}\x{7AF7}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFB}\x{7AFD}\x{7AFE}\x{7AFF}'
. '\x{7B00}\x{7B01}\x{7B02}\x{7B03}\x{7B04}\x{7B05}\x{7B06}\x{7B08}\x{7B09}'
. '\x{7B0A}\x{7B0B}\x{7B0C}\x{7B0D}\x{7B0E}\x{7B0F}\x{7B10}\x{7B11}\x{7B12}'
. '\x{7B13}\x{7B14}\x{7B15}\x{7B16}\x{7B17}\x{7B18}\x{7B19}\x{7B1A}\x{7B1B}'
. '\x{7B1C}\x{7B1D}\x{7B1E}\x{7B20}\x{7B21}\x{7B22}\x{7B23}\x{7B24}\x{7B25}'
. '\x{7B26}\x{7B28}\x{7B2A}\x{7B2B}\x{7B2C}\x{7B2D}\x{7B2E}\x{7B2F}\x{7B30}'
. '\x{7B31}\x{7B32}\x{7B33}\x{7B34}\x{7B35}\x{7B36}\x{7B37}\x{7B38}\x{7B39}'
. '\x{7B3A}\x{7B3B}\x{7B3C}\x{7B3D}\x{7B3E}\x{7B3F}\x{7B40}\x{7B41}\x{7B43}'
. '\x{7B44}\x{7B45}\x{7B46}\x{7B47}\x{7B48}\x{7B49}\x{7B4A}\x{7B4B}\x{7B4C}'
. '\x{7B4D}\x{7B4E}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B55}\x{7B56}'
. '\x{7B57}\x{7B58}\x{7B59}\x{7B5A}\x{7B5B}\x{7B5C}\x{7B5D}\x{7B5E}\x{7B5F}'
. '\x{7B60}\x{7B61}\x{7B62}\x{7B63}\x{7B64}\x{7B65}\x{7B66}\x{7B67}\x{7B68}'
. '\x{7B69}\x{7B6A}\x{7B6B}\x{7B6C}\x{7B6D}\x{7B6E}\x{7B70}\x{7B71}\x{7B72}'
. '\x{7B73}\x{7B74}\x{7B75}\x{7B76}\x{7B77}\x{7B78}\x{7B79}\x{7B7B}\x{7B7C}'
. '\x{7B7D}\x{7B7E}\x{7B7F}\x{7B80}\x{7B81}\x{7B82}\x{7B83}\x{7B84}\x{7B85}'
. '\x{7B87}\x{7B88}\x{7B89}\x{7B8A}\x{7B8B}\x{7B8C}\x{7B8D}\x{7B8E}\x{7B8F}'
. '\x{7B90}\x{7B91}\x{7B93}\x{7B94}\x{7B95}\x{7B96}\x{7B97}\x{7B98}\x{7B99}'
. '\x{7B9A}\x{7B9B}\x{7B9C}\x{7B9D}\x{7B9E}\x{7B9F}\x{7BA0}\x{7BA1}\x{7BA2}'
. '\x{7BA4}\x{7BA6}\x{7BA7}\x{7BA8}\x{7BA9}\x{7BAA}\x{7BAB}\x{7BAC}\x{7BAD}'
. '\x{7BAE}\x{7BAF}\x{7BB1}\x{7BB3}\x{7BB4}\x{7BB5}\x{7BB6}\x{7BB7}\x{7BB8}'
. '\x{7BB9}\x{7BBA}\x{7BBB}\x{7BBC}\x{7BBD}\x{7BBE}\x{7BBF}\x{7BC0}\x{7BC1}'
. '\x{7BC2}\x{7BC3}\x{7BC4}\x{7BC5}\x{7BC6}\x{7BC7}\x{7BC8}\x{7BC9}\x{7BCA}'
. '\x{7BCB}\x{7BCC}\x{7BCD}\x{7BCE}\x{7BD0}\x{7BD1}\x{7BD2}\x{7BD3}\x{7BD4}'
. '\x{7BD5}\x{7BD6}\x{7BD7}\x{7BD8}\x{7BD9}\x{7BDA}\x{7BDB}\x{7BDC}\x{7BDD}'
. '\x{7BDE}\x{7BDF}\x{7BE0}\x{7BE1}\x{7BE2}\x{7BE3}\x{7BE4}\x{7BE5}\x{7BE6}'
. '\x{7BE7}\x{7BE8}\x{7BE9}\x{7BEA}\x{7BEB}\x{7BEC}\x{7BED}\x{7BEE}\x{7BEF}'
. '\x{7BF0}\x{7BF1}\x{7BF2}\x{7BF3}\x{7BF4}\x{7BF5}\x{7BF6}\x{7BF7}\x{7BF8}'
. '\x{7BF9}\x{7BFB}\x{7BFC}\x{7BFD}\x{7BFE}\x{7BFF}\x{7C00}\x{7C01}\x{7C02}'
. '\x{7C03}\x{7C04}\x{7C05}\x{7C06}\x{7C07}\x{7C08}\x{7C09}\x{7C0A}\x{7C0B}'
. '\x{7C0C}\x{7C0D}\x{7C0E}\x{7C0F}\x{7C10}\x{7C11}\x{7C12}\x{7C13}\x{7C15}'
. '\x{7C16}\x{7C17}\x{7C18}\x{7C19}\x{7C1A}\x{7C1C}\x{7C1D}\x{7C1E}\x{7C1F}'
. '\x{7C20}\x{7C21}\x{7C22}\x{7C23}\x{7C24}\x{7C25}\x{7C26}\x{7C27}\x{7C28}'
. '\x{7C29}\x{7C2A}\x{7C2B}\x{7C2C}\x{7C2D}\x{7C30}\x{7C31}\x{7C32}\x{7C33}'
. '\x{7C34}\x{7C35}\x{7C36}\x{7C37}\x{7C38}\x{7C39}\x{7C3A}\x{7C3B}\x{7C3C}'
. '\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C41}\x{7C42}\x{7C43}\x{7C44}\x{7C45}'
. '\x{7C46}\x{7C47}\x{7C48}\x{7C49}\x{7C4A}\x{7C4B}\x{7C4C}\x{7C4D}\x{7C4E}'
. '\x{7C50}\x{7C51}\x{7C53}\x{7C54}\x{7C56}\x{7C57}\x{7C58}\x{7C59}\x{7C5A}'
. '\x{7C5B}\x{7C5C}\x{7C5E}\x{7C5F}\x{7C60}\x{7C61}\x{7C62}\x{7C63}\x{7C64}'
. '\x{7C65}\x{7C66}\x{7C67}\x{7C68}\x{7C69}\x{7C6A}\x{7C6B}\x{7C6C}\x{7C6D}'
. '\x{7C6E}\x{7C6F}\x{7C70}\x{7C71}\x{7C72}\x{7C73}\x{7C74}\x{7C75}\x{7C77}'
. '\x{7C78}\x{7C79}\x{7C7A}\x{7C7B}\x{7C7C}\x{7C7D}\x{7C7E}\x{7C7F}\x{7C80}'
. '\x{7C81}\x{7C82}\x{7C84}\x{7C85}\x{7C86}\x{7C88}\x{7C89}\x{7C8A}\x{7C8B}'
. '\x{7C8C}\x{7C8D}\x{7C8E}\x{7C8F}\x{7C90}\x{7C91}\x{7C92}\x{7C94}\x{7C95}'
. '\x{7C96}\x{7C97}\x{7C98}\x{7C99}\x{7C9B}\x{7C9C}\x{7C9D}\x{7C9E}\x{7C9F}'
. '\x{7CA0}\x{7CA1}\x{7CA2}\x{7CA3}\x{7CA4}\x{7CA5}\x{7CA6}\x{7CA7}\x{7CA8}'
. '\x{7CA9}\x{7CAA}\x{7CAD}\x{7CAE}\x{7CAF}\x{7CB0}\x{7CB1}\x{7CB2}\x{7CB3}'
. '\x{7CB4}\x{7CB5}\x{7CB6}\x{7CB7}\x{7CB8}\x{7CB9}\x{7CBA}\x{7CBB}\x{7CBC}'
. '\x{7CBD}\x{7CBE}\x{7CBF}\x{7CC0}\x{7CC1}\x{7CC2}\x{7CC3}\x{7CC4}\x{7CC5}'
. '\x{7CC6}\x{7CC7}\x{7CC8}\x{7CC9}\x{7CCA}\x{7CCB}\x{7CCC}\x{7CCD}\x{7CCE}'
. '\x{7CCF}\x{7CD0}\x{7CD1}\x{7CD2}\x{7CD4}\x{7CD5}\x{7CD6}\x{7CD7}\x{7CD8}'
. '\x{7CD9}\x{7CDC}\x{7CDD}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE4}\x{7CE7}'
. '\x{7CE8}\x{7CE9}\x{7CEA}\x{7CEB}\x{7CEC}\x{7CED}\x{7CEE}\x{7CEF}\x{7CF0}'
. '\x{7CF1}\x{7CF2}\x{7CF3}\x{7CF4}\x{7CF5}\x{7CF6}\x{7CF7}\x{7CF8}\x{7CF9}'
. '\x{7CFA}\x{7CFB}\x{7CFD}\x{7CFE}\x{7D00}\x{7D01}\x{7D02}\x{7D03}\x{7D04}'
. '\x{7D05}\x{7D06}\x{7D07}\x{7D08}\x{7D09}\x{7D0A}\x{7D0B}\x{7D0C}\x{7D0D}'
. '\x{7D0E}\x{7D0F}\x{7D10}\x{7D11}\x{7D12}\x{7D13}\x{7D14}\x{7D15}\x{7D16}'
. '\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D1D}\x{7D1E}\x{7D1F}'
. '\x{7D20}\x{7D21}\x{7D22}\x{7D24}\x{7D25}\x{7D26}\x{7D27}\x{7D28}\x{7D29}'
. '\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D31}\x{7D32}\x{7D33}\x{7D34}'
. '\x{7D35}\x{7D36}\x{7D37}\x{7D38}\x{7D39}\x{7D3A}\x{7D3B}\x{7D3C}\x{7D3D}'
. '\x{7D3E}\x{7D3F}\x{7D40}\x{7D41}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}'
. '\x{7D47}\x{7D49}\x{7D4A}\x{7D4B}\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D51}'
. '\x{7D52}\x{7D53}\x{7D54}\x{7D55}\x{7D56}\x{7D57}\x{7D58}\x{7D59}\x{7D5B}'
. '\x{7D5C}\x{7D5D}\x{7D5E}\x{7D5F}\x{7D60}\x{7D61}\x{7D62}\x{7D63}\x{7D65}'
. '\x{7D66}\x{7D67}\x{7D68}\x{7D69}\x{7D6A}\x{7D6B}\x{7D6C}\x{7D6D}\x{7D6E}'
. '\x{7D6F}\x{7D70}\x{7D71}\x{7D72}\x{7D73}\x{7D74}\x{7D75}\x{7D76}\x{7D77}'
. '\x{7D79}\x{7D7A}\x{7D7B}\x{7D7C}\x{7D7D}\x{7D7E}\x{7D7F}\x{7D80}\x{7D81}'
. '\x{7D83}\x{7D84}\x{7D85}\x{7D86}\x{7D87}\x{7D88}\x{7D89}\x{7D8A}\x{7D8B}'
. '\x{7D8C}\x{7D8D}\x{7D8E}\x{7D8F}\x{7D90}\x{7D91}\x{7D92}\x{7D93}\x{7D94}'
. '\x{7D96}\x{7D97}\x{7D99}\x{7D9B}\x{7D9C}\x{7D9D}\x{7D9E}\x{7D9F}\x{7DA0}'
. '\x{7DA1}\x{7DA2}\x{7DA3}\x{7DA5}\x{7DA6}\x{7DA7}\x{7DA9}\x{7DAA}\x{7DAB}'
. '\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}\x{7DB1}\x{7DB2}\x{7DB3}\x{7DB4}'
. '\x{7DB5}\x{7DB6}\x{7DB7}\x{7DB8}\x{7DB9}\x{7DBA}\x{7DBB}\x{7DBC}\x{7DBD}'
. '\x{7DBE}\x{7DBF}\x{7DC0}\x{7DC1}\x{7DC2}\x{7DC3}\x{7DC4}\x{7DC5}\x{7DC6}'
. '\x{7DC7}\x{7DC8}\x{7DC9}\x{7DCA}\x{7DCB}\x{7DCC}\x{7DCE}\x{7DCF}\x{7DD0}'
. '\x{7DD1}\x{7DD2}\x{7DD4}\x{7DD5}\x{7DD6}\x{7DD7}\x{7DD8}\x{7DD9}\x{7DDA}'
. '\x{7DDB}\x{7DDD}\x{7DDE}\x{7DDF}\x{7DE0}\x{7DE1}\x{7DE2}\x{7DE3}\x{7DE6}'
. '\x{7DE7}\x{7DE8}\x{7DE9}\x{7DEA}\x{7DEC}\x{7DED}\x{7DEE}\x{7DEF}\x{7DF0}'
. '\x{7DF1}\x{7DF2}\x{7DF3}\x{7DF4}\x{7DF5}\x{7DF6}\x{7DF7}\x{7DF8}\x{7DF9}'
. '\x{7DFA}\x{7DFB}\x{7DFC}\x{7E00}\x{7E01}\x{7E02}\x{7E03}\x{7E04}\x{7E05}'
. '\x{7E06}\x{7E07}\x{7E08}\x{7E09}\x{7E0A}\x{7E0B}\x{7E0C}\x{7E0D}\x{7E0E}'
. '\x{7E0F}\x{7E10}\x{7E11}\x{7E12}\x{7E13}\x{7E14}\x{7E15}\x{7E16}\x{7E17}'
. '\x{7E19}\x{7E1A}\x{7E1B}\x{7E1C}\x{7E1D}\x{7E1E}\x{7E1F}\x{7E20}\x{7E21}'
. '\x{7E22}\x{7E23}\x{7E24}\x{7E25}\x{7E26}\x{7E27}\x{7E28}\x{7E29}\x{7E2A}'
. '\x{7E2B}\x{7E2C}\x{7E2D}\x{7E2E}\x{7E2F}\x{7E30}\x{7E31}\x{7E32}\x{7E33}'
. '\x{7E34}\x{7E35}\x{7E36}\x{7E37}\x{7E38}\x{7E39}\x{7E3A}\x{7E3B}\x{7E3C}'
. '\x{7E3D}\x{7E3E}\x{7E3F}\x{7E40}\x{7E41}\x{7E42}\x{7E43}\x{7E44}\x{7E45}'
. '\x{7E46}\x{7E47}\x{7E48}\x{7E49}\x{7E4C}\x{7E4D}\x{7E4E}\x{7E4F}\x{7E50}'
. '\x{7E51}\x{7E52}\x{7E53}\x{7E54}\x{7E55}\x{7E56}\x{7E57}\x{7E58}\x{7E59}'
. '\x{7E5A}\x{7E5C}\x{7E5D}\x{7E5E}\x{7E5F}\x{7E60}\x{7E61}\x{7E62}\x{7E63}'
. '\x{7E65}\x{7E66}\x{7E67}\x{7E68}\x{7E69}\x{7E6A}\x{7E6B}\x{7E6C}\x{7E6D}'
. '\x{7E6E}\x{7E6F}\x{7E70}\x{7E71}\x{7E72}\x{7E73}\x{7E74}\x{7E75}\x{7E76}'
. '\x{7E77}\x{7E78}\x{7E79}\x{7E7A}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7E}\x{7E7F}'
. '\x{7E80}\x{7E81}\x{7E82}\x{7E83}\x{7E84}\x{7E85}\x{7E86}\x{7E87}\x{7E88}'
. '\x{7E89}\x{7E8A}\x{7E8B}\x{7E8C}\x{7E8D}\x{7E8E}\x{7E8F}\x{7E90}\x{7E91}'
. '\x{7E92}\x{7E93}\x{7E94}\x{7E95}\x{7E96}\x{7E97}\x{7E98}\x{7E99}\x{7E9A}'
. '\x{7E9B}\x{7E9C}\x{7E9E}\x{7E9F}\x{7EA0}\x{7EA1}\x{7EA2}\x{7EA3}\x{7EA4}'
. '\x{7EA5}\x{7EA6}\x{7EA7}\x{7EA8}\x{7EA9}\x{7EAA}\x{7EAB}\x{7EAC}\x{7EAD}'
. '\x{7EAE}\x{7EAF}\x{7EB0}\x{7EB1}\x{7EB2}\x{7EB3}\x{7EB4}\x{7EB5}\x{7EB6}'
. '\x{7EB7}\x{7EB8}\x{7EB9}\x{7EBA}\x{7EBB}\x{7EBC}\x{7EBD}\x{7EBE}\x{7EBF}'
. '\x{7EC0}\x{7EC1}\x{7EC2}\x{7EC3}\x{7EC4}\x{7EC5}\x{7EC6}\x{7EC7}\x{7EC8}'
. '\x{7EC9}\x{7ECA}\x{7ECB}\x{7ECC}\x{7ECD}\x{7ECE}\x{7ECF}\x{7ED0}\x{7ED1}'
. '\x{7ED2}\x{7ED3}\x{7ED4}\x{7ED5}\x{7ED6}\x{7ED7}\x{7ED8}\x{7ED9}\x{7EDA}'
. '\x{7EDB}\x{7EDC}\x{7EDD}\x{7EDE}\x{7EDF}\x{7EE0}\x{7EE1}\x{7EE2}\x{7EE3}'
. '\x{7EE4}\x{7EE5}\x{7EE6}\x{7EE7}\x{7EE8}\x{7EE9}\x{7EEA}\x{7EEB}\x{7EEC}'
. '\x{7EED}\x{7EEE}\x{7EEF}\x{7EF0}\x{7EF1}\x{7EF2}\x{7EF3}\x{7EF4}\x{7EF5}'
. '\x{7EF6}\x{7EF7}\x{7EF8}\x{7EF9}\x{7EFA}\x{7EFB}\x{7EFC}\x{7EFD}\x{7EFE}'
. '\x{7EFF}\x{7F00}\x{7F01}\x{7F02}\x{7F03}\x{7F04}\x{7F05}\x{7F06}\x{7F07}'
. '\x{7F08}\x{7F09}\x{7F0A}\x{7F0B}\x{7F0C}\x{7F0D}\x{7F0E}\x{7F0F}\x{7F10}'
. '\x{7F11}\x{7F12}\x{7F13}\x{7F14}\x{7F15}\x{7F16}\x{7F17}\x{7F18}\x{7F19}'
. '\x{7F1A}\x{7F1B}\x{7F1C}\x{7F1D}\x{7F1E}\x{7F1F}\x{7F20}\x{7F21}\x{7F22}'
. '\x{7F23}\x{7F24}\x{7F25}\x{7F26}\x{7F27}\x{7F28}\x{7F29}\x{7F2A}\x{7F2B}'
. '\x{7F2C}\x{7F2D}\x{7F2E}\x{7F2F}\x{7F30}\x{7F31}\x{7F32}\x{7F33}\x{7F34}'
. '\x{7F35}\x{7F36}\x{7F37}\x{7F38}\x{7F39}\x{7F3A}\x{7F3D}\x{7F3E}\x{7F3F}'
. '\x{7F40}\x{7F42}\x{7F43}\x{7F44}\x{7F45}\x{7F47}\x{7F48}\x{7F49}\x{7F4A}'
. '\x{7F4B}\x{7F4C}\x{7F4D}\x{7F4E}\x{7F4F}\x{7F50}\x{7F51}\x{7F52}\x{7F53}'
. '\x{7F54}\x{7F55}\x{7F56}\x{7F57}\x{7F58}\x{7F5A}\x{7F5B}\x{7F5C}\x{7F5D}'
. '\x{7F5E}\x{7F5F}\x{7F60}\x{7F61}\x{7F62}\x{7F63}\x{7F64}\x{7F65}\x{7F66}'
. '\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6C}\x{7F6D}\x{7F6E}\x{7F6F}'
. '\x{7F70}\x{7F71}\x{7F72}\x{7F73}\x{7F74}\x{7F75}\x{7F76}\x{7F77}\x{7F78}'
. '\x{7F79}\x{7F7A}\x{7F7B}\x{7F7C}\x{7F7D}\x{7F7E}\x{7F7F}\x{7F80}\x{7F81}'
. '\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}\x{7F88}\x{7F89}\x{7F8A}\x{7F8B}'
. '\x{7F8C}\x{7F8D}\x{7F8E}\x{7F8F}\x{7F91}\x{7F92}\x{7F93}\x{7F94}\x{7F95}'
. '\x{7F96}\x{7F98}\x{7F9A}\x{7F9B}\x{7F9C}\x{7F9D}\x{7F9E}\x{7F9F}\x{7FA0}'
. '\x{7FA1}\x{7FA2}\x{7FA3}\x{7FA4}\x{7FA5}\x{7FA6}\x{7FA7}\x{7FA8}\x{7FA9}'
. '\x{7FAA}\x{7FAB}\x{7FAC}\x{7FAD}\x{7FAE}\x{7FAF}\x{7FB0}\x{7FB1}\x{7FB2}'
. '\x{7FB3}\x{7FB5}\x{7FB6}\x{7FB7}\x{7FB8}\x{7FB9}\x{7FBA}\x{7FBB}\x{7FBC}'
. '\x{7FBD}\x{7FBE}\x{7FBF}\x{7FC0}\x{7FC1}\x{7FC2}\x{7FC3}\x{7FC4}\x{7FC5}'
. '\x{7FC6}\x{7FC7}\x{7FC8}\x{7FC9}\x{7FCA}\x{7FCB}\x{7FCC}\x{7FCD}\x{7FCE}'
. '\x{7FCF}\x{7FD0}\x{7FD1}\x{7FD2}\x{7FD3}\x{7FD4}\x{7FD5}\x{7FD7}\x{7FD8}'
. '\x{7FD9}\x{7FDA}\x{7FDB}\x{7FDC}\x{7FDE}\x{7FDF}\x{7FE0}\x{7FE1}\x{7FE2}'
. '\x{7FE3}\x{7FE5}\x{7FE6}\x{7FE7}\x{7FE8}\x{7FE9}\x{7FEA}\x{7FEB}\x{7FEC}'
. '\x{7FED}\x{7FEE}\x{7FEF}\x{7FF0}\x{7FF1}\x{7FF2}\x{7FF3}\x{7FF4}\x{7FF5}'
. '\x{7FF6}\x{7FF7}\x{7FF8}\x{7FF9}\x{7FFA}\x{7FFB}\x{7FFC}\x{7FFD}\x{7FFE}'
. '\x{7FFF}\x{8000}\x{8001}\x{8002}\x{8003}\x{8004}\x{8005}\x{8006}\x{8007}'
. '\x{8008}\x{8009}\x{800B}\x{800C}\x{800D}\x{800E}\x{800F}\x{8010}\x{8011}'
. '\x{8012}\x{8013}\x{8014}\x{8015}\x{8016}\x{8017}\x{8018}\x{8019}\x{801A}'
. '\x{801B}\x{801C}\x{801D}\x{801E}\x{801F}\x{8020}\x{8021}\x{8022}\x{8023}'
. '\x{8024}\x{8025}\x{8026}\x{8027}\x{8028}\x{8029}\x{802A}\x{802B}\x{802C}'
. '\x{802D}\x{802E}\x{8030}\x{8031}\x{8032}\x{8033}\x{8034}\x{8035}\x{8036}'
. '\x{8037}\x{8038}\x{8039}\x{803A}\x{803B}\x{803D}\x{803E}\x{803F}\x{8041}'
. '\x{8042}\x{8043}\x{8044}\x{8045}\x{8046}\x{8047}\x{8048}\x{8049}\x{804A}'
. '\x{804B}\x{804C}\x{804D}\x{804E}\x{804F}\x{8050}\x{8051}\x{8052}\x{8053}'
. '\x{8054}\x{8055}\x{8056}\x{8057}\x{8058}\x{8059}\x{805A}\x{805B}\x{805C}'
. '\x{805D}\x{805E}\x{805F}\x{8060}\x{8061}\x{8062}\x{8063}\x{8064}\x{8065}'
. '\x{8067}\x{8068}\x{8069}\x{806A}\x{806B}\x{806C}\x{806D}\x{806E}\x{806F}'
. '\x{8070}\x{8071}\x{8072}\x{8073}\x{8074}\x{8075}\x{8076}\x{8077}\x{8078}'
. '\x{8079}\x{807A}\x{807B}\x{807C}\x{807D}\x{807E}\x{807F}\x{8080}\x{8081}'
. '\x{8082}\x{8083}\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808A}\x{808B}'
. '\x{808C}\x{808D}\x{808F}\x{8090}\x{8091}\x{8092}\x{8093}\x{8095}\x{8096}'
. '\x{8097}\x{8098}\x{8099}\x{809A}\x{809B}\x{809C}\x{809D}\x{809E}\x{809F}'
. '\x{80A0}\x{80A1}\x{80A2}\x{80A3}\x{80A4}\x{80A5}\x{80A9}\x{80AA}\x{80AB}'
. '\x{80AD}\x{80AE}\x{80AF}\x{80B0}\x{80B1}\x{80B2}\x{80B4}\x{80B5}\x{80B6}'
. '\x{80B7}\x{80B8}\x{80BA}\x{80BB}\x{80BC}\x{80BD}\x{80BE}\x{80BF}\x{80C0}'
. '\x{80C1}\x{80C2}\x{80C3}\x{80C4}\x{80C5}\x{80C6}\x{80C7}\x{80C8}\x{80C9}'
. '\x{80CA}\x{80CB}\x{80CC}\x{80CD}\x{80CE}\x{80CF}\x{80D0}\x{80D1}\x{80D2}'
. '\x{80D3}\x{80D4}\x{80D5}\x{80D6}\x{80D7}\x{80D8}\x{80D9}\x{80DA}\x{80DB}'
. '\x{80DC}\x{80DD}\x{80DE}\x{80E0}\x{80E1}\x{80E2}\x{80E3}\x{80E4}\x{80E5}'
. '\x{80E6}\x{80E7}\x{80E8}\x{80E9}\x{80EA}\x{80EB}\x{80EC}\x{80ED}\x{80EE}'
. '\x{80EF}\x{80F0}\x{80F1}\x{80F2}\x{80F3}\x{80F4}\x{80F5}\x{80F6}\x{80F7}'
. '\x{80F8}\x{80F9}\x{80FA}\x{80FB}\x{80FC}\x{80FD}\x{80FE}\x{80FF}\x{8100}'
. '\x{8101}\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{810B}'
. '\x{810C}\x{810D}\x{810E}\x{810F}\x{8110}\x{8111}\x{8112}\x{8113}\x{8114}'
. '\x{8115}\x{8116}\x{8118}\x{8119}\x{811A}\x{811B}\x{811C}\x{811D}\x{811E}'
. '\x{811F}\x{8120}\x{8121}\x{8122}\x{8123}\x{8124}\x{8125}\x{8126}\x{8127}'
. '\x{8128}\x{8129}\x{812A}\x{812B}\x{812C}\x{812D}\x{812E}\x{812F}\x{8130}'
. '\x{8131}\x{8132}\x{8136}\x{8137}\x{8138}\x{8139}\x{813A}\x{813B}\x{813C}'
. '\x{813D}\x{813E}\x{813F}\x{8140}\x{8141}\x{8142}\x{8143}\x{8144}\x{8145}'
. '\x{8146}\x{8147}\x{8148}\x{8149}\x{814A}\x{814B}\x{814C}\x{814D}\x{814E}'
. '\x{814F}\x{8150}\x{8151}\x{8152}\x{8153}\x{8154}\x{8155}\x{8156}\x{8157}'
. '\x{8158}\x{8159}\x{815A}\x{815B}\x{815C}\x{815D}\x{815E}\x{8160}\x{8161}'
. '\x{8162}\x{8163}\x{8164}\x{8165}\x{8166}\x{8167}\x{8168}\x{8169}\x{816A}'
. '\x{816B}\x{816C}\x{816D}\x{816E}\x{816F}\x{8170}\x{8171}\x{8172}\x{8173}'
. '\x{8174}\x{8175}\x{8176}\x{8177}\x{8178}\x{8179}\x{817A}\x{817B}\x{817C}'
. '\x{817D}\x{817E}\x{817F}\x{8180}\x{8181}\x{8182}\x{8183}\x{8185}\x{8186}'
. '\x{8187}\x{8188}\x{8189}\x{818A}\x{818B}\x{818C}\x{818D}\x{818E}\x{818F}'
. '\x{8191}\x{8192}\x{8193}\x{8194}\x{8195}\x{8197}\x{8198}\x{8199}\x{819A}'
. '\x{819B}\x{819C}\x{819D}\x{819E}\x{819F}\x{81A0}\x{81A1}\x{81A2}\x{81A3}'
. '\x{81A4}\x{81A5}\x{81A6}\x{81A7}\x{81A8}\x{81A9}\x{81AA}\x{81AB}\x{81AC}'
. '\x{81AD}\x{81AE}\x{81AF}\x{81B0}\x{81B1}\x{81B2}\x{81B3}\x{81B4}\x{81B5}'
. '\x{81B6}\x{81B7}\x{81B8}\x{81B9}\x{81BA}\x{81BB}\x{81BC}\x{81BD}\x{81BE}'
. '\x{81BF}\x{81C0}\x{81C1}\x{81C2}\x{81C3}\x{81C4}\x{81C5}\x{81C6}\x{81C7}'
. '\x{81C8}\x{81C9}\x{81CA}\x{81CC}\x{81CD}\x{81CE}\x{81CF}\x{81D0}\x{81D1}'
. '\x{81D2}\x{81D4}\x{81D5}\x{81D6}\x{81D7}\x{81D8}\x{81D9}\x{81DA}\x{81DB}'
. '\x{81DC}\x{81DD}\x{81DE}\x{81DF}\x{81E0}\x{81E1}\x{81E2}\x{81E3}\x{81E5}'
. '\x{81E6}\x{81E7}\x{81E8}\x{81E9}\x{81EA}\x{81EB}\x{81EC}\x{81ED}\x{81EE}'
. '\x{81F1}\x{81F2}\x{81F3}\x{81F4}\x{81F5}\x{81F6}\x{81F7}\x{81F8}\x{81F9}'
. '\x{81FA}\x{81FB}\x{81FC}\x{81FD}\x{81FE}\x{81FF}\x{8200}\x{8201}\x{8202}'
. '\x{8203}\x{8204}\x{8205}\x{8206}\x{8207}\x{8208}\x{8209}\x{820A}\x{820B}'
. '\x{820C}\x{820D}\x{820E}\x{820F}\x{8210}\x{8211}\x{8212}\x{8214}\x{8215}'
. '\x{8216}\x{8218}\x{8219}\x{821A}\x{821B}\x{821C}\x{821D}\x{821E}\x{821F}'
. '\x{8220}\x{8221}\x{8222}\x{8223}\x{8225}\x{8226}\x{8227}\x{8228}\x{8229}'
. '\x{822A}\x{822B}\x{822C}\x{822D}\x{822F}\x{8230}\x{8231}\x{8232}\x{8233}'
. '\x{8234}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{823A}\x{823B}\x{823C}'
. '\x{823D}\x{823E}\x{823F}\x{8240}\x{8242}\x{8243}\x{8244}\x{8245}\x{8246}'
. '\x{8247}\x{8248}\x{8249}\x{824A}\x{824B}\x{824C}\x{824D}\x{824E}\x{824F}'
. '\x{8250}\x{8251}\x{8252}\x{8253}\x{8254}\x{8255}\x{8256}\x{8257}\x{8258}'
. '\x{8259}\x{825A}\x{825B}\x{825C}\x{825D}\x{825E}\x{825F}\x{8260}\x{8261}'
. '\x{8263}\x{8264}\x{8266}\x{8267}\x{8268}\x{8269}\x{826A}\x{826B}\x{826C}'
. '\x{826D}\x{826E}\x{826F}\x{8270}\x{8271}\x{8272}\x{8273}\x{8274}\x{8275}'
. '\x{8276}\x{8277}\x{8278}\x{8279}\x{827A}\x{827B}\x{827C}\x{827D}\x{827E}'
. '\x{827F}\x{8280}\x{8281}\x{8282}\x{8283}\x{8284}\x{8285}\x{8286}\x{8287}'
. '\x{8288}\x{8289}\x{828A}\x{828B}\x{828D}\x{828E}\x{828F}\x{8290}\x{8291}'
. '\x{8292}\x{8293}\x{8294}\x{8295}\x{8296}\x{8297}\x{8298}\x{8299}\x{829A}'
. '\x{829B}\x{829C}\x{829D}\x{829E}\x{829F}\x{82A0}\x{82A1}\x{82A2}\x{82A3}'
. '\x{82A4}\x{82A5}\x{82A6}\x{82A7}\x{82A8}\x{82A9}\x{82AA}\x{82AB}\x{82AC}'
. '\x{82AD}\x{82AE}\x{82AF}\x{82B0}\x{82B1}\x{82B3}\x{82B4}\x{82B5}\x{82B6}'
. '\x{82B7}\x{82B8}\x{82B9}\x{82BA}\x{82BB}\x{82BC}\x{82BD}\x{82BE}\x{82BF}'
. '\x{82C0}\x{82C1}\x{82C2}\x{82C3}\x{82C4}\x{82C5}\x{82C6}\x{82C7}\x{82C8}'
. '\x{82C9}\x{82CA}\x{82CB}\x{82CC}\x{82CD}\x{82CE}\x{82CF}\x{82D0}\x{82D1}'
. '\x{82D2}\x{82D3}\x{82D4}\x{82D5}\x{82D6}\x{82D7}\x{82D8}\x{82D9}\x{82DA}'
. '\x{82DB}\x{82DC}\x{82DD}\x{82DE}\x{82DF}\x{82E0}\x{82E1}\x{82E3}\x{82E4}'
. '\x{82E5}\x{82E6}\x{82E7}\x{82E8}\x{82E9}\x{82EA}\x{82EB}\x{82EC}\x{82ED}'
. '\x{82EE}\x{82EF}\x{82F0}\x{82F1}\x{82F2}\x{82F3}\x{82F4}\x{82F5}\x{82F6}'
. '\x{82F7}\x{82F8}\x{82F9}\x{82FA}\x{82FB}\x{82FD}\x{82FE}\x{82FF}\x{8300}'
. '\x{8301}\x{8302}\x{8303}\x{8304}\x{8305}\x{8306}\x{8307}\x{8308}\x{8309}'
. '\x{830B}\x{830C}\x{830D}\x{830E}\x{830F}\x{8311}\x{8312}\x{8313}\x{8314}'
. '\x{8315}\x{8316}\x{8317}\x{8318}\x{8319}\x{831A}\x{831B}\x{831C}\x{831D}'
. '\x{831E}\x{831F}\x{8320}\x{8321}\x{8322}\x{8323}\x{8324}\x{8325}\x{8326}'
. '\x{8327}\x{8328}\x{8329}\x{832A}\x{832B}\x{832C}\x{832D}\x{832E}\x{832F}'
. '\x{8331}\x{8332}\x{8333}\x{8334}\x{8335}\x{8336}\x{8337}\x{8338}\x{8339}'
. '\x{833A}\x{833B}\x{833C}\x{833D}\x{833E}\x{833F}\x{8340}\x{8341}\x{8342}'
. '\x{8343}\x{8344}\x{8345}\x{8346}\x{8347}\x{8348}\x{8349}\x{834A}\x{834B}'
. '\x{834C}\x{834D}\x{834E}\x{834F}\x{8350}\x{8351}\x{8352}\x{8353}\x{8354}'
. '\x{8356}\x{8357}\x{8358}\x{8359}\x{835A}\x{835B}\x{835C}\x{835D}\x{835E}'
. '\x{835F}\x{8360}\x{8361}\x{8362}\x{8363}\x{8364}\x{8365}\x{8366}\x{8367}'
. '\x{8368}\x{8369}\x{836A}\x{836B}\x{836C}\x{836D}\x{836E}\x{836F}\x{8370}'
. '\x{8371}\x{8372}\x{8373}\x{8374}\x{8375}\x{8376}\x{8377}\x{8378}\x{8379}'
. '\x{837A}\x{837B}\x{837C}\x{837D}\x{837E}\x{837F}\x{8380}\x{8381}\x{8382}'
. '\x{8383}\x{8384}\x{8385}\x{8386}\x{8387}\x{8388}\x{8389}\x{838A}\x{838B}'
. '\x{838C}\x{838D}\x{838E}\x{838F}\x{8390}\x{8391}\x{8392}\x{8393}\x{8394}'
. '\x{8395}\x{8396}\x{8397}\x{8398}\x{8399}\x{839A}\x{839B}\x{839C}\x{839D}'
. '\x{839E}\x{83A0}\x{83A1}\x{83A2}\x{83A3}\x{83A4}\x{83A5}\x{83A6}\x{83A7}'
. '\x{83A8}\x{83A9}\x{83AA}\x{83AB}\x{83AC}\x{83AD}\x{83AE}\x{83AF}\x{83B0}'
. '\x{83B1}\x{83B2}\x{83B3}\x{83B4}\x{83B6}\x{83B7}\x{83B8}\x{83B9}\x{83BA}'
. '\x{83BB}\x{83BC}\x{83BD}\x{83BF}\x{83C0}\x{83C1}\x{83C2}\x{83C3}\x{83C4}'
. '\x{83C5}\x{83C6}\x{83C7}\x{83C8}\x{83C9}\x{83CA}\x{83CB}\x{83CC}\x{83CD}'
. '\x{83CE}\x{83CF}\x{83D0}\x{83D1}\x{83D2}\x{83D3}\x{83D4}\x{83D5}\x{83D6}'
. '\x{83D7}\x{83D8}\x{83D9}\x{83DA}\x{83DB}\x{83DC}\x{83DD}\x{83DE}\x{83DF}'
. '\x{83E0}\x{83E1}\x{83E2}\x{83E3}\x{83E4}\x{83E5}\x{83E7}\x{83E8}\x{83E9}'
. '\x{83EA}\x{83EB}\x{83EC}\x{83EE}\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F3}'
. '\x{83F4}\x{83F5}\x{83F6}\x{83F7}\x{83F8}\x{83F9}\x{83FA}\x{83FB}\x{83FC}'
. '\x{83FD}\x{83FE}\x{83FF}\x{8400}\x{8401}\x{8402}\x{8403}\x{8404}\x{8405}'
. '\x{8406}\x{8407}\x{8408}\x{8409}\x{840A}\x{840B}\x{840C}\x{840D}\x{840E}'
. '\x{840F}\x{8410}\x{8411}\x{8412}\x{8413}\x{8415}\x{8418}\x{8419}\x{841A}'
. '\x{841B}\x{841C}\x{841D}\x{841E}\x{8421}\x{8422}\x{8423}\x{8424}\x{8425}'
. '\x{8426}\x{8427}\x{8428}\x{8429}\x{842A}\x{842B}\x{842C}\x{842D}\x{842E}'
. '\x{842F}\x{8430}\x{8431}\x{8432}\x{8433}\x{8434}\x{8435}\x{8436}\x{8437}'
. '\x{8438}\x{8439}\x{843A}\x{843B}\x{843C}\x{843D}\x{843E}\x{843F}\x{8440}'
. '\x{8441}\x{8442}\x{8443}\x{8444}\x{8445}\x{8446}\x{8447}\x{8448}\x{8449}'
. '\x{844A}\x{844B}\x{844C}\x{844D}\x{844E}\x{844F}\x{8450}\x{8451}\x{8452}'
. '\x{8453}\x{8454}\x{8455}\x{8456}\x{8457}\x{8459}\x{845A}\x{845B}\x{845C}'
. '\x{845D}\x{845E}\x{845F}\x{8460}\x{8461}\x{8462}\x{8463}\x{8464}\x{8465}'
. '\x{8466}\x{8467}\x{8468}\x{8469}\x{846A}\x{846B}\x{846C}\x{846D}\x{846E}'
. '\x{846F}\x{8470}\x{8471}\x{8472}\x{8473}\x{8474}\x{8475}\x{8476}\x{8477}'
. '\x{8478}\x{8479}\x{847A}\x{847B}\x{847C}\x{847D}\x{847E}\x{847F}\x{8480}'
. '\x{8481}\x{8482}\x{8484}\x{8485}\x{8486}\x{8487}\x{8488}\x{8489}\x{848A}'
. '\x{848B}\x{848C}\x{848D}\x{848E}\x{848F}\x{8490}\x{8491}\x{8492}\x{8493}'
. '\x{8494}\x{8496}\x{8497}\x{8498}\x{8499}\x{849A}\x{849B}\x{849C}\x{849D}'
. '\x{849E}\x{849F}\x{84A0}\x{84A1}\x{84A2}\x{84A3}\x{84A4}\x{84A5}\x{84A6}'
. '\x{84A7}\x{84A8}\x{84A9}\x{84AA}\x{84AB}\x{84AC}\x{84AE}\x{84AF}\x{84B0}'
. '\x{84B1}\x{84B2}\x{84B3}\x{84B4}\x{84B5}\x{84B6}\x{84B8}\x{84B9}\x{84BA}'
. '\x{84BB}\x{84BC}\x{84BD}\x{84BE}\x{84BF}\x{84C0}\x{84C1}\x{84C2}\x{84C4}'
. '\x{84C5}\x{84C6}\x{84C7}\x{84C8}\x{84C9}\x{84CA}\x{84CB}\x{84CC}\x{84CD}'
. '\x{84CE}\x{84CF}\x{84D0}\x{84D1}\x{84D2}\x{84D3}\x{84D4}\x{84D5}\x{84D6}'
. '\x{84D7}\x{84D8}\x{84D9}\x{84DB}\x{84DC}\x{84DD}\x{84DE}\x{84DF}\x{84E0}'
. '\x{84E1}\x{84E2}\x{84E3}\x{84E4}\x{84E5}\x{84E6}\x{84E7}\x{84E8}\x{84E9}'
. '\x{84EA}\x{84EB}\x{84EC}\x{84EE}\x{84EF}\x{84F0}\x{84F1}\x{84F2}\x{84F3}'
. '\x{84F4}\x{84F5}\x{84F6}\x{84F7}\x{84F8}\x{84F9}\x{84FA}\x{84FB}\x{84FC}'
. '\x{84FD}\x{84FE}\x{84FF}\x{8500}\x{8501}\x{8502}\x{8503}\x{8504}\x{8506}'
. '\x{8507}\x{8508}\x{8509}\x{850A}\x{850B}\x{850C}\x{850D}\x{850E}\x{850F}'
. '\x{8511}\x{8512}\x{8513}\x{8514}\x{8515}\x{8516}\x{8517}\x{8518}\x{8519}'
. '\x{851A}\x{851B}\x{851C}\x{851D}\x{851E}\x{851F}\x{8520}\x{8521}\x{8522}'
. '\x{8523}\x{8524}\x{8525}\x{8526}\x{8527}\x{8528}\x{8529}\x{852A}\x{852B}'
. '\x{852C}\x{852D}\x{852E}\x{852F}\x{8530}\x{8531}\x{8534}\x{8535}\x{8536}'
. '\x{8537}\x{8538}\x{8539}\x{853A}\x{853B}\x{853C}\x{853D}\x{853E}\x{853F}'
. '\x{8540}\x{8541}\x{8542}\x{8543}\x{8544}\x{8545}\x{8546}\x{8547}\x{8548}'
. '\x{8549}\x{854A}\x{854B}\x{854D}\x{854E}\x{854F}\x{8551}\x{8552}\x{8553}'
. '\x{8554}\x{8555}\x{8556}\x{8557}\x{8558}\x{8559}\x{855A}\x{855B}\x{855C}'
. '\x{855D}\x{855E}\x{855F}\x{8560}\x{8561}\x{8562}\x{8563}\x{8564}\x{8565}'
. '\x{8566}\x{8567}\x{8568}\x{8569}\x{856A}\x{856B}\x{856C}\x{856D}\x{856E}'
. '\x{856F}\x{8570}\x{8571}\x{8572}\x{8573}\x{8574}\x{8575}\x{8576}\x{8577}'
. '\x{8578}\x{8579}\x{857A}\x{857B}\x{857C}\x{857D}\x{857E}\x{8580}\x{8581}'
. '\x{8582}\x{8583}\x{8584}\x{8585}\x{8586}\x{8587}\x{8588}\x{8589}\x{858A}'
. '\x{858B}\x{858C}\x{858D}\x{858E}\x{858F}\x{8590}\x{8591}\x{8592}\x{8594}'
. '\x{8595}\x{8596}\x{8598}\x{8599}\x{859A}\x{859B}\x{859C}\x{859D}\x{859E}'
. '\x{859F}\x{85A0}\x{85A1}\x{85A2}\x{85A3}\x{85A4}\x{85A5}\x{85A6}\x{85A7}'
. '\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AD}\x{85AE}\x{85AF}\x{85B0}'
. '\x{85B1}\x{85B3}\x{85B4}\x{85B5}\x{85B6}\x{85B7}\x{85B8}\x{85B9}\x{85BA}'
. '\x{85BC}\x{85BD}\x{85BE}\x{85BF}\x{85C0}\x{85C1}\x{85C2}\x{85C3}\x{85C4}'
. '\x{85C5}\x{85C6}\x{85C7}\x{85C8}\x{85C9}\x{85CA}\x{85CB}\x{85CD}\x{85CE}'
. '\x{85CF}\x{85D0}\x{85D1}\x{85D2}\x{85D3}\x{85D4}\x{85D5}\x{85D6}\x{85D7}'
. '\x{85D8}\x{85D9}\x{85DA}\x{85DB}\x{85DC}\x{85DD}\x{85DE}\x{85DF}\x{85E0}'
. '\x{85E1}\x{85E2}\x{85E3}\x{85E4}\x{85E5}\x{85E6}\x{85E7}\x{85E8}\x{85E9}'
. '\x{85EA}\x{85EB}\x{85EC}\x{85ED}\x{85EF}\x{85F0}\x{85F1}\x{85F2}\x{85F4}'
. '\x{85F5}\x{85F6}\x{85F7}\x{85F8}\x{85F9}\x{85FA}\x{85FB}\x{85FD}\x{85FE}'
. '\x{85FF}\x{8600}\x{8601}\x{8602}\x{8604}\x{8605}\x{8606}\x{8607}\x{8608}'
. '\x{8609}\x{860A}\x{860B}\x{860C}\x{860F}\x{8611}\x{8612}\x{8613}\x{8614}'
. '\x{8616}\x{8617}\x{8618}\x{8619}\x{861A}\x{861B}\x{861C}\x{861E}\x{861F}'
. '\x{8620}\x{8621}\x{8622}\x{8623}\x{8624}\x{8625}\x{8626}\x{8627}\x{8628}'
. '\x{8629}\x{862A}\x{862B}\x{862C}\x{862D}\x{862E}\x{862F}\x{8630}\x{8631}'
. '\x{8632}\x{8633}\x{8634}\x{8635}\x{8636}\x{8638}\x{8639}\x{863A}\x{863B}'
. '\x{863C}\x{863D}\x{863E}\x{863F}\x{8640}\x{8641}\x{8642}\x{8643}\x{8644}'
. '\x{8645}\x{8646}\x{8647}\x{8648}\x{8649}\x{864A}\x{864B}\x{864C}\x{864D}'
. '\x{864E}\x{864F}\x{8650}\x{8651}\x{8652}\x{8653}\x{8654}\x{8655}\x{8656}'
. '\x{8658}\x{8659}\x{865A}\x{865B}\x{865C}\x{865D}\x{865E}\x{865F}\x{8660}'
. '\x{8661}\x{8662}\x{8663}\x{8664}\x{8665}\x{8666}\x{8667}\x{8668}\x{8669}'
. '\x{866A}\x{866B}\x{866C}\x{866D}\x{866E}\x{866F}\x{8670}\x{8671}\x{8672}'
. '\x{8673}\x{8674}\x{8676}\x{8677}\x{8678}\x{8679}\x{867A}\x{867B}\x{867C}'
. '\x{867D}\x{867E}\x{867F}\x{8680}\x{8681}\x{8682}\x{8683}\x{8684}\x{8685}'
. '\x{8686}\x{8687}\x{8688}\x{868A}\x{868B}\x{868C}\x{868D}\x{868E}\x{868F}'
. '\x{8690}\x{8691}\x{8693}\x{8694}\x{8695}\x{8696}\x{8697}\x{8698}\x{8699}'
. '\x{869A}\x{869B}\x{869C}\x{869D}\x{869E}\x{869F}\x{86A1}\x{86A2}\x{86A3}'
. '\x{86A4}\x{86A5}\x{86A7}\x{86A8}\x{86A9}\x{86AA}\x{86AB}\x{86AC}\x{86AD}'
. '\x{86AE}\x{86AF}\x{86B0}\x{86B1}\x{86B2}\x{86B3}\x{86B4}\x{86B5}\x{86B6}'
. '\x{86B7}\x{86B8}\x{86B9}\x{86BA}\x{86BB}\x{86BC}\x{86BD}\x{86BE}\x{86BF}'
. '\x{86C0}\x{86C1}\x{86C2}\x{86C3}\x{86C4}\x{86C5}\x{86C6}\x{86C7}\x{86C8}'
. '\x{86C9}\x{86CA}\x{86CB}\x{86CC}\x{86CE}\x{86CF}\x{86D0}\x{86D1}\x{86D2}'
. '\x{86D3}\x{86D4}\x{86D6}\x{86D7}\x{86D8}\x{86D9}\x{86DA}\x{86DB}\x{86DC}'
. '\x{86DD}\x{86DE}\x{86DF}\x{86E1}\x{86E2}\x{86E3}\x{86E4}\x{86E5}\x{86E6}'
. '\x{86E8}\x{86E9}\x{86EA}\x{86EB}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F0}'
. '\x{86F1}\x{86F2}\x{86F3}\x{86F4}\x{86F5}\x{86F6}\x{86F7}\x{86F8}\x{86F9}'
. '\x{86FA}\x{86FB}\x{86FC}\x{86FE}\x{86FF}\x{8700}\x{8701}\x{8702}\x{8703}'
. '\x{8704}\x{8705}\x{8706}\x{8707}\x{8708}\x{8709}\x{870A}\x{870B}\x{870C}'
. '\x{870D}\x{870E}\x{870F}\x{8710}\x{8711}\x{8712}\x{8713}\x{8714}\x{8715}'
. '\x{8716}\x{8717}\x{8718}\x{8719}\x{871A}\x{871B}\x{871C}\x{871E}\x{871F}'
. '\x{8720}\x{8721}\x{8722}\x{8723}\x{8724}\x{8725}\x{8726}\x{8727}\x{8728}'
. '\x{8729}\x{872A}\x{872B}\x{872C}\x{872D}\x{872E}\x{8730}\x{8731}\x{8732}'
. '\x{8733}\x{8734}\x{8735}\x{8736}\x{8737}\x{8738}\x{8739}\x{873A}\x{873B}'
. '\x{873C}\x{873E}\x{873F}\x{8740}\x{8741}\x{8742}\x{8743}\x{8744}\x{8746}'
. '\x{8747}\x{8748}\x{8749}\x{874A}\x{874C}\x{874D}\x{874E}\x{874F}\x{8750}'
. '\x{8751}\x{8752}\x{8753}\x{8754}\x{8755}\x{8756}\x{8757}\x{8758}\x{8759}'
. '\x{875A}\x{875B}\x{875C}\x{875D}\x{875E}\x{875F}\x{8760}\x{8761}\x{8762}'
. '\x{8763}\x{8764}\x{8765}\x{8766}\x{8767}\x{8768}\x{8769}\x{876A}\x{876B}'
. '\x{876C}\x{876D}\x{876E}\x{876F}\x{8770}\x{8772}\x{8773}\x{8774}\x{8775}'
. '\x{8776}\x{8777}\x{8778}\x{8779}\x{877A}\x{877B}\x{877C}\x{877D}\x{877E}'
. '\x{8780}\x{8781}\x{8782}\x{8783}\x{8784}\x{8785}\x{8786}\x{8787}\x{8788}'
. '\x{8789}\x{878A}\x{878B}\x{878C}\x{878D}\x{878F}\x{8790}\x{8791}\x{8792}'
. '\x{8793}\x{8794}\x{8795}\x{8796}\x{8797}\x{8798}\x{879A}\x{879B}\x{879C}'
. '\x{879D}\x{879E}\x{879F}\x{87A0}\x{87A1}\x{87A2}\x{87A3}\x{87A4}\x{87A5}'
. '\x{87A6}\x{87A7}\x{87A8}\x{87A9}\x{87AA}\x{87AB}\x{87AC}\x{87AD}\x{87AE}'
. '\x{87AF}\x{87B0}\x{87B1}\x{87B2}\x{87B3}\x{87B4}\x{87B5}\x{87B6}\x{87B7}'
. '\x{87B8}\x{87B9}\x{87BA}\x{87BB}\x{87BC}\x{87BD}\x{87BE}\x{87BF}\x{87C0}'
. '\x{87C1}\x{87C2}\x{87C3}\x{87C4}\x{87C5}\x{87C6}\x{87C7}\x{87C8}\x{87C9}'
. '\x{87CA}\x{87CB}\x{87CC}\x{87CD}\x{87CE}\x{87CF}\x{87D0}\x{87D1}\x{87D2}'
. '\x{87D3}\x{87D4}\x{87D5}\x{87D6}\x{87D7}\x{87D8}\x{87D9}\x{87DB}\x{87DC}'
. '\x{87DD}\x{87DE}\x{87DF}\x{87E0}\x{87E1}\x{87E2}\x{87E3}\x{87E4}\x{87E5}'
. '\x{87E6}\x{87E7}\x{87E8}\x{87E9}\x{87EA}\x{87EB}\x{87EC}\x{87ED}\x{87EE}'
. '\x{87EF}\x{87F1}\x{87F2}\x{87F3}\x{87F4}\x{87F5}\x{87F6}\x{87F7}\x{87F8}'
. '\x{87F9}\x{87FA}\x{87FB}\x{87FC}\x{87FD}\x{87FE}\x{87FF}\x{8800}\x{8801}'
. '\x{8802}\x{8803}\x{8804}\x{8805}\x{8806}\x{8808}\x{8809}\x{880A}\x{880B}'
. '\x{880C}\x{880D}\x{880E}\x{880F}\x{8810}\x{8811}\x{8813}\x{8814}\x{8815}'
. '\x{8816}\x{8817}\x{8818}\x{8819}\x{881A}\x{881B}\x{881C}\x{881D}\x{881E}'
. '\x{881F}\x{8820}\x{8821}\x{8822}\x{8823}\x{8824}\x{8825}\x{8826}\x{8827}'
. '\x{8828}\x{8829}\x{882A}\x{882B}\x{882C}\x{882E}\x{882F}\x{8830}\x{8831}'
. '\x{8832}\x{8833}\x{8834}\x{8835}\x{8836}\x{8837}\x{8838}\x{8839}\x{883B}'
. '\x{883C}\x{883D}\x{883E}\x{883F}\x{8840}\x{8841}\x{8842}\x{8843}\x{8844}'
. '\x{8845}\x{8846}\x{8848}\x{8849}\x{884A}\x{884B}\x{884C}\x{884D}\x{884E}'
. '\x{884F}\x{8850}\x{8851}\x{8852}\x{8853}\x{8854}\x{8855}\x{8856}\x{8857}'
. '\x{8859}\x{885A}\x{885B}\x{885D}\x{885E}\x{8860}\x{8861}\x{8862}\x{8863}'
. '\x{8864}\x{8865}\x{8866}\x{8867}\x{8868}\x{8869}\x{886A}\x{886B}\x{886C}'
. '\x{886D}\x{886E}\x{886F}\x{8870}\x{8871}\x{8872}\x{8873}\x{8874}\x{8875}'
. '\x{8876}\x{8877}\x{8878}\x{8879}\x{887B}\x{887C}\x{887D}\x{887E}\x{887F}'
. '\x{8880}\x{8881}\x{8882}\x{8883}\x{8884}\x{8885}\x{8886}\x{8887}\x{8888}'
. '\x{8889}\x{888A}\x{888B}\x{888C}\x{888D}\x{888E}\x{888F}\x{8890}\x{8891}'
. '\x{8892}\x{8893}\x{8894}\x{8895}\x{8896}\x{8897}\x{8898}\x{8899}\x{889A}'
. '\x{889B}\x{889C}\x{889D}\x{889E}\x{889F}\x{88A0}\x{88A1}\x{88A2}\x{88A3}'
. '\x{88A4}\x{88A5}\x{88A6}\x{88A7}\x{88A8}\x{88A9}\x{88AA}\x{88AB}\x{88AC}'
. '\x{88AD}\x{88AE}\x{88AF}\x{88B0}\x{88B1}\x{88B2}\x{88B3}\x{88B4}\x{88B6}'
. '\x{88B7}\x{88B8}\x{88B9}\x{88BA}\x{88BB}\x{88BC}\x{88BD}\x{88BE}\x{88BF}'
. '\x{88C0}\x{88C1}\x{88C2}\x{88C3}\x{88C4}\x{88C5}\x{88C6}\x{88C7}\x{88C8}'
. '\x{88C9}\x{88CA}\x{88CB}\x{88CC}\x{88CD}\x{88CE}\x{88CF}\x{88D0}\x{88D1}'
. '\x{88D2}\x{88D3}\x{88D4}\x{88D5}\x{88D6}\x{88D7}\x{88D8}\x{88D9}\x{88DA}'
. '\x{88DB}\x{88DC}\x{88DD}\x{88DE}\x{88DF}\x{88E0}\x{88E1}\x{88E2}\x{88E3}'
. '\x{88E4}\x{88E5}\x{88E7}\x{88E8}\x{88EA}\x{88EB}\x{88EC}\x{88EE}\x{88EF}'
. '\x{88F0}\x{88F1}\x{88F2}\x{88F3}\x{88F4}\x{88F5}\x{88F6}\x{88F7}\x{88F8}'
. '\x{88F9}\x{88FA}\x{88FB}\x{88FC}\x{88FD}\x{88FE}\x{88FF}\x{8900}\x{8901}'
. '\x{8902}\x{8904}\x{8905}\x{8906}\x{8907}\x{8908}\x{8909}\x{890A}\x{890B}'
. '\x{890C}\x{890D}\x{890E}\x{8910}\x{8911}\x{8912}\x{8913}\x{8914}\x{8915}'
. '\x{8916}\x{8917}\x{8918}\x{8919}\x{891A}\x{891B}\x{891C}\x{891D}\x{891E}'
. '\x{891F}\x{8920}\x{8921}\x{8922}\x{8923}\x{8925}\x{8926}\x{8927}\x{8928}'
. '\x{8929}\x{892A}\x{892B}\x{892C}\x{892D}\x{892E}\x{892F}\x{8930}\x{8931}'
. '\x{8932}\x{8933}\x{8934}\x{8935}\x{8936}\x{8937}\x{8938}\x{8939}\x{893A}'
. '\x{893B}\x{893C}\x{893D}\x{893E}\x{893F}\x{8940}\x{8941}\x{8942}\x{8943}'
. '\x{8944}\x{8945}\x{8946}\x{8947}\x{8948}\x{8949}\x{894A}\x{894B}\x{894C}'
. '\x{894E}\x{894F}\x{8950}\x{8951}\x{8952}\x{8953}\x{8954}\x{8955}\x{8956}'
. '\x{8957}\x{8958}\x{8959}\x{895A}\x{895B}\x{895C}\x{895D}\x{895E}\x{895F}'
. '\x{8960}\x{8961}\x{8962}\x{8963}\x{8964}\x{8966}\x{8967}\x{8968}\x{8969}'
. '\x{896A}\x{896B}\x{896C}\x{896D}\x{896E}\x{896F}\x{8970}\x{8971}\x{8972}'
. '\x{8973}\x{8974}\x{8976}\x{8977}\x{8978}\x{8979}\x{897A}\x{897B}\x{897C}'
. '\x{897E}\x{897F}\x{8980}\x{8981}\x{8982}\x{8983}\x{8984}\x{8985}\x{8986}'
. '\x{8987}\x{8988}\x{8989}\x{898A}\x{898B}\x{898C}\x{898E}\x{898F}\x{8991}'
. '\x{8992}\x{8993}\x{8995}\x{8996}\x{8997}\x{8998}\x{899A}\x{899B}\x{899C}'
. '\x{899D}\x{899E}\x{899F}\x{89A0}\x{89A1}\x{89A2}\x{89A3}\x{89A4}\x{89A5}'
. '\x{89A6}\x{89A7}\x{89A8}\x{89AA}\x{89AB}\x{89AC}\x{89AD}\x{89AE}\x{89AF}'
. '\x{89B1}\x{89B2}\x{89B3}\x{89B5}\x{89B6}\x{89B7}\x{89B8}\x{89B9}\x{89BA}'
. '\x{89BD}\x{89BE}\x{89BF}\x{89C0}\x{89C1}\x{89C2}\x{89C3}\x{89C4}\x{89C5}'
. '\x{89C6}\x{89C7}\x{89C8}\x{89C9}\x{89CA}\x{89CB}\x{89CC}\x{89CD}\x{89CE}'
. '\x{89CF}\x{89D0}\x{89D1}\x{89D2}\x{89D3}\x{89D4}\x{89D5}\x{89D6}\x{89D7}'
. '\x{89D8}\x{89D9}\x{89DA}\x{89DB}\x{89DC}\x{89DD}\x{89DE}\x{89DF}\x{89E0}'
. '\x{89E1}\x{89E2}\x{89E3}\x{89E4}\x{89E5}\x{89E6}\x{89E7}\x{89E8}\x{89E9}'
. '\x{89EA}\x{89EB}\x{89EC}\x{89ED}\x{89EF}\x{89F0}\x{89F1}\x{89F2}\x{89F3}'
. '\x{89F4}\x{89F6}\x{89F7}\x{89F8}\x{89FA}\x{89FB}\x{89FC}\x{89FE}\x{89FF}'
. '\x{8A00}\x{8A01}\x{8A02}\x{8A03}\x{8A04}\x{8A07}\x{8A08}\x{8A09}\x{8A0A}'
. '\x{8A0B}\x{8A0C}\x{8A0D}\x{8A0E}\x{8A0F}\x{8A10}\x{8A11}\x{8A12}\x{8A13}'
. '\x{8A15}\x{8A16}\x{8A17}\x{8A18}\x{8A1A}\x{8A1B}\x{8A1C}\x{8A1D}\x{8A1E}'
. '\x{8A1F}\x{8A22}\x{8A23}\x{8A24}\x{8A25}\x{8A26}\x{8A27}\x{8A28}\x{8A29}'
. '\x{8A2A}\x{8A2C}\x{8A2D}\x{8A2E}\x{8A2F}\x{8A30}\x{8A31}\x{8A32}\x{8A34}'
. '\x{8A35}\x{8A36}\x{8A37}\x{8A38}\x{8A39}\x{8A3A}\x{8A3B}\x{8A3C}\x{8A3E}'
. '\x{8A3F}\x{8A40}\x{8A41}\x{8A42}\x{8A43}\x{8A44}\x{8A45}\x{8A46}\x{8A47}'
. '\x{8A48}\x{8A49}\x{8A4A}\x{8A4C}\x{8A4D}\x{8A4E}\x{8A4F}\x{8A50}\x{8A51}'
. '\x{8A52}\x{8A53}\x{8A54}\x{8A55}\x{8A56}\x{8A57}\x{8A58}\x{8A59}\x{8A5A}'
. '\x{8A5B}\x{8A5C}\x{8A5D}\x{8A5E}\x{8A5F}\x{8A60}\x{8A61}\x{8A62}\x{8A63}'
. '\x{8A65}\x{8A66}\x{8A67}\x{8A68}\x{8A69}\x{8A6A}\x{8A6B}\x{8A6C}\x{8A6D}'
. '\x{8A6E}\x{8A6F}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A74}\x{8A75}\x{8A76}'
. '\x{8A77}\x{8A79}\x{8A7A}\x{8A7B}\x{8A7C}\x{8A7E}\x{8A7F}\x{8A80}\x{8A81}'
. '\x{8A82}\x{8A83}\x{8A84}\x{8A85}\x{8A86}\x{8A87}\x{8A89}\x{8A8A}\x{8A8B}'
. '\x{8A8C}\x{8A8D}\x{8A8E}\x{8A8F}\x{8A90}\x{8A91}\x{8A92}\x{8A93}\x{8A94}'
. '\x{8A95}\x{8A96}\x{8A97}\x{8A98}\x{8A99}\x{8A9A}\x{8A9B}\x{8A9C}\x{8A9D}'
. '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA2}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA7}'
. '\x{8AA8}\x{8AA9}\x{8AAA}\x{8AAB}\x{8AAC}\x{8AAE}\x{8AB0}\x{8AB1}\x{8AB2}'
. '\x{8AB3}\x{8AB4}\x{8AB5}\x{8AB6}\x{8AB8}\x{8AB9}\x{8ABA}\x{8ABB}\x{8ABC}'
. '\x{8ABD}\x{8ABE}\x{8ABF}\x{8AC0}\x{8AC1}\x{8AC2}\x{8AC3}\x{8AC4}\x{8AC5}'
. '\x{8AC6}\x{8AC7}\x{8AC8}\x{8AC9}\x{8ACA}\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACE}'
. '\x{8ACF}\x{8AD1}\x{8AD2}\x{8AD3}\x{8AD4}\x{8AD5}\x{8AD6}\x{8AD7}\x{8AD8}'
. '\x{8AD9}\x{8ADA}\x{8ADB}\x{8ADC}\x{8ADD}\x{8ADE}\x{8ADF}\x{8AE0}\x{8AE1}'
. '\x{8AE2}\x{8AE3}\x{8AE4}\x{8AE5}\x{8AE6}\x{8AE7}\x{8AE8}\x{8AE9}\x{8AEA}'
. '\x{8AEB}\x{8AED}\x{8AEE}\x{8AEF}\x{8AF0}\x{8AF1}\x{8AF2}\x{8AF3}\x{8AF4}'
. '\x{8AF5}\x{8AF6}\x{8AF7}\x{8AF8}\x{8AF9}\x{8AFA}\x{8AFB}\x{8AFC}\x{8AFD}'
. '\x{8AFE}\x{8AFF}\x{8B00}\x{8B01}\x{8B02}\x{8B03}\x{8B04}\x{8B05}\x{8B06}'
. '\x{8B07}\x{8B08}\x{8B09}\x{8B0A}\x{8B0B}\x{8B0D}\x{8B0E}\x{8B0F}\x{8B10}'
. '\x{8B11}\x{8B12}\x{8B13}\x{8B14}\x{8B15}\x{8B16}\x{8B17}\x{8B18}\x{8B19}'
. '\x{8B1A}\x{8B1B}\x{8B1C}\x{8B1D}\x{8B1E}\x{8B1F}\x{8B20}\x{8B21}\x{8B22}'
. '\x{8B23}\x{8B24}\x{8B25}\x{8B26}\x{8B27}\x{8B28}\x{8B2A}\x{8B2B}\x{8B2C}'
. '\x{8B2D}\x{8B2E}\x{8B2F}\x{8B30}\x{8B31}\x{8B33}\x{8B34}\x{8B35}\x{8B36}'
. '\x{8B37}\x{8B39}\x{8B3A}\x{8B3B}\x{8B3C}\x{8B3D}\x{8B3E}\x{8B40}\x{8B41}'
. '\x{8B42}\x{8B43}\x{8B44}\x{8B45}\x{8B46}\x{8B47}\x{8B48}\x{8B49}\x{8B4A}'
. '\x{8B4B}\x{8B4C}\x{8B4D}\x{8B4E}\x{8B4F}\x{8B50}\x{8B51}\x{8B52}\x{8B53}'
. '\x{8B54}\x{8B55}\x{8B56}\x{8B57}\x{8B58}\x{8B59}\x{8B5A}\x{8B5B}\x{8B5C}'
. '\x{8B5D}\x{8B5E}\x{8B5F}\x{8B60}\x{8B63}\x{8B64}\x{8B65}\x{8B66}\x{8B67}'
. '\x{8B68}\x{8B6A}\x{8B6B}\x{8B6C}\x{8B6D}\x{8B6E}\x{8B6F}\x{8B70}\x{8B71}'
. '\x{8B73}\x{8B74}\x{8B76}\x{8B77}\x{8B78}\x{8B79}\x{8B7A}\x{8B7B}\x{8B7D}'
. '\x{8B7E}\x{8B7F}\x{8B80}\x{8B82}\x{8B83}\x{8B84}\x{8B85}\x{8B86}\x{8B88}'
. '\x{8B89}\x{8B8A}\x{8B8B}\x{8B8C}\x{8B8E}\x{8B90}\x{8B91}\x{8B92}\x{8B93}'
. '\x{8B94}\x{8B95}\x{8B96}\x{8B97}\x{8B98}\x{8B99}\x{8B9A}\x{8B9C}\x{8B9D}'
. '\x{8B9E}\x{8B9F}\x{8BA0}\x{8BA1}\x{8BA2}\x{8BA3}\x{8BA4}\x{8BA5}\x{8BA6}'
. '\x{8BA7}\x{8BA8}\x{8BA9}\x{8BAA}\x{8BAB}\x{8BAC}\x{8BAD}\x{8BAE}\x{8BAF}'
. '\x{8BB0}\x{8BB1}\x{8BB2}\x{8BB3}\x{8BB4}\x{8BB5}\x{8BB6}\x{8BB7}\x{8BB8}'
. '\x{8BB9}\x{8BBA}\x{8BBB}\x{8BBC}\x{8BBD}\x{8BBE}\x{8BBF}\x{8BC0}\x{8BC1}'
. '\x{8BC2}\x{8BC3}\x{8BC4}\x{8BC5}\x{8BC6}\x{8BC7}\x{8BC8}\x{8BC9}\x{8BCA}'
. '\x{8BCB}\x{8BCC}\x{8BCD}\x{8BCE}\x{8BCF}\x{8BD0}\x{8BD1}\x{8BD2}\x{8BD3}'
. '\x{8BD4}\x{8BD5}\x{8BD6}\x{8BD7}\x{8BD8}\x{8BD9}\x{8BDA}\x{8BDB}\x{8BDC}'
. '\x{8BDD}\x{8BDE}\x{8BDF}\x{8BE0}\x{8BE1}\x{8BE2}\x{8BE3}\x{8BE4}\x{8BE5}'
. '\x{8BE6}\x{8BE7}\x{8BE8}\x{8BE9}\x{8BEA}\x{8BEB}\x{8BEC}\x{8BED}\x{8BEE}'
. '\x{8BEF}\x{8BF0}\x{8BF1}\x{8BF2}\x{8BF3}\x{8BF4}\x{8BF5}\x{8BF6}\x{8BF7}'
. '\x{8BF8}\x{8BF9}\x{8BFA}\x{8BFB}\x{8BFC}\x{8BFD}\x{8BFE}\x{8BFF}\x{8C00}'
. '\x{8C01}\x{8C02}\x{8C03}\x{8C04}\x{8C05}\x{8C06}\x{8C07}\x{8C08}\x{8C09}'
. '\x{8C0A}\x{8C0B}\x{8C0C}\x{8C0D}\x{8C0E}\x{8C0F}\x{8C10}\x{8C11}\x{8C12}'
. '\x{8C13}\x{8C14}\x{8C15}\x{8C16}\x{8C17}\x{8C18}\x{8C19}\x{8C1A}\x{8C1B}'
. '\x{8C1C}\x{8C1D}\x{8C1E}\x{8C1F}\x{8C20}\x{8C21}\x{8C22}\x{8C23}\x{8C24}'
. '\x{8C25}\x{8C26}\x{8C27}\x{8C28}\x{8C29}\x{8C2A}\x{8C2B}\x{8C2C}\x{8C2D}'
. '\x{8C2E}\x{8C2F}\x{8C30}\x{8C31}\x{8C32}\x{8C33}\x{8C34}\x{8C35}\x{8C36}'
. '\x{8C37}\x{8C39}\x{8C3A}\x{8C3B}\x{8C3C}\x{8C3D}\x{8C3E}\x{8C3F}\x{8C41}'
. '\x{8C42}\x{8C43}\x{8C45}\x{8C46}\x{8C47}\x{8C48}\x{8C49}\x{8C4A}\x{8C4B}'
. '\x{8C4C}\x{8C4D}\x{8C4E}\x{8C4F}\x{8C50}\x{8C54}\x{8C55}\x{8C56}\x{8C57}'
. '\x{8C59}\x{8C5A}\x{8C5B}\x{8C5C}\x{8C5D}\x{8C5E}\x{8C5F}\x{8C60}\x{8C61}'
. '\x{8C62}\x{8C63}\x{8C64}\x{8C65}\x{8C66}\x{8C67}\x{8C68}\x{8C69}\x{8C6A}'
. '\x{8C6B}\x{8C6C}\x{8C6D}\x{8C6E}\x{8C6F}\x{8C70}\x{8C71}\x{8C72}\x{8C73}'
. '\x{8C75}\x{8C76}\x{8C77}\x{8C78}\x{8C79}\x{8C7A}\x{8C7B}\x{8C7D}\x{8C7E}'
. '\x{8C80}\x{8C81}\x{8C82}\x{8C84}\x{8C85}\x{8C86}\x{8C88}\x{8C89}\x{8C8A}'
. '\x{8C8C}\x{8C8D}\x{8C8F}\x{8C90}\x{8C91}\x{8C92}\x{8C93}\x{8C94}\x{8C95}'
. '\x{8C96}\x{8C97}\x{8C98}\x{8C99}\x{8C9A}\x{8C9C}\x{8C9D}\x{8C9E}\x{8C9F}'
. '\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA3}\x{8CA4}\x{8CA5}\x{8CA7}\x{8CA8}\x{8CA9}'
. '\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}\x{8CB1}\x{8CB2}'
. '\x{8CB3}\x{8CB4}\x{8CB5}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CB9}\x{8CBA}\x{8CBB}'
. '\x{8CBC}\x{8CBD}\x{8CBE}\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}'
. '\x{8CC5}\x{8CC6}\x{8CC7}\x{8CC8}\x{8CC9}\x{8CCA}\x{8CCC}\x{8CCE}\x{8CCF}'
. '\x{8CD0}\x{8CD1}\x{8CD2}\x{8CD3}\x{8CD4}\x{8CD5}\x{8CD7}\x{8CD9}\x{8CDA}'
. '\x{8CDB}\x{8CDC}\x{8CDD}\x{8CDE}\x{8CDF}\x{8CE0}\x{8CE1}\x{8CE2}\x{8CE3}'
. '\x{8CE4}\x{8CE5}\x{8CE6}\x{8CE7}\x{8CE8}\x{8CEA}\x{8CEB}\x{8CEC}\x{8CED}'
. '\x{8CEE}\x{8CEF}\x{8CF0}\x{8CF1}\x{8CF2}\x{8CF3}\x{8CF4}\x{8CF5}\x{8CF6}'
. '\x{8CF8}\x{8CF9}\x{8CFA}\x{8CFB}\x{8CFC}\x{8CFD}\x{8CFE}\x{8CFF}\x{8D00}'
. '\x{8D02}\x{8D03}\x{8D04}\x{8D05}\x{8D06}\x{8D07}\x{8D08}\x{8D09}\x{8D0A}'
. '\x{8D0B}\x{8D0C}\x{8D0D}\x{8D0E}\x{8D0F}\x{8D10}\x{8D13}\x{8D14}\x{8D15}'
. '\x{8D16}\x{8D17}\x{8D18}\x{8D19}\x{8D1A}\x{8D1B}\x{8D1C}\x{8D1D}\x{8D1E}'
. '\x{8D1F}\x{8D20}\x{8D21}\x{8D22}\x{8D23}\x{8D24}\x{8D25}\x{8D26}\x{8D27}'
. '\x{8D28}\x{8D29}\x{8D2A}\x{8D2B}\x{8D2C}\x{8D2D}\x{8D2E}\x{8D2F}\x{8D30}'
. '\x{8D31}\x{8D32}\x{8D33}\x{8D34}\x{8D35}\x{8D36}\x{8D37}\x{8D38}\x{8D39}'
. '\x{8D3A}\x{8D3B}\x{8D3C}\x{8D3D}\x{8D3E}\x{8D3F}\x{8D40}\x{8D41}\x{8D42}'
. '\x{8D43}\x{8D44}\x{8D45}\x{8D46}\x{8D47}\x{8D48}\x{8D49}\x{8D4A}\x{8D4B}'
. '\x{8D4C}\x{8D4D}\x{8D4E}\x{8D4F}\x{8D50}\x{8D51}\x{8D52}\x{8D53}\x{8D54}'
. '\x{8D55}\x{8D56}\x{8D57}\x{8D58}\x{8D59}\x{8D5A}\x{8D5B}\x{8D5C}\x{8D5D}'
. '\x{8D5E}\x{8D5F}\x{8D60}\x{8D61}\x{8D62}\x{8D63}\x{8D64}\x{8D65}\x{8D66}'
. '\x{8D67}\x{8D68}\x{8D69}\x{8D6A}\x{8D6B}\x{8D6C}\x{8D6D}\x{8D6E}\x{8D6F}'
. '\x{8D70}\x{8D71}\x{8D72}\x{8D73}\x{8D74}\x{8D75}\x{8D76}\x{8D77}\x{8D78}'
. '\x{8D79}\x{8D7A}\x{8D7B}\x{8D7D}\x{8D7E}\x{8D7F}\x{8D80}\x{8D81}\x{8D82}'
. '\x{8D83}\x{8D84}\x{8D85}\x{8D86}\x{8D87}\x{8D88}\x{8D89}\x{8D8A}\x{8D8B}'
. '\x{8D8C}\x{8D8D}\x{8D8E}\x{8D8F}\x{8D90}\x{8D91}\x{8D92}\x{8D93}\x{8D94}'
. '\x{8D95}\x{8D96}\x{8D97}\x{8D98}\x{8D99}\x{8D9A}\x{8D9B}\x{8D9C}\x{8D9D}'
. '\x{8D9E}\x{8D9F}\x{8DA0}\x{8DA1}\x{8DA2}\x{8DA3}\x{8DA4}\x{8DA5}\x{8DA7}'
. '\x{8DA8}\x{8DA9}\x{8DAA}\x{8DAB}\x{8DAC}\x{8DAD}\x{8DAE}\x{8DAF}\x{8DB0}'
. '\x{8DB1}\x{8DB2}\x{8DB3}\x{8DB4}\x{8DB5}\x{8DB6}\x{8DB7}\x{8DB8}\x{8DB9}'
. '\x{8DBA}\x{8DBB}\x{8DBC}\x{8DBD}\x{8DBE}\x{8DBF}\x{8DC1}\x{8DC2}\x{8DC3}'
. '\x{8DC4}\x{8DC5}\x{8DC6}\x{8DC7}\x{8DC8}\x{8DC9}\x{8DCA}\x{8DCB}\x{8DCC}'
. '\x{8DCD}\x{8DCE}\x{8DCF}\x{8DD0}\x{8DD1}\x{8DD2}\x{8DD3}\x{8DD4}\x{8DD5}'
. '\x{8DD6}\x{8DD7}\x{8DD8}\x{8DD9}\x{8DDA}\x{8DDB}\x{8DDC}\x{8DDD}\x{8DDE}'
. '\x{8DDF}\x{8DE0}\x{8DE1}\x{8DE2}\x{8DE3}\x{8DE4}\x{8DE6}\x{8DE7}\x{8DE8}'
. '\x{8DE9}\x{8DEA}\x{8DEB}\x{8DEC}\x{8DED}\x{8DEE}\x{8DEF}\x{8DF0}\x{8DF1}'
. '\x{8DF2}\x{8DF3}\x{8DF4}\x{8DF5}\x{8DF6}\x{8DF7}\x{8DF8}\x{8DF9}\x{8DFA}'
. '\x{8DFB}\x{8DFC}\x{8DFD}\x{8DFE}\x{8DFF}\x{8E00}\x{8E02}\x{8E03}\x{8E04}'
. '\x{8E05}\x{8E06}\x{8E07}\x{8E08}\x{8E09}\x{8E0A}\x{8E0C}\x{8E0D}\x{8E0E}'
. '\x{8E0F}\x{8E10}\x{8E11}\x{8E12}\x{8E13}\x{8E14}\x{8E15}\x{8E16}\x{8E17}'
. '\x{8E18}\x{8E19}\x{8E1A}\x{8E1B}\x{8E1C}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E20}'
. '\x{8E21}\x{8E22}\x{8E23}\x{8E24}\x{8E25}\x{8E26}\x{8E27}\x{8E28}\x{8E29}'
. '\x{8E2A}\x{8E2B}\x{8E2C}\x{8E2D}\x{8E2E}\x{8E2F}\x{8E30}\x{8E31}\x{8E33}'
. '\x{8E34}\x{8E35}\x{8E36}\x{8E37}\x{8E38}\x{8E39}\x{8E3A}\x{8E3B}\x{8E3C}'
. '\x{8E3D}\x{8E3E}\x{8E3F}\x{8E40}\x{8E41}\x{8E42}\x{8E43}\x{8E44}\x{8E45}'
. '\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4B}\x{8E4C}\x{8E4D}\x{8E4E}\x{8E50}'
. '\x{8E51}\x{8E52}\x{8E53}\x{8E54}\x{8E55}\x{8E56}\x{8E57}\x{8E58}\x{8E59}'
. '\x{8E5A}\x{8E5B}\x{8E5C}\x{8E5D}\x{8E5E}\x{8E5F}\x{8E60}\x{8E61}\x{8E62}'
. '\x{8E63}\x{8E64}\x{8E65}\x{8E66}\x{8E67}\x{8E68}\x{8E69}\x{8E6A}\x{8E6B}'
. '\x{8E6C}\x{8E6D}\x{8E6F}\x{8E70}\x{8E71}\x{8E72}\x{8E73}\x{8E74}\x{8E76}'
. '\x{8E78}\x{8E7A}\x{8E7B}\x{8E7C}\x{8E7D}\x{8E7E}\x{8E7F}\x{8E80}\x{8E81}'
. '\x{8E82}\x{8E83}\x{8E84}\x{8E85}\x{8E86}\x{8E87}\x{8E88}\x{8E89}\x{8E8A}'
. '\x{8E8B}\x{8E8C}\x{8E8D}\x{8E8E}\x{8E8F}\x{8E90}\x{8E91}\x{8E92}\x{8E93}'
. '\x{8E94}\x{8E95}\x{8E96}\x{8E97}\x{8E98}\x{8E9A}\x{8E9C}\x{8E9D}\x{8E9E}'
. '\x{8E9F}\x{8EA0}\x{8EA1}\x{8EA3}\x{8EA4}\x{8EA5}\x{8EA6}\x{8EA7}\x{8EA8}'
. '\x{8EA9}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAD}\x{8EAE}\x{8EAF}\x{8EB0}\x{8EB1}'
. '\x{8EB2}\x{8EB4}\x{8EB5}\x{8EB8}\x{8EB9}\x{8EBA}\x{8EBB}\x{8EBC}\x{8EBD}'
. '\x{8EBE}\x{8EBF}\x{8EC0}\x{8EC2}\x{8EC3}\x{8EC5}\x{8EC6}\x{8EC7}\x{8EC8}'
. '\x{8EC9}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ECE}\x{8ECF}\x{8ED0}\x{8ED1}'
. '\x{8ED2}\x{8ED3}\x{8ED4}\x{8ED5}\x{8ED6}\x{8ED7}\x{8ED8}\x{8EDA}\x{8EDB}'
. '\x{8EDC}\x{8EDD}\x{8EDE}\x{8EDF}\x{8EE0}\x{8EE1}\x{8EE4}\x{8EE5}\x{8EE6}'
. '\x{8EE7}\x{8EE8}\x{8EE9}\x{8EEA}\x{8EEB}\x{8EEC}\x{8EED}\x{8EEE}\x{8EEF}'
. '\x{8EF1}\x{8EF2}\x{8EF3}\x{8EF4}\x{8EF5}\x{8EF6}\x{8EF7}\x{8EF8}\x{8EF9}'
. '\x{8EFA}\x{8EFB}\x{8EFC}\x{8EFD}\x{8EFE}\x{8EFF}\x{8F00}\x{8F01}\x{8F02}'
. '\x{8F03}\x{8F04}\x{8F05}\x{8F06}\x{8F07}\x{8F08}\x{8F09}\x{8F0A}\x{8F0B}'
. '\x{8F0D}\x{8F0E}\x{8F10}\x{8F11}\x{8F12}\x{8F13}\x{8F14}\x{8F15}\x{8F16}'
. '\x{8F17}\x{8F18}\x{8F1A}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1E}\x{8F1F}\x{8F20}'
. '\x{8F21}\x{8F22}\x{8F23}\x{8F24}\x{8F25}\x{8F26}\x{8F27}\x{8F28}\x{8F29}'
. '\x{8F2A}\x{8F2B}\x{8F2C}\x{8F2E}\x{8F2F}\x{8F30}\x{8F31}\x{8F32}\x{8F33}'
. '\x{8F34}\x{8F35}\x{8F36}\x{8F37}\x{8F38}\x{8F39}\x{8F3B}\x{8F3C}\x{8F3D}'
. '\x{8F3E}\x{8F3F}\x{8F40}\x{8F42}\x{8F43}\x{8F44}\x{8F45}\x{8F46}\x{8F47}'
. '\x{8F48}\x{8F49}\x{8F4A}\x{8F4B}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F4F}\x{8F50}'
. '\x{8F51}\x{8F52}\x{8F53}\x{8F54}\x{8F55}\x{8F56}\x{8F57}\x{8F58}\x{8F59}'
. '\x{8F5A}\x{8F5B}\x{8F5D}\x{8F5E}\x{8F5F}\x{8F60}\x{8F61}\x{8F62}\x{8F63}'
. '\x{8F64}\x{8F65}\x{8F66}\x{8F67}\x{8F68}\x{8F69}\x{8F6A}\x{8F6B}\x{8F6C}'
. '\x{8F6D}\x{8F6E}\x{8F6F}\x{8F70}\x{8F71}\x{8F72}\x{8F73}\x{8F74}\x{8F75}'
. '\x{8F76}\x{8F77}\x{8F78}\x{8F79}\x{8F7A}\x{8F7B}\x{8F7C}\x{8F7D}\x{8F7E}'
. '\x{8F7F}\x{8F80}\x{8F81}\x{8F82}\x{8F83}\x{8F84}\x{8F85}\x{8F86}\x{8F87}'
. '\x{8F88}\x{8F89}\x{8F8A}\x{8F8B}\x{8F8C}\x{8F8D}\x{8F8E}\x{8F8F}\x{8F90}'
. '\x{8F91}\x{8F92}\x{8F93}\x{8F94}\x{8F95}\x{8F96}\x{8F97}\x{8F98}\x{8F99}'
. '\x{8F9A}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA0}\x{8FA1}\x{8FA2}\x{8FA3}'
. '\x{8FA5}\x{8FA6}\x{8FA7}\x{8FA8}\x{8FA9}\x{8FAA}\x{8FAB}\x{8FAC}\x{8FAD}'
. '\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB4}\x{8FB5}\x{8FB6}\x{8FB7}'
. '\x{8FB8}\x{8FB9}\x{8FBB}\x{8FBC}\x{8FBD}\x{8FBE}\x{8FBF}\x{8FC0}\x{8FC1}'
. '\x{8FC2}\x{8FC4}\x{8FC5}\x{8FC6}\x{8FC7}\x{8FC8}\x{8FC9}\x{8FCB}\x{8FCC}'
. '\x{8FCD}\x{8FCE}\x{8FCF}\x{8FD0}\x{8FD1}\x{8FD2}\x{8FD3}\x{8FD4}\x{8FD5}'
. '\x{8FD6}\x{8FD7}\x{8FD8}\x{8FD9}\x{8FDA}\x{8FDB}\x{8FDC}\x{8FDD}\x{8FDE}'
. '\x{8FDF}\x{8FE0}\x{8FE1}\x{8FE2}\x{8FE3}\x{8FE4}\x{8FE5}\x{8FE6}\x{8FE8}'
. '\x{8FE9}\x{8FEA}\x{8FEB}\x{8FEC}\x{8FED}\x{8FEE}\x{8FEF}\x{8FF0}\x{8FF1}'
. '\x{8FF2}\x{8FF3}\x{8FF4}\x{8FF5}\x{8FF6}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}'
. '\x{8FFB}\x{8FFC}\x{8FFD}\x{8FFE}\x{8FFF}\x{9000}\x{9001}\x{9002}\x{9003}'
. '\x{9004}\x{9005}\x{9006}\x{9007}\x{9008}\x{9009}\x{900A}\x{900B}\x{900C}'
. '\x{900D}\x{900F}\x{9010}\x{9011}\x{9012}\x{9013}\x{9014}\x{9015}\x{9016}'
. '\x{9017}\x{9018}\x{9019}\x{901A}\x{901B}\x{901C}\x{901D}\x{901E}\x{901F}'
. '\x{9020}\x{9021}\x{9022}\x{9023}\x{9024}\x{9025}\x{9026}\x{9027}\x{9028}'
. '\x{9029}\x{902B}\x{902D}\x{902E}\x{902F}\x{9030}\x{9031}\x{9032}\x{9033}'
. '\x{9034}\x{9035}\x{9036}\x{9038}\x{903A}\x{903B}\x{903C}\x{903D}\x{903E}'
. '\x{903F}\x{9041}\x{9042}\x{9043}\x{9044}\x{9045}\x{9047}\x{9048}\x{9049}'
. '\x{904A}\x{904B}\x{904C}\x{904D}\x{904E}\x{904F}\x{9050}\x{9051}\x{9052}'
. '\x{9053}\x{9054}\x{9055}\x{9056}\x{9057}\x{9058}\x{9059}\x{905A}\x{905B}'
. '\x{905C}\x{905D}\x{905E}\x{905F}\x{9060}\x{9061}\x{9062}\x{9063}\x{9064}'
. '\x{9065}\x{9066}\x{9067}\x{9068}\x{9069}\x{906A}\x{906B}\x{906C}\x{906D}'
. '\x{906E}\x{906F}\x{9070}\x{9071}\x{9072}\x{9073}\x{9074}\x{9075}\x{9076}'
. '\x{9077}\x{9078}\x{9079}\x{907A}\x{907B}\x{907C}\x{907D}\x{907E}\x{907F}'
. '\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9085}\x{9086}\x{9087}\x{9088}'
. '\x{9089}\x{908A}\x{908B}\x{908C}\x{908D}\x{908E}\x{908F}\x{9090}\x{9091}'
. '\x{9092}\x{9093}\x{9094}\x{9095}\x{9096}\x{9097}\x{9098}\x{9099}\x{909A}'
. '\x{909B}\x{909C}\x{909D}\x{909E}\x{909F}\x{90A0}\x{90A1}\x{90A2}\x{90A3}'
. '\x{90A4}\x{90A5}\x{90A6}\x{90A7}\x{90A8}\x{90A9}\x{90AA}\x{90AC}\x{90AD}'
. '\x{90AE}\x{90AF}\x{90B0}\x{90B1}\x{90B2}\x{90B3}\x{90B4}\x{90B5}\x{90B6}'
. '\x{90B7}\x{90B8}\x{90B9}\x{90BA}\x{90BB}\x{90BC}\x{90BD}\x{90BE}\x{90BF}'
. '\x{90C0}\x{90C1}\x{90C2}\x{90C3}\x{90C4}\x{90C5}\x{90C6}\x{90C7}\x{90C8}'
. '\x{90C9}\x{90CA}\x{90CB}\x{90CE}\x{90CF}\x{90D0}\x{90D1}\x{90D3}\x{90D4}'
. '\x{90D5}\x{90D6}\x{90D7}\x{90D8}\x{90D9}\x{90DA}\x{90DB}\x{90DC}\x{90DD}'
. '\x{90DE}\x{90DF}\x{90E0}\x{90E1}\x{90E2}\x{90E3}\x{90E4}\x{90E5}\x{90E6}'
. '\x{90E7}\x{90E8}\x{90E9}\x{90EA}\x{90EB}\x{90EC}\x{90ED}\x{90EE}\x{90EF}'
. '\x{90F0}\x{90F1}\x{90F2}\x{90F3}\x{90F4}\x{90F5}\x{90F7}\x{90F8}\x{90F9}'
. '\x{90FA}\x{90FB}\x{90FC}\x{90FD}\x{90FE}\x{90FF}\x{9100}\x{9101}\x{9102}'
. '\x{9103}\x{9104}\x{9105}\x{9106}\x{9107}\x{9108}\x{9109}\x{910B}\x{910C}'
. '\x{910D}\x{910E}\x{910F}\x{9110}\x{9111}\x{9112}\x{9113}\x{9114}\x{9115}'
. '\x{9116}\x{9117}\x{9118}\x{9119}\x{911A}\x{911B}\x{911C}\x{911D}\x{911E}'
. '\x{911F}\x{9120}\x{9121}\x{9122}\x{9123}\x{9124}\x{9125}\x{9126}\x{9127}'
. '\x{9128}\x{9129}\x{912A}\x{912B}\x{912C}\x{912D}\x{912E}\x{912F}\x{9130}'
. '\x{9131}\x{9132}\x{9133}\x{9134}\x{9135}\x{9136}\x{9137}\x{9138}\x{9139}'
. '\x{913A}\x{913B}\x{913E}\x{913F}\x{9140}\x{9141}\x{9142}\x{9143}\x{9144}'
. '\x{9145}\x{9146}\x{9147}\x{9148}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}'
. '\x{914E}\x{914F}\x{9150}\x{9151}\x{9152}\x{9153}\x{9154}\x{9155}\x{9156}'
. '\x{9157}\x{9158}\x{915A}\x{915B}\x{915C}\x{915D}\x{915E}\x{915F}\x{9160}'
. '\x{9161}\x{9162}\x{9163}\x{9164}\x{9165}\x{9166}\x{9167}\x{9168}\x{9169}'
. '\x{916A}\x{916B}\x{916C}\x{916D}\x{916E}\x{916F}\x{9170}\x{9171}\x{9172}'
. '\x{9173}\x{9174}\x{9175}\x{9176}\x{9177}\x{9178}\x{9179}\x{917A}\x{917C}'
. '\x{917D}\x{917E}\x{917F}\x{9180}\x{9181}\x{9182}\x{9183}\x{9184}\x{9185}'
. '\x{9186}\x{9187}\x{9188}\x{9189}\x{918A}\x{918B}\x{918C}\x{918D}\x{918E}'
. '\x{918F}\x{9190}\x{9191}\x{9192}\x{9193}\x{9194}\x{9196}\x{9199}\x{919A}'
. '\x{919B}\x{919C}\x{919D}\x{919E}\x{919F}\x{91A0}\x{91A1}\x{91A2}\x{91A3}'
. '\x{91A5}\x{91A6}\x{91A7}\x{91A8}\x{91AA}\x{91AB}\x{91AC}\x{91AD}\x{91AE}'
. '\x{91AF}\x{91B0}\x{91B1}\x{91B2}\x{91B3}\x{91B4}\x{91B5}\x{91B6}\x{91B7}'
. '\x{91B9}\x{91BA}\x{91BB}\x{91BC}\x{91BD}\x{91BE}\x{91C0}\x{91C1}\x{91C2}'
. '\x{91C3}\x{91C5}\x{91C6}\x{91C7}\x{91C9}\x{91CA}\x{91CB}\x{91CC}\x{91CD}'
. '\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D2}\x{91D3}\x{91D4}\x{91D5}\x{91D7}'
. '\x{91D8}\x{91D9}\x{91DA}\x{91DB}\x{91DC}\x{91DD}\x{91DE}\x{91DF}\x{91E2}'
. '\x{91E3}\x{91E4}\x{91E5}\x{91E6}\x{91E7}\x{91E8}\x{91E9}\x{91EA}\x{91EB}'
. '\x{91EC}\x{91ED}\x{91EE}\x{91F0}\x{91F1}\x{91F2}\x{91F3}\x{91F4}\x{91F5}'
. '\x{91F7}\x{91F8}\x{91F9}\x{91FA}\x{91FB}\x{91FD}\x{91FE}\x{91FF}\x{9200}'
. '\x{9201}\x{9202}\x{9203}\x{9204}\x{9205}\x{9206}\x{9207}\x{9208}\x{9209}'
. '\x{920A}\x{920B}\x{920C}\x{920D}\x{920E}\x{920F}\x{9210}\x{9211}\x{9212}'
. '\x{9214}\x{9215}\x{9216}\x{9217}\x{9218}\x{9219}\x{921A}\x{921B}\x{921C}'
. '\x{921D}\x{921E}\x{9220}\x{9221}\x{9223}\x{9224}\x{9225}\x{9226}\x{9227}'
. '\x{9228}\x{9229}\x{922A}\x{922B}\x{922D}\x{922E}\x{922F}\x{9230}\x{9231}'
. '\x{9232}\x{9233}\x{9234}\x{9235}\x{9236}\x{9237}\x{9238}\x{9239}\x{923A}'
. '\x{923B}\x{923C}\x{923D}\x{923E}\x{923F}\x{9240}\x{9241}\x{9242}\x{9245}'
. '\x{9246}\x{9247}\x{9248}\x{9249}\x{924A}\x{924B}\x{924C}\x{924D}\x{924E}'
. '\x{924F}\x{9250}\x{9251}\x{9252}\x{9253}\x{9254}\x{9255}\x{9256}\x{9257}'
. '\x{9258}\x{9259}\x{925A}\x{925B}\x{925C}\x{925D}\x{925E}\x{925F}\x{9260}'
. '\x{9261}\x{9262}\x{9263}\x{9264}\x{9265}\x{9266}\x{9267}\x{9268}\x{926B}'
. '\x{926C}\x{926D}\x{926E}\x{926F}\x{9270}\x{9272}\x{9273}\x{9274}\x{9275}'
. '\x{9276}\x{9277}\x{9278}\x{9279}\x{927A}\x{927B}\x{927C}\x{927D}\x{927E}'
. '\x{927F}\x{9280}\x{9282}\x{9283}\x{9285}\x{9286}\x{9287}\x{9288}\x{9289}'
. '\x{928A}\x{928B}\x{928C}\x{928D}\x{928E}\x{928F}\x{9290}\x{9291}\x{9292}'
. '\x{9293}\x{9294}\x{9295}\x{9296}\x{9297}\x{9298}\x{9299}\x{929A}\x{929B}'
. '\x{929C}\x{929D}\x{929F}\x{92A0}\x{92A1}\x{92A2}\x{92A3}\x{92A4}\x{92A5}'
. '\x{92A6}\x{92A7}\x{92A8}\x{92A9}\x{92AA}\x{92AB}\x{92AC}\x{92AD}\x{92AE}'
. '\x{92AF}\x{92B0}\x{92B1}\x{92B2}\x{92B3}\x{92B4}\x{92B5}\x{92B6}\x{92B7}'
. '\x{92B8}\x{92B9}\x{92BA}\x{92BB}\x{92BC}\x{92BE}\x{92BF}\x{92C0}\x{92C1}'
. '\x{92C2}\x{92C3}\x{92C4}\x{92C5}\x{92C6}\x{92C7}\x{92C8}\x{92C9}\x{92CA}'
. '\x{92CB}\x{92CC}\x{92CD}\x{92CE}\x{92CF}\x{92D0}\x{92D1}\x{92D2}\x{92D3}'
. '\x{92D5}\x{92D6}\x{92D7}\x{92D8}\x{92D9}\x{92DA}\x{92DC}\x{92DD}\x{92DE}'
. '\x{92DF}\x{92E0}\x{92E1}\x{92E3}\x{92E4}\x{92E5}\x{92E6}\x{92E7}\x{92E8}'
. '\x{92E9}\x{92EA}\x{92EB}\x{92EC}\x{92ED}\x{92EE}\x{92EF}\x{92F0}\x{92F1}'
. '\x{92F2}\x{92F3}\x{92F4}\x{92F5}\x{92F6}\x{92F7}\x{92F8}\x{92F9}\x{92FA}'
. '\x{92FB}\x{92FC}\x{92FD}\x{92FE}\x{92FF}\x{9300}\x{9301}\x{9302}\x{9303}'
. '\x{9304}\x{9305}\x{9306}\x{9307}\x{9308}\x{9309}\x{930A}\x{930B}\x{930C}'
. '\x{930D}\x{930E}\x{930F}\x{9310}\x{9311}\x{9312}\x{9313}\x{9314}\x{9315}'
. '\x{9316}\x{9317}\x{9318}\x{9319}\x{931A}\x{931B}\x{931D}\x{931E}\x{931F}'
. '\x{9320}\x{9321}\x{9322}\x{9323}\x{9324}\x{9325}\x{9326}\x{9327}\x{9328}'
. '\x{9329}\x{932A}\x{932B}\x{932D}\x{932E}\x{932F}\x{9332}\x{9333}\x{9334}'
. '\x{9335}\x{9336}\x{9337}\x{9338}\x{9339}\x{933A}\x{933B}\x{933C}\x{933D}'
. '\x{933E}\x{933F}\x{9340}\x{9341}\x{9342}\x{9343}\x{9344}\x{9345}\x{9346}'
. '\x{9347}\x{9348}\x{9349}\x{934A}\x{934B}\x{934C}\x{934D}\x{934E}\x{934F}'
. '\x{9350}\x{9351}\x{9352}\x{9353}\x{9354}\x{9355}\x{9356}\x{9357}\x{9358}'
. '\x{9359}\x{935A}\x{935B}\x{935C}\x{935D}\x{935E}\x{935F}\x{9360}\x{9361}'
. '\x{9363}\x{9364}\x{9365}\x{9366}\x{9367}\x{9369}\x{936A}\x{936C}\x{936D}'
. '\x{936E}\x{9370}\x{9371}\x{9372}\x{9374}\x{9375}\x{9376}\x{9377}\x{9379}'
. '\x{937A}\x{937B}\x{937C}\x{937D}\x{937E}\x{9380}\x{9382}\x{9383}\x{9384}'
. '\x{9385}\x{9386}\x{9387}\x{9388}\x{9389}\x{938A}\x{938C}\x{938D}\x{938E}'
. '\x{938F}\x{9390}\x{9391}\x{9392}\x{9393}\x{9394}\x{9395}\x{9396}\x{9397}'
. '\x{9398}\x{9399}\x{939A}\x{939B}\x{939D}\x{939E}\x{939F}\x{93A1}\x{93A2}'
. '\x{93A3}\x{93A4}\x{93A5}\x{93A6}\x{93A7}\x{93A8}\x{93A9}\x{93AA}\x{93AC}'
. '\x{93AD}\x{93AE}\x{93AF}\x{93B0}\x{93B1}\x{93B2}\x{93B3}\x{93B4}\x{93B5}'
. '\x{93B6}\x{93B7}\x{93B8}\x{93B9}\x{93BA}\x{93BC}\x{93BD}\x{93BE}\x{93BF}'
. '\x{93C0}\x{93C1}\x{93C2}\x{93C3}\x{93C4}\x{93C5}\x{93C6}\x{93C7}\x{93C8}'
. '\x{93C9}\x{93CA}\x{93CB}\x{93CC}\x{93CD}\x{93CE}\x{93CF}\x{93D0}\x{93D1}'
. '\x{93D2}\x{93D3}\x{93D4}\x{93D5}\x{93D6}\x{93D7}\x{93D8}\x{93D9}\x{93DA}'
. '\x{93DB}\x{93DC}\x{93DD}\x{93DE}\x{93DF}\x{93E1}\x{93E2}\x{93E3}\x{93E4}'
. '\x{93E6}\x{93E7}\x{93E8}\x{93E9}\x{93EA}\x{93EB}\x{93EC}\x{93ED}\x{93EE}'
. '\x{93EF}\x{93F0}\x{93F1}\x{93F2}\x{93F4}\x{93F5}\x{93F6}\x{93F7}\x{93F8}'
. '\x{93F9}\x{93FA}\x{93FB}\x{93FC}\x{93FD}\x{93FE}\x{93FF}\x{9400}\x{9401}'
. '\x{9403}\x{9404}\x{9405}\x{9406}\x{9407}\x{9408}\x{9409}\x{940A}\x{940B}'
. '\x{940C}\x{940D}\x{940E}\x{940F}\x{9410}\x{9411}\x{9412}\x{9413}\x{9414}'
. '\x{9415}\x{9416}\x{9418}\x{9419}\x{941B}\x{941D}\x{9420}\x{9422}\x{9423}'
. '\x{9425}\x{9426}\x{9427}\x{9428}\x{9429}\x{942A}\x{942B}\x{942C}\x{942D}'
. '\x{942E}\x{942F}\x{9430}\x{9431}\x{9432}\x{9433}\x{9434}\x{9435}\x{9436}'
. '\x{9437}\x{9438}\x{9439}\x{943A}\x{943B}\x{943C}\x{943D}\x{943E}\x{943F}'
. '\x{9440}\x{9441}\x{9442}\x{9444}\x{9445}\x{9446}\x{9447}\x{9448}\x{9449}'
. '\x{944A}\x{944B}\x{944C}\x{944D}\x{944F}\x{9450}\x{9451}\x{9452}\x{9453}'
. '\x{9454}\x{9455}\x{9456}\x{9457}\x{9458}\x{9459}\x{945B}\x{945C}\x{945D}'
. '\x{945E}\x{945F}\x{9460}\x{9461}\x{9462}\x{9463}\x{9464}\x{9465}\x{9466}'
. '\x{9467}\x{9468}\x{9469}\x{946A}\x{946B}\x{946D}\x{946E}\x{946F}\x{9470}'
. '\x{9471}\x{9472}\x{9473}\x{9474}\x{9475}\x{9476}\x{9477}\x{9478}\x{9479}'
. '\x{947A}\x{947C}\x{947D}\x{947E}\x{947F}\x{9480}\x{9481}\x{9482}\x{9483}'
. '\x{9484}\x{9485}\x{9486}\x{9487}\x{9488}\x{9489}\x{948A}\x{948B}\x{948C}'
. '\x{948D}\x{948E}\x{948F}\x{9490}\x{9491}\x{9492}\x{9493}\x{9494}\x{9495}'
. '\x{9496}\x{9497}\x{9498}\x{9499}\x{949A}\x{949B}\x{949C}\x{949D}\x{949E}'
. '\x{949F}\x{94A0}\x{94A1}\x{94A2}\x{94A3}\x{94A4}\x{94A5}\x{94A6}\x{94A7}'
. '\x{94A8}\x{94A9}\x{94AA}\x{94AB}\x{94AC}\x{94AD}\x{94AE}\x{94AF}\x{94B0}'
. '\x{94B1}\x{94B2}\x{94B3}\x{94B4}\x{94B5}\x{94B6}\x{94B7}\x{94B8}\x{94B9}'
. '\x{94BA}\x{94BB}\x{94BC}\x{94BD}\x{94BE}\x{94BF}\x{94C0}\x{94C1}\x{94C2}'
. '\x{94C3}\x{94C4}\x{94C5}\x{94C6}\x{94C7}\x{94C8}\x{94C9}\x{94CA}\x{94CB}'
. '\x{94CC}\x{94CD}\x{94CE}\x{94CF}\x{94D0}\x{94D1}\x{94D2}\x{94D3}\x{94D4}'
. '\x{94D5}\x{94D6}\x{94D7}\x{94D8}\x{94D9}\x{94DA}\x{94DB}\x{94DC}\x{94DD}'
. '\x{94DE}\x{94DF}\x{94E0}\x{94E1}\x{94E2}\x{94E3}\x{94E4}\x{94E5}\x{94E6}'
. '\x{94E7}\x{94E8}\x{94E9}\x{94EA}\x{94EB}\x{94EC}\x{94ED}\x{94EE}\x{94EF}'
. '\x{94F0}\x{94F1}\x{94F2}\x{94F3}\x{94F4}\x{94F5}\x{94F6}\x{94F7}\x{94F8}'
. '\x{94F9}\x{94FA}\x{94FB}\x{94FC}\x{94FD}\x{94FE}\x{94FF}\x{9500}\x{9501}'
. '\x{9502}\x{9503}\x{9504}\x{9505}\x{9506}\x{9507}\x{9508}\x{9509}\x{950A}'
. '\x{950B}\x{950C}\x{950D}\x{950E}\x{950F}\x{9510}\x{9511}\x{9512}\x{9513}'
. '\x{9514}\x{9515}\x{9516}\x{9517}\x{9518}\x{9519}\x{951A}\x{951B}\x{951C}'
. '\x{951D}\x{951E}\x{951F}\x{9520}\x{9521}\x{9522}\x{9523}\x{9524}\x{9525}'
. '\x{9526}\x{9527}\x{9528}\x{9529}\x{952A}\x{952B}\x{952C}\x{952D}\x{952E}'
. '\x{952F}\x{9530}\x{9531}\x{9532}\x{9533}\x{9534}\x{9535}\x{9536}\x{9537}'
. '\x{9538}\x{9539}\x{953A}\x{953B}\x{953C}\x{953D}\x{953E}\x{953F}\x{9540}'
. '\x{9541}\x{9542}\x{9543}\x{9544}\x{9545}\x{9546}\x{9547}\x{9548}\x{9549}'
. '\x{954A}\x{954B}\x{954C}\x{954D}\x{954E}\x{954F}\x{9550}\x{9551}\x{9552}'
. '\x{9553}\x{9554}\x{9555}\x{9556}\x{9557}\x{9558}\x{9559}\x{955A}\x{955B}'
. '\x{955C}\x{955D}\x{955E}\x{955F}\x{9560}\x{9561}\x{9562}\x{9563}\x{9564}'
. '\x{9565}\x{9566}\x{9567}\x{9568}\x{9569}\x{956A}\x{956B}\x{956C}\x{956D}'
. '\x{956E}\x{956F}\x{9570}\x{9571}\x{9572}\x{9573}\x{9574}\x{9575}\x{9576}'
. '\x{9577}\x{957A}\x{957B}\x{957C}\x{957D}\x{957F}\x{9580}\x{9581}\x{9582}'
. '\x{9583}\x{9584}\x{9586}\x{9587}\x{9588}\x{9589}\x{958A}\x{958B}\x{958C}'
. '\x{958D}\x{958E}\x{958F}\x{9590}\x{9591}\x{9592}\x{9593}\x{9594}\x{9595}'
. '\x{9596}\x{9598}\x{9599}\x{959A}\x{959B}\x{959C}\x{959D}\x{959E}\x{959F}'
. '\x{95A1}\x{95A2}\x{95A3}\x{95A4}\x{95A5}\x{95A6}\x{95A7}\x{95A8}\x{95A9}'
. '\x{95AA}\x{95AB}\x{95AC}\x{95AD}\x{95AE}\x{95AF}\x{95B0}\x{95B1}\x{95B2}'
. '\x{95B5}\x{95B6}\x{95B7}\x{95B9}\x{95BA}\x{95BB}\x{95BC}\x{95BD}\x{95BE}'
. '\x{95BF}\x{95C0}\x{95C2}\x{95C3}\x{95C4}\x{95C5}\x{95C6}\x{95C7}\x{95C8}'
. '\x{95C9}\x{95CA}\x{95CB}\x{95CC}\x{95CD}\x{95CE}\x{95CF}\x{95D0}\x{95D1}'
. '\x{95D2}\x{95D3}\x{95D4}\x{95D5}\x{95D6}\x{95D7}\x{95D8}\x{95DA}\x{95DB}'
. '\x{95DC}\x{95DE}\x{95DF}\x{95E0}\x{95E1}\x{95E2}\x{95E3}\x{95E4}\x{95E5}'
. '\x{95E6}\x{95E7}\x{95E8}\x{95E9}\x{95EA}\x{95EB}\x{95EC}\x{95ED}\x{95EE}'
. '\x{95EF}\x{95F0}\x{95F1}\x{95F2}\x{95F3}\x{95F4}\x{95F5}\x{95F6}\x{95F7}'
. '\x{95F8}\x{95F9}\x{95FA}\x{95FB}\x{95FC}\x{95FD}\x{95FE}\x{95FF}\x{9600}'
. '\x{9601}\x{9602}\x{9603}\x{9604}\x{9605}\x{9606}\x{9607}\x{9608}\x{9609}'
. '\x{960A}\x{960B}\x{960C}\x{960D}\x{960E}\x{960F}\x{9610}\x{9611}\x{9612}'
. '\x{9613}\x{9614}\x{9615}\x{9616}\x{9617}\x{9618}\x{9619}\x{961A}\x{961B}'
. '\x{961C}\x{961D}\x{961E}\x{961F}\x{9620}\x{9621}\x{9622}\x{9623}\x{9624}'
. '\x{9627}\x{9628}\x{962A}\x{962B}\x{962C}\x{962D}\x{962E}\x{962F}\x{9630}'
. '\x{9631}\x{9632}\x{9633}\x{9634}\x{9635}\x{9636}\x{9637}\x{9638}\x{9639}'
. '\x{963A}\x{963B}\x{963C}\x{963D}\x{963F}\x{9640}\x{9641}\x{9642}\x{9643}'
. '\x{9644}\x{9645}\x{9646}\x{9647}\x{9648}\x{9649}\x{964A}\x{964B}\x{964C}'
. '\x{964D}\x{964E}\x{964F}\x{9650}\x{9651}\x{9652}\x{9653}\x{9654}\x{9655}'
. '\x{9658}\x{9659}\x{965A}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9660}'
. '\x{9661}\x{9662}\x{9663}\x{9664}\x{9666}\x{9667}\x{9668}\x{9669}\x{966A}'
. '\x{966B}\x{966C}\x{966D}\x{966E}\x{966F}\x{9670}\x{9671}\x{9672}\x{9673}'
. '\x{9674}\x{9675}\x{9676}\x{9677}\x{9678}\x{967C}\x{967D}\x{967E}\x{9680}'
. '\x{9683}\x{9684}\x{9685}\x{9686}\x{9687}\x{9688}\x{9689}\x{968A}\x{968B}'
. '\x{968D}\x{968E}\x{968F}\x{9690}\x{9691}\x{9692}\x{9693}\x{9694}\x{9695}'
. '\x{9697}\x{9698}\x{9699}\x{969B}\x{969C}\x{969E}\x{96A0}\x{96A1}\x{96A2}'
. '\x{96A3}\x{96A4}\x{96A5}\x{96A6}\x{96A7}\x{96A8}\x{96A9}\x{96AA}\x{96AC}'
. '\x{96AD}\x{96AE}\x{96B0}\x{96B1}\x{96B3}\x{96B4}\x{96B6}\x{96B7}\x{96B8}'
. '\x{96B9}\x{96BA}\x{96BB}\x{96BC}\x{96BD}\x{96BE}\x{96BF}\x{96C0}\x{96C1}'
. '\x{96C2}\x{96C3}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C8}\x{96C9}\x{96CA}'
. '\x{96CB}\x{96CC}\x{96CD}\x{96CE}\x{96CF}\x{96D0}\x{96D1}\x{96D2}\x{96D3}'
. '\x{96D4}\x{96D5}\x{96D6}\x{96D7}\x{96D8}\x{96D9}\x{96DA}\x{96DB}\x{96DC}'
. '\x{96DD}\x{96DE}\x{96DF}\x{96E0}\x{96E1}\x{96E2}\x{96E3}\x{96E5}\x{96E8}'
. '\x{96E9}\x{96EA}\x{96EB}\x{96EC}\x{96ED}\x{96EE}\x{96EF}\x{96F0}\x{96F1}'
. '\x{96F2}\x{96F3}\x{96F4}\x{96F5}\x{96F6}\x{96F7}\x{96F8}\x{96F9}\x{96FA}'
. '\x{96FB}\x{96FD}\x{96FE}\x{96FF}\x{9700}\x{9701}\x{9702}\x{9703}\x{9704}'
. '\x{9705}\x{9706}\x{9707}\x{9708}\x{9709}\x{970A}\x{970B}\x{970C}\x{970D}'
. '\x{970E}\x{970F}\x{9710}\x{9711}\x{9712}\x{9713}\x{9715}\x{9716}\x{9718}'
. '\x{9719}\x{971C}\x{971D}\x{971E}\x{971F}\x{9720}\x{9721}\x{9722}\x{9723}'
. '\x{9724}\x{9725}\x{9726}\x{9727}\x{9728}\x{9729}\x{972A}\x{972B}\x{972C}'
. '\x{972D}\x{972E}\x{972F}\x{9730}\x{9731}\x{9732}\x{9735}\x{9736}\x{9738}'
. '\x{9739}\x{973A}\x{973B}\x{973C}\x{973D}\x{973E}\x{973F}\x{9742}\x{9743}'
. '\x{9744}\x{9745}\x{9746}\x{9747}\x{9748}\x{9749}\x{974A}\x{974B}\x{974C}'
. '\x{974E}\x{974F}\x{9750}\x{9751}\x{9752}\x{9753}\x{9754}\x{9755}\x{9756}'
. '\x{9758}\x{9759}\x{975A}\x{975B}\x{975C}\x{975D}\x{975E}\x{975F}\x{9760}'
. '\x{9761}\x{9762}\x{9765}\x{9766}\x{9767}\x{9768}\x{9769}\x{976A}\x{976B}'
. '\x{976C}\x{976D}\x{976E}\x{976F}\x{9770}\x{9772}\x{9773}\x{9774}\x{9776}'
. '\x{9777}\x{9778}\x{9779}\x{977A}\x{977B}\x{977C}\x{977D}\x{977E}\x{977F}'
. '\x{9780}\x{9781}\x{9782}\x{9783}\x{9784}\x{9785}\x{9786}\x{9788}\x{978A}'
. '\x{978B}\x{978C}\x{978D}\x{978E}\x{978F}\x{9790}\x{9791}\x{9792}\x{9793}'
. '\x{9794}\x{9795}\x{9796}\x{9797}\x{9798}\x{9799}\x{979A}\x{979C}\x{979D}'
. '\x{979E}\x{979F}\x{97A0}\x{97A1}\x{97A2}\x{97A3}\x{97A4}\x{97A5}\x{97A6}'
. '\x{97A7}\x{97A8}\x{97AA}\x{97AB}\x{97AC}\x{97AD}\x{97AE}\x{97AF}\x{97B2}'
. '\x{97B3}\x{97B4}\x{97B6}\x{97B7}\x{97B8}\x{97B9}\x{97BA}\x{97BB}\x{97BC}'
. '\x{97BD}\x{97BF}\x{97C1}\x{97C2}\x{97C3}\x{97C4}\x{97C5}\x{97C6}\x{97C7}'
. '\x{97C8}\x{97C9}\x{97CA}\x{97CB}\x{97CC}\x{97CD}\x{97CE}\x{97CF}\x{97D0}'
. '\x{97D1}\x{97D3}\x{97D4}\x{97D5}\x{97D6}\x{97D7}\x{97D8}\x{97D9}\x{97DA}'
. '\x{97DB}\x{97DC}\x{97DD}\x{97DE}\x{97DF}\x{97E0}\x{97E1}\x{97E2}\x{97E3}'
. '\x{97E4}\x{97E5}\x{97E6}\x{97E7}\x{97E8}\x{97E9}\x{97EA}\x{97EB}\x{97EC}'
. '\x{97ED}\x{97EE}\x{97EF}\x{97F0}\x{97F1}\x{97F2}\x{97F3}\x{97F4}\x{97F5}'
. '\x{97F6}\x{97F7}\x{97F8}\x{97F9}\x{97FA}\x{97FB}\x{97FD}\x{97FE}\x{97FF}'
. '\x{9800}\x{9801}\x{9802}\x{9803}\x{9804}\x{9805}\x{9806}\x{9807}\x{9808}'
. '\x{9809}\x{980A}\x{980B}\x{980C}\x{980D}\x{980E}\x{980F}\x{9810}\x{9811}'
. '\x{9812}\x{9813}\x{9814}\x{9815}\x{9816}\x{9817}\x{9818}\x{9819}\x{981A}'
. '\x{981B}\x{981C}\x{981D}\x{981E}\x{9820}\x{9821}\x{9822}\x{9823}\x{9824}'
. '\x{9826}\x{9827}\x{9828}\x{9829}\x{982B}\x{982D}\x{982E}\x{982F}\x{9830}'
. '\x{9831}\x{9832}\x{9834}\x{9835}\x{9836}\x{9837}\x{9838}\x{9839}\x{983B}'
. '\x{983C}\x{983D}\x{983F}\x{9840}\x{9841}\x{9843}\x{9844}\x{9845}\x{9846}'
. '\x{9848}\x{9849}\x{984A}\x{984C}\x{984D}\x{984E}\x{984F}\x{9850}\x{9851}'
. '\x{9852}\x{9853}\x{9854}\x{9855}\x{9857}\x{9858}\x{9859}\x{985A}\x{985B}'
. '\x{985C}\x{985D}\x{985E}\x{985F}\x{9860}\x{9861}\x{9862}\x{9863}\x{9864}'
. '\x{9865}\x{9867}\x{9869}\x{986A}\x{986B}\x{986C}\x{986D}\x{986E}\x{986F}'
. '\x{9870}\x{9871}\x{9872}\x{9873}\x{9874}\x{9875}\x{9876}\x{9877}\x{9878}'
. '\x{9879}\x{987A}\x{987B}\x{987C}\x{987D}\x{987E}\x{987F}\x{9880}\x{9881}'
. '\x{9882}\x{9883}\x{9884}\x{9885}\x{9886}\x{9887}\x{9888}\x{9889}\x{988A}'
. '\x{988B}\x{988C}\x{988D}\x{988E}\x{988F}\x{9890}\x{9891}\x{9892}\x{9893}'
. '\x{9894}\x{9895}\x{9896}\x{9897}\x{9898}\x{9899}\x{989A}\x{989B}\x{989C}'
. '\x{989D}\x{989E}\x{989F}\x{98A0}\x{98A1}\x{98A2}\x{98A3}\x{98A4}\x{98A5}'
. '\x{98A6}\x{98A7}\x{98A8}\x{98A9}\x{98AA}\x{98AB}\x{98AC}\x{98AD}\x{98AE}'
. '\x{98AF}\x{98B0}\x{98B1}\x{98B2}\x{98B3}\x{98B4}\x{98B5}\x{98B6}\x{98B8}'
. '\x{98B9}\x{98BA}\x{98BB}\x{98BC}\x{98BD}\x{98BE}\x{98BF}\x{98C0}\x{98C1}'
. '\x{98C2}\x{98C3}\x{98C4}\x{98C5}\x{98C6}\x{98C8}\x{98C9}\x{98CB}\x{98CC}'
. '\x{98CD}\x{98CE}\x{98CF}\x{98D0}\x{98D1}\x{98D2}\x{98D3}\x{98D4}\x{98D5}'
. '\x{98D6}\x{98D7}\x{98D8}\x{98D9}\x{98DA}\x{98DB}\x{98DC}\x{98DD}\x{98DE}'
. '\x{98DF}\x{98E0}\x{98E2}\x{98E3}\x{98E5}\x{98E6}\x{98E7}\x{98E8}\x{98E9}'
. '\x{98EA}\x{98EB}\x{98ED}\x{98EF}\x{98F0}\x{98F2}\x{98F3}\x{98F4}\x{98F5}'
. '\x{98F6}\x{98F7}\x{98F9}\x{98FA}\x{98FC}\x{98FD}\x{98FE}\x{98FF}\x{9900}'
. '\x{9901}\x{9902}\x{9903}\x{9904}\x{9905}\x{9906}\x{9907}\x{9908}\x{9909}'
. '\x{990A}\x{990B}\x{990C}\x{990D}\x{990E}\x{990F}\x{9910}\x{9911}\x{9912}'
. '\x{9913}\x{9914}\x{9915}\x{9916}\x{9917}\x{9918}\x{991A}\x{991B}\x{991C}'
. '\x{991D}\x{991E}\x{991F}\x{9920}\x{9921}\x{9922}\x{9923}\x{9924}\x{9925}'
. '\x{9926}\x{9927}\x{9928}\x{9929}\x{992A}\x{992B}\x{992C}\x{992D}\x{992E}'
. '\x{992F}\x{9930}\x{9931}\x{9932}\x{9933}\x{9934}\x{9935}\x{9936}\x{9937}'
. '\x{9938}\x{9939}\x{993A}\x{993C}\x{993D}\x{993E}\x{993F}\x{9940}\x{9941}'
. '\x{9942}\x{9943}\x{9945}\x{9946}\x{9947}\x{9948}\x{9949}\x{994A}\x{994B}'
. '\x{994C}\x{994E}\x{994F}\x{9950}\x{9951}\x{9952}\x{9953}\x{9954}\x{9955}'
. '\x{9956}\x{9957}\x{9958}\x{9959}\x{995B}\x{995C}\x{995E}\x{995F}\x{9960}'
. '\x{9961}\x{9962}\x{9963}\x{9964}\x{9965}\x{9966}\x{9967}\x{9968}\x{9969}'
. '\x{996A}\x{996B}\x{996C}\x{996D}\x{996E}\x{996F}\x{9970}\x{9971}\x{9972}'
. '\x{9973}\x{9974}\x{9975}\x{9976}\x{9977}\x{9978}\x{9979}\x{997A}\x{997B}'
. '\x{997C}\x{997D}\x{997E}\x{997F}\x{9980}\x{9981}\x{9982}\x{9983}\x{9984}'
. '\x{9985}\x{9986}\x{9987}\x{9988}\x{9989}\x{998A}\x{998B}\x{998C}\x{998D}'
. '\x{998E}\x{998F}\x{9990}\x{9991}\x{9992}\x{9993}\x{9994}\x{9995}\x{9996}'
. '\x{9997}\x{9998}\x{9999}\x{999A}\x{999B}\x{999C}\x{999D}\x{999E}\x{999F}'
. '\x{99A0}\x{99A1}\x{99A2}\x{99A3}\x{99A4}\x{99A5}\x{99A6}\x{99A7}\x{99A8}'
. '\x{99A9}\x{99AA}\x{99AB}\x{99AC}\x{99AD}\x{99AE}\x{99AF}\x{99B0}\x{99B1}'
. '\x{99B2}\x{99B3}\x{99B4}\x{99B5}\x{99B6}\x{99B7}\x{99B8}\x{99B9}\x{99BA}'
. '\x{99BB}\x{99BC}\x{99BD}\x{99BE}\x{99C0}\x{99C1}\x{99C2}\x{99C3}\x{99C4}'
. '\x{99C6}\x{99C7}\x{99C8}\x{99C9}\x{99CA}\x{99CB}\x{99CC}\x{99CD}\x{99CE}'
. '\x{99CF}\x{99D0}\x{99D1}\x{99D2}\x{99D3}\x{99D4}\x{99D5}\x{99D6}\x{99D7}'
. '\x{99D8}\x{99D9}\x{99DA}\x{99DB}\x{99DC}\x{99DD}\x{99DE}\x{99DF}\x{99E1}'
. '\x{99E2}\x{99E3}\x{99E4}\x{99E5}\x{99E7}\x{99E8}\x{99E9}\x{99EA}\x{99EC}'
. '\x{99ED}\x{99EE}\x{99EF}\x{99F0}\x{99F1}\x{99F2}\x{99F3}\x{99F4}\x{99F6}'
. '\x{99F7}\x{99F8}\x{99F9}\x{99FA}\x{99FB}\x{99FC}\x{99FD}\x{99FE}\x{99FF}'
. '\x{9A00}\x{9A01}\x{9A02}\x{9A03}\x{9A04}\x{9A05}\x{9A06}\x{9A07}\x{9A08}'
. '\x{9A09}\x{9A0A}\x{9A0B}\x{9A0C}\x{9A0D}\x{9A0E}\x{9A0F}\x{9A11}\x{9A14}'
. '\x{9A15}\x{9A16}\x{9A19}\x{9A1A}\x{9A1B}\x{9A1C}\x{9A1D}\x{9A1E}\x{9A1F}'
. '\x{9A20}\x{9A21}\x{9A22}\x{9A23}\x{9A24}\x{9A25}\x{9A26}\x{9A27}\x{9A29}'
. '\x{9A2A}\x{9A2B}\x{9A2C}\x{9A2D}\x{9A2E}\x{9A2F}\x{9A30}\x{9A31}\x{9A32}'
. '\x{9A33}\x{9A34}\x{9A35}\x{9A36}\x{9A37}\x{9A38}\x{9A39}\x{9A3A}\x{9A3C}'
. '\x{9A3D}\x{9A3E}\x{9A3F}\x{9A40}\x{9A41}\x{9A42}\x{9A43}\x{9A44}\x{9A45}'
. '\x{9A46}\x{9A47}\x{9A48}\x{9A49}\x{9A4A}\x{9A4B}\x{9A4C}\x{9A4D}\x{9A4E}'
. '\x{9A4F}\x{9A50}\x{9A52}\x{9A53}\x{9A54}\x{9A55}\x{9A56}\x{9A57}\x{9A59}'
. '\x{9A5A}\x{9A5B}\x{9A5C}\x{9A5E}\x{9A5F}\x{9A60}\x{9A61}\x{9A62}\x{9A64}'
. '\x{9A65}\x{9A66}\x{9A67}\x{9A68}\x{9A69}\x{9A6A}\x{9A6B}\x{9A6C}\x{9A6D}'
. '\x{9A6E}\x{9A6F}\x{9A70}\x{9A71}\x{9A72}\x{9A73}\x{9A74}\x{9A75}\x{9A76}'
. '\x{9A77}\x{9A78}\x{9A79}\x{9A7A}\x{9A7B}\x{9A7C}\x{9A7D}\x{9A7E}\x{9A7F}'
. '\x{9A80}\x{9A81}\x{9A82}\x{9A83}\x{9A84}\x{9A85}\x{9A86}\x{9A87}\x{9A88}'
. '\x{9A89}\x{9A8A}\x{9A8B}\x{9A8C}\x{9A8D}\x{9A8E}\x{9A8F}\x{9A90}\x{9A91}'
. '\x{9A92}\x{9A93}\x{9A94}\x{9A95}\x{9A96}\x{9A97}\x{9A98}\x{9A99}\x{9A9A}'
. '\x{9A9B}\x{9A9C}\x{9A9D}\x{9A9E}\x{9A9F}\x{9AA0}\x{9AA1}\x{9AA2}\x{9AA3}'
. '\x{9AA4}\x{9AA5}\x{9AA6}\x{9AA7}\x{9AA8}\x{9AAA}\x{9AAB}\x{9AAC}\x{9AAD}'
. '\x{9AAE}\x{9AAF}\x{9AB0}\x{9AB1}\x{9AB2}\x{9AB3}\x{9AB4}\x{9AB5}\x{9AB6}'
. '\x{9AB7}\x{9AB8}\x{9AB9}\x{9ABA}\x{9ABB}\x{9ABC}\x{9ABE}\x{9ABF}\x{9AC0}'
. '\x{9AC1}\x{9AC2}\x{9AC3}\x{9AC4}\x{9AC5}\x{9AC6}\x{9AC7}\x{9AC9}\x{9ACA}'
. '\x{9ACB}\x{9ACC}\x{9ACD}\x{9ACE}\x{9ACF}\x{9AD0}\x{9AD1}\x{9AD2}\x{9AD3}'
. '\x{9AD4}\x{9AD5}\x{9AD6}\x{9AD8}\x{9AD9}\x{9ADA}\x{9ADB}\x{9ADC}\x{9ADD}'
. '\x{9ADE}\x{9ADF}\x{9AE1}\x{9AE2}\x{9AE3}\x{9AE5}\x{9AE6}\x{9AE7}\x{9AEA}'
. '\x{9AEB}\x{9AEC}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF2}\x{9AF3}\x{9AF4}'
. '\x{9AF5}\x{9AF6}\x{9AF7}\x{9AF8}\x{9AF9}\x{9AFA}\x{9AFB}\x{9AFC}\x{9AFD}'
. '\x{9AFE}\x{9AFF}\x{9B01}\x{9B03}\x{9B04}\x{9B05}\x{9B06}\x{9B07}\x{9B08}'
. '\x{9B0A}\x{9B0B}\x{9B0C}\x{9B0D}\x{9B0E}\x{9B0F}\x{9B10}\x{9B11}\x{9B12}'
. '\x{9B13}\x{9B15}\x{9B16}\x{9B17}\x{9B18}\x{9B19}\x{9B1A}\x{9B1C}\x{9B1D}'
. '\x{9B1E}\x{9B1F}\x{9B20}\x{9B21}\x{9B22}\x{9B23}\x{9B24}\x{9B25}\x{9B26}'
. '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2B}\x{9B2C}\x{9B2D}\x{9B2E}\x{9B2F}'
. '\x{9B30}\x{9B31}\x{9B32}\x{9B33}\x{9B35}\x{9B36}\x{9B37}\x{9B38}\x{9B39}'
. '\x{9B3A}\x{9B3B}\x{9B3C}\x{9B3E}\x{9B3F}\x{9B41}\x{9B42}\x{9B43}\x{9B44}'
. '\x{9B45}\x{9B46}\x{9B47}\x{9B48}\x{9B49}\x{9B4A}\x{9B4B}\x{9B4C}\x{9B4D}'
. '\x{9B4E}\x{9B4F}\x{9B51}\x{9B52}\x{9B53}\x{9B54}\x{9B55}\x{9B56}\x{9B58}'
. '\x{9B59}\x{9B5A}\x{9B5B}\x{9B5C}\x{9B5D}\x{9B5E}\x{9B5F}\x{9B60}\x{9B61}'
. '\x{9B63}\x{9B64}\x{9B65}\x{9B66}\x{9B67}\x{9B68}\x{9B69}\x{9B6A}\x{9B6B}'
. '\x{9B6C}\x{9B6D}\x{9B6E}\x{9B6F}\x{9B70}\x{9B71}\x{9B73}\x{9B74}\x{9B75}'
. '\x{9B76}\x{9B77}\x{9B78}\x{9B79}\x{9B7A}\x{9B7B}\x{9B7C}\x{9B7D}\x{9B7E}'
. '\x{9B7F}\x{9B80}\x{9B81}\x{9B82}\x{9B83}\x{9B84}\x{9B85}\x{9B86}\x{9B87}'
. '\x{9B88}\x{9B8A}\x{9B8B}\x{9B8D}\x{9B8E}\x{9B8F}\x{9B90}\x{9B91}\x{9B92}'
. '\x{9B93}\x{9B94}\x{9B95}\x{9B96}\x{9B97}\x{9B98}\x{9B9A}\x{9B9B}\x{9B9C}'
. '\x{9B9D}\x{9B9E}\x{9B9F}\x{9BA0}\x{9BA1}\x{9BA2}\x{9BA3}\x{9BA4}\x{9BA5}'
. '\x{9BA6}\x{9BA7}\x{9BA8}\x{9BA9}\x{9BAA}\x{9BAB}\x{9BAC}\x{9BAD}\x{9BAE}'
. '\x{9BAF}\x{9BB0}\x{9BB1}\x{9BB2}\x{9BB3}\x{9BB4}\x{9BB5}\x{9BB6}\x{9BB7}'
. '\x{9BB8}\x{9BB9}\x{9BBA}\x{9BBB}\x{9BBC}\x{9BBD}\x{9BBE}\x{9BBF}\x{9BC0}'
. '\x{9BC1}\x{9BC3}\x{9BC4}\x{9BC5}\x{9BC6}\x{9BC7}\x{9BC8}\x{9BC9}\x{9BCA}'
. '\x{9BCB}\x{9BCC}\x{9BCD}\x{9BCE}\x{9BCF}\x{9BD0}\x{9BD1}\x{9BD2}\x{9BD3}'
. '\x{9BD4}\x{9BD5}\x{9BD6}\x{9BD7}\x{9BD8}\x{9BD9}\x{9BDA}\x{9BDB}\x{9BDC}'
. '\x{9BDD}\x{9BDE}\x{9BDF}\x{9BE0}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}\x{9BE5}'
. '\x{9BE6}\x{9BE7}\x{9BE8}\x{9BE9}\x{9BEA}\x{9BEB}\x{9BEC}\x{9BED}\x{9BEE}'
. '\x{9BEF}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF3}\x{9BF4}\x{9BF5}\x{9BF7}\x{9BF8}'
. '\x{9BF9}\x{9BFA}\x{9BFB}\x{9BFC}\x{9BFD}\x{9BFE}\x{9BFF}\x{9C02}\x{9C05}'
. '\x{9C06}\x{9C07}\x{9C08}\x{9C09}\x{9C0A}\x{9C0B}\x{9C0C}\x{9C0D}\x{9C0E}'
. '\x{9C0F}\x{9C10}\x{9C11}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C16}\x{9C17}'
. '\x{9C18}\x{9C19}\x{9C1A}\x{9C1B}\x{9C1C}\x{9C1D}\x{9C1E}\x{9C1F}\x{9C20}'
. '\x{9C21}\x{9C22}\x{9C23}\x{9C24}\x{9C25}\x{9C26}\x{9C27}\x{9C28}\x{9C29}'
. '\x{9C2A}\x{9C2B}\x{9C2C}\x{9C2D}\x{9C2F}\x{9C30}\x{9C31}\x{9C32}\x{9C33}'
. '\x{9C34}\x{9C35}\x{9C36}\x{9C37}\x{9C38}\x{9C39}\x{9C3A}\x{9C3B}\x{9C3C}'
. '\x{9C3D}\x{9C3E}\x{9C3F}\x{9C40}\x{9C41}\x{9C43}\x{9C44}\x{9C45}\x{9C46}'
. '\x{9C47}\x{9C48}\x{9C49}\x{9C4A}\x{9C4B}\x{9C4C}\x{9C4D}\x{9C4E}\x{9C50}'
. '\x{9C52}\x{9C53}\x{9C54}\x{9C55}\x{9C56}\x{9C57}\x{9C58}\x{9C59}\x{9C5A}'
. '\x{9C5B}\x{9C5C}\x{9C5D}\x{9C5E}\x{9C5F}\x{9C60}\x{9C62}\x{9C63}\x{9C65}'
. '\x{9C66}\x{9C67}\x{9C68}\x{9C69}\x{9C6A}\x{9C6B}\x{9C6C}\x{9C6D}\x{9C6E}'
. '\x{9C6F}\x{9C70}\x{9C71}\x{9C72}\x{9C73}\x{9C74}\x{9C75}\x{9C77}\x{9C78}'
. '\x{9C79}\x{9C7A}\x{9C7C}\x{9C7D}\x{9C7E}\x{9C7F}\x{9C80}\x{9C81}\x{9C82}'
. '\x{9C83}\x{9C84}\x{9C85}\x{9C86}\x{9C87}\x{9C88}\x{9C89}\x{9C8A}\x{9C8B}'
. '\x{9C8C}\x{9C8D}\x{9C8E}\x{9C8F}\x{9C90}\x{9C91}\x{9C92}\x{9C93}\x{9C94}'
. '\x{9C95}\x{9C96}\x{9C97}\x{9C98}\x{9C99}\x{9C9A}\x{9C9B}\x{9C9C}\x{9C9D}'
. '\x{9C9E}\x{9C9F}\x{9CA0}\x{9CA1}\x{9CA2}\x{9CA3}\x{9CA4}\x{9CA5}\x{9CA6}'
. '\x{9CA7}\x{9CA8}\x{9CA9}\x{9CAA}\x{9CAB}\x{9CAC}\x{9CAD}\x{9CAE}\x{9CAF}'
. '\x{9CB0}\x{9CB1}\x{9CB2}\x{9CB3}\x{9CB4}\x{9CB5}\x{9CB6}\x{9CB7}\x{9CB8}'
. '\x{9CB9}\x{9CBA}\x{9CBB}\x{9CBC}\x{9CBD}\x{9CBE}\x{9CBF}\x{9CC0}\x{9CC1}'
. '\x{9CC2}\x{9CC3}\x{9CC4}\x{9CC5}\x{9CC6}\x{9CC7}\x{9CC8}\x{9CC9}\x{9CCA}'
. '\x{9CCB}\x{9CCC}\x{9CCD}\x{9CCE}\x{9CCF}\x{9CD0}\x{9CD1}\x{9CD2}\x{9CD3}'
. '\x{9CD4}\x{9CD5}\x{9CD6}\x{9CD7}\x{9CD8}\x{9CD9}\x{9CDA}\x{9CDB}\x{9CDC}'
. '\x{9CDD}\x{9CDE}\x{9CDF}\x{9CE0}\x{9CE1}\x{9CE2}\x{9CE3}\x{9CE4}\x{9CE5}'
. '\x{9CE6}\x{9CE7}\x{9CE8}\x{9CE9}\x{9CEA}\x{9CEB}\x{9CEC}\x{9CED}\x{9CEE}'
. '\x{9CEF}\x{9CF0}\x{9CF1}\x{9CF2}\x{9CF3}\x{9CF4}\x{9CF5}\x{9CF6}\x{9CF7}'
. '\x{9CF8}\x{9CF9}\x{9CFA}\x{9CFB}\x{9CFC}\x{9CFD}\x{9CFE}\x{9CFF}\x{9D00}'
. '\x{9D01}\x{9D02}\x{9D03}\x{9D04}\x{9D05}\x{9D06}\x{9D07}\x{9D08}\x{9D09}'
. '\x{9D0A}\x{9D0B}\x{9D0F}\x{9D10}\x{9D12}\x{9D13}\x{9D14}\x{9D15}\x{9D16}'
. '\x{9D17}\x{9D18}\x{9D19}\x{9D1A}\x{9D1B}\x{9D1C}\x{9D1D}\x{9D1E}\x{9D1F}'
. '\x{9D20}\x{9D21}\x{9D22}\x{9D23}\x{9D24}\x{9D25}\x{9D26}\x{9D28}\x{9D29}'
. '\x{9D2B}\x{9D2D}\x{9D2E}\x{9D2F}\x{9D30}\x{9D31}\x{9D32}\x{9D33}\x{9D34}'
. '\x{9D36}\x{9D37}\x{9D38}\x{9D39}\x{9D3A}\x{9D3B}\x{9D3D}\x{9D3E}\x{9D3F}'
. '\x{9D40}\x{9D41}\x{9D42}\x{9D43}\x{9D45}\x{9D46}\x{9D47}\x{9D48}\x{9D49}'
. '\x{9D4A}\x{9D4B}\x{9D4C}\x{9D4D}\x{9D4E}\x{9D4F}\x{9D50}\x{9D51}\x{9D52}'
. '\x{9D53}\x{9D54}\x{9D55}\x{9D56}\x{9D57}\x{9D58}\x{9D59}\x{9D5A}\x{9D5B}'
. '\x{9D5C}\x{9D5D}\x{9D5E}\x{9D5F}\x{9D60}\x{9D61}\x{9D62}\x{9D63}\x{9D64}'
. '\x{9D65}\x{9D66}\x{9D67}\x{9D68}\x{9D69}\x{9D6A}\x{9D6B}\x{9D6C}\x{9D6E}'
. '\x{9D6F}\x{9D70}\x{9D71}\x{9D72}\x{9D73}\x{9D74}\x{9D75}\x{9D76}\x{9D77}'
. '\x{9D78}\x{9D79}\x{9D7A}\x{9D7B}\x{9D7C}\x{9D7D}\x{9D7E}\x{9D7F}\x{9D80}'
. '\x{9D81}\x{9D82}\x{9D83}\x{9D84}\x{9D85}\x{9D86}\x{9D87}\x{9D88}\x{9D89}'
. '\x{9D8A}\x{9D8B}\x{9D8C}\x{9D8D}\x{9D8E}\x{9D90}\x{9D91}\x{9D92}\x{9D93}'
. '\x{9D94}\x{9D96}\x{9D97}\x{9D98}\x{9D99}\x{9D9A}\x{9D9B}\x{9D9C}\x{9D9D}'
. '\x{9D9E}\x{9D9F}\x{9DA0}\x{9DA1}\x{9DA2}\x{9DA3}\x{9DA4}\x{9DA5}\x{9DA6}'
. '\x{9DA7}\x{9DA8}\x{9DA9}\x{9DAA}\x{9DAB}\x{9DAC}\x{9DAD}\x{9DAF}\x{9DB0}'
. '\x{9DB1}\x{9DB2}\x{9DB3}\x{9DB4}\x{9DB5}\x{9DB6}\x{9DB7}\x{9DB8}\x{9DB9}'
. '\x{9DBA}\x{9DBB}\x{9DBC}\x{9DBE}\x{9DBF}\x{9DC1}\x{9DC2}\x{9DC3}\x{9DC4}'
. '\x{9DC5}\x{9DC7}\x{9DC8}\x{9DC9}\x{9DCA}\x{9DCB}\x{9DCC}\x{9DCD}\x{9DCE}'
. '\x{9DCF}\x{9DD0}\x{9DD1}\x{9DD2}\x{9DD3}\x{9DD4}\x{9DD5}\x{9DD6}\x{9DD7}'
. '\x{9DD8}\x{9DD9}\x{9DDA}\x{9DDB}\x{9DDC}\x{9DDD}\x{9DDE}\x{9DDF}\x{9DE0}'
. '\x{9DE1}\x{9DE2}\x{9DE3}\x{9DE4}\x{9DE5}\x{9DE6}\x{9DE7}\x{9DE8}\x{9DE9}'
. '\x{9DEB}\x{9DEC}\x{9DED}\x{9DEE}\x{9DEF}\x{9DF0}\x{9DF1}\x{9DF2}\x{9DF3}'
. '\x{9DF4}\x{9DF5}\x{9DF6}\x{9DF7}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFB}\x{9DFD}'
. '\x{9DFE}\x{9DFF}\x{9E00}\x{9E01}\x{9E02}\x{9E03}\x{9E04}\x{9E05}\x{9E06}'
. '\x{9E07}\x{9E08}\x{9E09}\x{9E0A}\x{9E0B}\x{9E0C}\x{9E0D}\x{9E0F}\x{9E10}'
. '\x{9E11}\x{9E12}\x{9E13}\x{9E14}\x{9E15}\x{9E17}\x{9E18}\x{9E19}\x{9E1A}'
. '\x{9E1B}\x{9E1D}\x{9E1E}\x{9E1F}\x{9E20}\x{9E21}\x{9E22}\x{9E23}\x{9E24}'
. '\x{9E25}\x{9E26}\x{9E27}\x{9E28}\x{9E29}\x{9E2A}\x{9E2B}\x{9E2C}\x{9E2D}'
. '\x{9E2E}\x{9E2F}\x{9E30}\x{9E31}\x{9E32}\x{9E33}\x{9E34}\x{9E35}\x{9E36}'
. '\x{9E37}\x{9E38}\x{9E39}\x{9E3A}\x{9E3B}\x{9E3C}\x{9E3D}\x{9E3E}\x{9E3F}'
. '\x{9E40}\x{9E41}\x{9E42}\x{9E43}\x{9E44}\x{9E45}\x{9E46}\x{9E47}\x{9E48}'
. '\x{9E49}\x{9E4A}\x{9E4B}\x{9E4C}\x{9E4D}\x{9E4E}\x{9E4F}\x{9E50}\x{9E51}'
. '\x{9E52}\x{9E53}\x{9E54}\x{9E55}\x{9E56}\x{9E57}\x{9E58}\x{9E59}\x{9E5A}'
. '\x{9E5B}\x{9E5C}\x{9E5D}\x{9E5E}\x{9E5F}\x{9E60}\x{9E61}\x{9E62}\x{9E63}'
. '\x{9E64}\x{9E65}\x{9E66}\x{9E67}\x{9E68}\x{9E69}\x{9E6A}\x{9E6B}\x{9E6C}'
. '\x{9E6D}\x{9E6E}\x{9E6F}\x{9E70}\x{9E71}\x{9E72}\x{9E73}\x{9E74}\x{9E75}'
. '\x{9E76}\x{9E77}\x{9E79}\x{9E7A}\x{9E7C}\x{9E7D}\x{9E7E}\x{9E7F}\x{9E80}'
. '\x{9E81}\x{9E82}\x{9E83}\x{9E84}\x{9E85}\x{9E86}\x{9E87}\x{9E88}\x{9E89}'
. '\x{9E8A}\x{9E8B}\x{9E8C}\x{9E8D}\x{9E8E}\x{9E91}\x{9E92}\x{9E93}\x{9E94}'
. '\x{9E96}\x{9E97}\x{9E99}\x{9E9A}\x{9E9B}\x{9E9C}\x{9E9D}\x{9E9F}\x{9EA0}'
. '\x{9EA1}\x{9EA3}\x{9EA4}\x{9EA5}\x{9EA6}\x{9EA7}\x{9EA8}\x{9EA9}\x{9EAA}'
. '\x{9EAD}\x{9EAE}\x{9EAF}\x{9EB0}\x{9EB2}\x{9EB3}\x{9EB4}\x{9EB5}\x{9EB6}'
. '\x{9EB7}\x{9EB8}\x{9EBB}\x{9EBC}\x{9EBD}\x{9EBE}\x{9EBF}\x{9EC0}\x{9EC1}'
. '\x{9EC2}\x{9EC3}\x{9EC4}\x{9EC5}\x{9EC6}\x{9EC7}\x{9EC8}\x{9EC9}\x{9ECA}'
. '\x{9ECB}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED1}\x{9ED2}\x{9ED3}'
. '\x{9ED4}\x{9ED5}\x{9ED6}\x{9ED7}\x{9ED8}\x{9ED9}\x{9EDA}\x{9EDB}\x{9EDC}'
. '\x{9EDD}\x{9EDE}\x{9EDF}\x{9EE0}\x{9EE1}\x{9EE2}\x{9EE3}\x{9EE4}\x{9EE5}'
. '\x{9EE6}\x{9EE7}\x{9EE8}\x{9EE9}\x{9EEA}\x{9EEB}\x{9EED}\x{9EEE}\x{9EEF}'
. '\x{9EF0}\x{9EF2}\x{9EF3}\x{9EF4}\x{9EF5}\x{9EF6}\x{9EF7}\x{9EF8}\x{9EF9}'
. '\x{9EFA}\x{9EFB}\x{9EFC}\x{9EFD}\x{9EFE}\x{9EFF}\x{9F00}\x{9F01}\x{9F02}'
. '\x{9F04}\x{9F05}\x{9F06}\x{9F07}\x{9F08}\x{9F09}\x{9F0A}\x{9F0B}\x{9F0C}'
. '\x{9F0D}\x{9F0E}\x{9F0F}\x{9F10}\x{9F12}\x{9F13}\x{9F15}\x{9F16}\x{9F17}'
. '\x{9F18}\x{9F19}\x{9F1A}\x{9F1B}\x{9F1C}\x{9F1D}\x{9F1E}\x{9F1F}\x{9F20}'
. '\x{9F22}\x{9F23}\x{9F24}\x{9F25}\x{9F27}\x{9F28}\x{9F29}\x{9F2A}\x{9F2B}'
. '\x{9F2C}\x{9F2D}\x{9F2E}\x{9F2F}\x{9F30}\x{9F31}\x{9F32}\x{9F33}\x{9F34}'
. '\x{9F35}\x{9F36}\x{9F37}\x{9F38}\x{9F39}\x{9F3A}\x{9F3B}\x{9F3C}\x{9F3D}'
. '\x{9F3E}\x{9F3F}\x{9F40}\x{9F41}\x{9F42}\x{9F43}\x{9F44}\x{9F46}\x{9F47}'
. '\x{9F48}\x{9F49}\x{9F4A}\x{9F4B}\x{9F4C}\x{9F4D}\x{9F4E}\x{9F4F}\x{9F50}'
. '\x{9F51}\x{9F52}\x{9F54}\x{9F55}\x{9F56}\x{9F57}\x{9F58}\x{9F59}\x{9F5A}'
. '\x{9F5B}\x{9F5C}\x{9F5D}\x{9F5E}\x{9F5F}\x{9F60}\x{9F61}\x{9F63}\x{9F64}'
. '\x{9F65}\x{9F66}\x{9F67}\x{9F68}\x{9F69}\x{9F6A}\x{9F6B}\x{9F6C}\x{9F6E}'
. '\x{9F6F}\x{9F70}\x{9F71}\x{9F72}\x{9F73}\x{9F74}\x{9F75}\x{9F76}\x{9F77}'
. '\x{9F78}\x{9F79}\x{9F7A}\x{9F7B}\x{9F7C}\x{9F7D}\x{9F7E}\x{9F7F}\x{9F80}'
. '\x{9F81}\x{9F82}\x{9F83}\x{9F84}\x{9F85}\x{9F86}\x{9F87}\x{9F88}\x{9F89}'
. '\x{9F8A}\x{9F8B}\x{9F8C}\x{9F8D}\x{9F8E}\x{9F8F}\x{9F90}\x{9F91}\x{9F92}'
. '\x{9F93}\x{9F94}\x{9F95}\x{9F96}\x{9F97}\x{9F98}\x{9F99}\x{9F9A}\x{9F9B}'
. '\x{9F9C}\x{9F9D}\x{9F9E}\x{9F9F}\x{9FA0}\x{9FA2}\x{9FA4}\x{9FA5}]{1,20}$/iu',
];
laminas-validator/src/Hostname/Biz.php 0000644 00000752311 15240152635 0013771 0 ustar 00 <?php // phpcs:disable PSR12.Files.FileHeader.IncorrectOrder
namespace Laminas\Validator\Hostname;
/**
* Resource file for biz idn validation
*/
return [
1 => '/^[\x{002d}0-9a-zäåæéöøü]{1,63}$/iu',
2 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu',
3 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu',
4 => '/^[\x{002d}0-9a-záæéíðóöúýþ]{1,63}$/iu',
5 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu',
6 => '/^[\x{002d}0-9a-ząčėęįšūųž]{1,63}$/iu',
7 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu',
8 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu',
9 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu',
10 => '/^[\x{002d}0-9a-záàâãçéêíóôõú]{1,63}$/iu',
11 => '/^[\x{002d}0-9a-z\x{3005}-\x{3007}\x{3041}-\x{3093}\x{309D}\x{309E}\x{30A1}-\x{30F6}\x{30FC}'
. '\x{30FD}\x{30FE}\x{4E00}\x{4E01}\x{4E03}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}'
. '\x{4E0B}\x{4E0D}\x{4E0E}\x{4E10}\x{4E11}\x{4E14}\x{4E15}\x{4E16}\x{4E17}'
. '\x{4E18}\x{4E19}\x{4E1E}\x{4E21}\x{4E26}\x{4E2A}\x{4E2D}\x{4E31}\x{4E32}'
. '\x{4E36}\x{4E38}\x{4E39}\x{4E3B}\x{4E3C}\x{4E3F}\x{4E42}\x{4E43}\x{4E45}'
. '\x{4E4B}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E55}\x{4E56}\x{4E57}\x{4E58}\x{4E59}'
. '\x{4E5D}\x{4E5E}\x{4E5F}\x{4E62}\x{4E71}\x{4E73}\x{4E7E}\x{4E80}\x{4E82}'
. '\x{4E85}\x{4E86}\x{4E88}\x{4E89}\x{4E8A}\x{4E8B}\x{4E8C}\x{4E8E}\x{4E91}'
. '\x{4E92}\x{4E94}\x{4E95}\x{4E98}\x{4E99}\x{4E9B}\x{4E9C}\x{4E9E}\x{4E9F}'
. '\x{4EA0}\x{4EA1}\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA8}\x{4EAB}\x{4EAC}'
. '\x{4EAD}\x{4EAE}\x{4EB0}\x{4EB3}\x{4EB6}\x{4EBA}\x{4EC0}\x{4EC1}\x{4EC2}'
. '\x{4EC4}\x{4EC6}\x{4EC7}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED4}'
. '\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE3}'
. '\x{4EE4}\x{4EE5}\x{4EED}\x{4EEE}\x{4EF0}\x{4EF2}\x{4EF6}\x{4EF7}\x{4EFB}'
. '\x{4F01}\x{4F09}\x{4F0A}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}\x{4F11}\x{4F1A}'
. '\x{4F1C}\x{4F1D}\x{4F2F}\x{4F30}\x{4F34}\x{4F36}\x{4F38}\x{4F3A}\x{4F3C}'
. '\x{4F3D}\x{4F43}\x{4F46}\x{4F47}\x{4F4D}\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}'
. '\x{4F53}\x{4F55}\x{4F57}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}'
. '\x{4F69}\x{4F6F}\x{4F70}\x{4F73}\x{4F75}\x{4F76}\x{4F7B}\x{4F7C}\x{4F7F}'
. '\x{4F83}\x{4F86}\x{4F88}\x{4F8B}\x{4F8D}\x{4F8F}\x{4F91}\x{4F96}\x{4F98}'
. '\x{4F9B}\x{4F9D}\x{4FA0}\x{4FA1}\x{4FAB}\x{4FAD}\x{4FAE}\x{4FAF}\x{4FB5}'
. '\x{4FB6}\x{4FBF}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FCA}\x{4FCE}\x{4FD0}\x{4FD1}'
. '\x{4FD4}\x{4FD7}\x{4FD8}\x{4FDA}\x{4FDB}\x{4FDD}\x{4FDF}\x{4FE1}\x{4FE3}'
. '\x{4FE4}\x{4FE5}\x{4FEE}\x{4FEF}\x{4FF3}\x{4FF5}\x{4FF6}\x{4FF8}\x{4FFA}'
. '\x{4FFE}\x{5005}\x{5006}\x{5009}\x{500B}\x{500D}\x{500F}\x{5011}\x{5012}'
. '\x{5014}\x{5016}\x{5019}\x{501A}\x{501F}\x{5021}\x{5023}\x{5024}\x{5025}'
. '\x{5026}\x{5028}\x{5029}\x{502A}\x{502B}\x{502C}\x{502D}\x{5036}\x{5039}'
. '\x{5043}\x{5047}\x{5048}\x{5049}\x{504F}\x{5050}\x{5055}\x{5056}\x{505A}'
. '\x{505C}\x{5065}\x{506C}\x{5072}\x{5074}\x{5075}\x{5076}\x{5078}\x{507D}'
. '\x{5080}\x{5085}\x{508D}\x{5091}\x{5098}\x{5099}\x{509A}\x{50AC}\x{50AD}'
. '\x{50B2}\x{50B3}\x{50B4}\x{50B5}\x{50B7}\x{50BE}\x{50C2}\x{50C5}\x{50C9}'
. '\x{50CA}\x{50CD}\x{50CF}\x{50D1}\x{50D5}\x{50D6}\x{50DA}\x{50DE}\x{50E3}'
. '\x{50E5}\x{50E7}\x{50ED}\x{50EE}\x{50F5}\x{50F9}\x{50FB}\x{5100}\x{5101}'
. '\x{5102}\x{5104}\x{5109}\x{5112}\x{5114}\x{5115}\x{5116}\x{5118}\x{511A}'
. '\x{511F}\x{5121}\x{512A}\x{5132}\x{5137}\x{513A}\x{513B}\x{513C}\x{513F}'
. '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}'
. '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5152}\x{5154}\x{515A}\x{515C}'
. '\x{5162}\x{5165}\x{5168}\x{5169}\x{516A}\x{516B}\x{516C}\x{516D}\x{516E}'
. '\x{5171}\x{5175}\x{5176}\x{5177}\x{5178}\x{517C}\x{5180}\x{5182}\x{5185}'
. '\x{5186}\x{5189}\x{518A}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}'
. '\x{5193}\x{5195}\x{5196}\x{5197}\x{5199}\x{51A0}\x{51A2}\x{51A4}\x{51A5}'
. '\x{51A6}\x{51A8}\x{51A9}\x{51AA}\x{51AB}\x{51AC}\x{51B0}\x{51B1}\x{51B2}'
. '\x{51B3}\x{51B4}\x{51B5}\x{51B6}\x{51B7}\x{51BD}\x{51C4}\x{51C5}\x{51C6}'
. '\x{51C9}\x{51CB}\x{51CC}\x{51CD}\x{51D6}\x{51DB}\x{51DC}\x{51DD}\x{51E0}'
. '\x{51E1}\x{51E6}\x{51E7}\x{51E9}\x{51EA}\x{51ED}\x{51F0}\x{51F1}\x{51F5}'
. '\x{51F6}\x{51F8}\x{51F9}\x{51FA}\x{51FD}\x{51FE}\x{5200}\x{5203}\x{5204}'
. '\x{5206}\x{5207}\x{5208}\x{520A}\x{520B}\x{520E}\x{5211}\x{5214}\x{5217}'
. '\x{521D}\x{5224}\x{5225}\x{5227}\x{5229}\x{522A}\x{522E}\x{5230}\x{5233}'
. '\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{5243}\x{5244}\x{5247}'
. '\x{524A}\x{524B}\x{524C}\x{524D}\x{524F}\x{5254}\x{5256}\x{525B}\x{525E}'
. '\x{5263}\x{5264}\x{5265}\x{5269}\x{526A}\x{526F}\x{5270}\x{5271}\x{5272}'
. '\x{5273}\x{5274}\x{5275}\x{527D}\x{527F}\x{5283}\x{5287}\x{5288}\x{5289}'
. '\x{528D}\x{5291}\x{5292}\x{5294}\x{529B}\x{529F}\x{52A0}\x{52A3}\x{52A9}'
. '\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52B1}\x{52B4}\x{52B5}\x{52B9}\x{52BC}'
. '\x{52BE}\x{52C1}\x{52C3}\x{52C5}\x{52C7}\x{52C9}\x{52CD}\x{52D2}\x{52D5}'
. '\x{52D7}\x{52D8}\x{52D9}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}'
. '\x{52E4}\x{52E6}\x{52E7}\x{52F2}\x{52F3}\x{52F5}\x{52F8}\x{52F9}\x{52FA}'
. '\x{52FE}\x{52FF}\x{5301}\x{5302}\x{5305}\x{5306}\x{5308}\x{530D}\x{530F}'
. '\x{5310}\x{5315}\x{5316}\x{5317}\x{5319}\x{531A}\x{531D}\x{5320}\x{5321}'
. '\x{5323}\x{532A}\x{532F}\x{5331}\x{5333}\x{5338}\x{5339}\x{533A}\x{533B}'
. '\x{533F}\x{5340}\x{5341}\x{5343}\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}'
. '\x{534A}\x{534D}\x{5351}\x{5352}\x{5353}\x{5354}\x{5357}\x{5358}\x{535A}'
. '\x{535C}\x{535E}\x{5360}\x{5366}\x{5369}\x{536E}\x{536F}\x{5370}\x{5371}'
. '\x{5373}\x{5374}\x{5375}\x{5377}\x{5378}\x{537B}\x{537F}\x{5382}\x{5384}'
. '\x{5396}\x{5398}\x{539A}\x{539F}\x{53A0}\x{53A5}\x{53A6}\x{53A8}\x{53A9}'
. '\x{53AD}\x{53AE}\x{53B0}\x{53B3}\x{53B6}\x{53BB}\x{53C2}\x{53C3}\x{53C8}'
. '\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}\x{53D4}\x{53D6}\x{53D7}'
. '\x{53D9}\x{53DB}\x{53DF}\x{53E1}\x{53E2}\x{53E3}\x{53E4}\x{53E5}\x{53E8}'
. '\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}\x{53EF}\x{53F0}\x{53F1}'
. '\x{53F2}\x{53F3}\x{53F6}\x{53F7}\x{53F8}\x{53FA}\x{5401}\x{5403}\x{5404}'
. '\x{5408}\x{5409}\x{540A}\x{540B}\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}'
. '\x{5411}\x{541B}\x{541D}\x{541F}\x{5420}\x{5426}\x{5429}\x{542B}\x{542C}'
. '\x{542D}\x{542E}\x{5436}\x{5438}\x{5439}\x{543B}\x{543C}\x{543D}\x{543E}'
. '\x{5440}\x{5442}\x{5446}\x{5448}\x{5449}\x{544A}\x{544E}\x{5451}\x{545F}'
. '\x{5468}\x{546A}\x{5470}\x{5471}\x{5473}\x{5475}\x{5476}\x{5477}\x{547B}'
. '\x{547C}\x{547D}\x{5480}\x{5484}\x{5486}\x{548B}\x{548C}\x{548E}\x{548F}'
. '\x{5490}\x{5492}\x{54A2}\x{54A4}\x{54A5}\x{54A8}\x{54AB}\x{54AC}\x{54AF}'
. '\x{54B2}\x{54B3}\x{54B8}\x{54BC}\x{54BD}\x{54BE}\x{54C0}\x{54C1}\x{54C2}'
. '\x{54C4}\x{54C7}\x{54C8}\x{54C9}\x{54D8}\x{54E1}\x{54E2}\x{54E5}\x{54E6}'
. '\x{54E8}\x{54E9}\x{54ED}\x{54EE}\x{54F2}\x{54FA}\x{54FD}\x{5504}\x{5506}'
. '\x{5507}\x{550F}\x{5510}\x{5514}\x{5516}\x{552E}\x{552F}\x{5531}\x{5533}'
. '\x{5538}\x{5539}\x{553E}\x{5540}\x{5544}\x{5545}\x{5546}\x{554C}\x{554F}'
. '\x{5553}\x{5556}\x{5557}\x{555C}\x{555D}\x{5563}\x{557B}\x{557C}\x{557E}'
. '\x{5580}\x{5583}\x{5584}\x{5587}\x{5589}\x{558A}\x{558B}\x{5598}\x{5599}'
. '\x{559A}\x{559C}\x{559D}\x{559E}\x{559F}\x{55A7}\x{55A8}\x{55A9}\x{55AA}'
. '\x{55AB}\x{55AC}\x{55AE}\x{55B0}\x{55B6}\x{55C4}\x{55C5}\x{55C7}\x{55D4}'
. '\x{55DA}\x{55DC}\x{55DF}\x{55E3}\x{55E4}\x{55F7}\x{55F9}\x{55FD}\x{55FE}'
. '\x{5606}\x{5609}\x{5614}\x{5616}\x{5617}\x{5618}\x{561B}\x{5629}\x{562F}'
. '\x{5631}\x{5632}\x{5634}\x{5636}\x{5638}\x{5642}\x{564C}\x{564E}\x{5650}'
. '\x{565B}\x{5664}\x{5668}\x{566A}\x{566B}\x{566C}\x{5674}\x{5678}\x{567A}'
. '\x{5680}\x{5686}\x{5687}\x{568A}\x{568F}\x{5694}\x{56A0}\x{56A2}\x{56A5}'
. '\x{56AE}\x{56B4}\x{56B6}\x{56BC}\x{56C0}\x{56C1}\x{56C2}\x{56C3}\x{56C8}'
. '\x{56CE}\x{56D1}\x{56D3}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DE}\x{56E0}'
. '\x{56E3}\x{56EE}\x{56F0}\x{56F2}\x{56F3}\x{56F9}\x{56FA}\x{56FD}\x{56FF}'
. '\x{5700}\x{5703}\x{5704}\x{5708}\x{5709}\x{570B}\x{570D}\x{570F}\x{5712}'
. '\x{5713}\x{5716}\x{5718}\x{571C}\x{571F}\x{5726}\x{5727}\x{5728}\x{572D}'
. '\x{5730}\x{5737}\x{5738}\x{573B}\x{5740}\x{5742}\x{5747}\x{574A}\x{574E}'
. '\x{574F}\x{5750}\x{5751}\x{5761}\x{5764}\x{5766}\x{5769}\x{576A}\x{577F}'
. '\x{5782}\x{5788}\x{5789}\x{578B}\x{5793}\x{57A0}\x{57A2}\x{57A3}\x{57A4}'
. '\x{57AA}\x{57B0}\x{57B3}\x{57C0}\x{57C3}\x{57C6}\x{57CB}\x{57CE}\x{57D2}'
. '\x{57D3}\x{57D4}\x{57D6}\x{57DC}\x{57DF}\x{57E0}\x{57E3}\x{57F4}\x{57F7}'
. '\x{57F9}\x{57FA}\x{57FC}\x{5800}\x{5802}\x{5805}\x{5806}\x{580A}\x{580B}'
. '\x{5815}\x{5819}\x{581D}\x{5821}\x{5824}\x{582A}\x{582F}\x{5830}\x{5831}'
. '\x{5834}\x{5835}\x{583A}\x{583D}\x{5840}\x{5841}\x{584A}\x{584B}\x{5851}'
. '\x{5852}\x{5854}\x{5857}\x{5858}\x{5859}\x{585A}\x{585E}\x{5862}\x{5869}'
. '\x{586B}\x{5870}\x{5872}\x{5875}\x{5879}\x{587E}\x{5883}\x{5885}\x{5893}'
. '\x{5897}\x{589C}\x{589F}\x{58A8}\x{58AB}\x{58AE}\x{58B3}\x{58B8}\x{58B9}'
. '\x{58BA}\x{58BB}\x{58BE}\x{58C1}\x{58C5}\x{58C7}\x{58CA}\x{58CC}\x{58D1}'
. '\x{58D3}\x{58D5}\x{58D7}\x{58D8}\x{58D9}\x{58DC}\x{58DE}\x{58DF}\x{58E4}'
. '\x{58E5}\x{58EB}\x{58EC}\x{58EE}\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F7}'
. '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{5902}\x{5909}\x{590A}\x{590F}'
. '\x{5910}\x{5915}\x{5916}\x{5918}\x{5919}\x{591A}\x{591B}\x{591C}\x{5922}'
. '\x{5925}\x{5927}\x{5929}\x{592A}\x{592B}\x{592C}\x{592D}\x{592E}\x{5931}'
. '\x{5932}\x{5937}\x{5938}\x{593E}\x{5944}\x{5947}\x{5948}\x{5949}\x{594E}'
. '\x{594F}\x{5950}\x{5951}\x{5954}\x{5955}\x{5957}\x{5958}\x{595A}\x{5960}'
. '\x{5962}\x{5965}\x{5967}\x{5968}\x{5969}\x{596A}\x{596C}\x{596E}\x{5973}'
. '\x{5974}\x{5978}\x{597D}\x{5981}\x{5982}\x{5983}\x{5984}\x{598A}\x{598D}'
. '\x{5993}\x{5996}\x{5999}\x{599B}\x{599D}\x{59A3}\x{59A5}\x{59A8}\x{59AC}'
. '\x{59B2}\x{59B9}\x{59BB}\x{59BE}\x{59C6}\x{59C9}\x{59CB}\x{59D0}\x{59D1}'
. '\x{59D3}\x{59D4}\x{59D9}\x{59DA}\x{59DC}\x{59E5}\x{59E6}\x{59E8}\x{59EA}'
. '\x{59EB}\x{59F6}\x{59FB}\x{59FF}\x{5A01}\x{5A03}\x{5A09}\x{5A11}\x{5A18}'
. '\x{5A1A}\x{5A1C}\x{5A1F}\x{5A20}\x{5A25}\x{5A29}\x{5A2F}\x{5A35}\x{5A36}'
. '\x{5A3C}\x{5A40}\x{5A41}\x{5A46}\x{5A49}\x{5A5A}\x{5A62}\x{5A66}\x{5A6A}'
. '\x{5A6C}\x{5A7F}\x{5A92}\x{5A9A}\x{5A9B}\x{5ABC}\x{5ABD}\x{5ABE}\x{5AC1}'
. '\x{5AC2}\x{5AC9}\x{5ACB}\x{5ACC}\x{5AD0}\x{5AD6}\x{5AD7}\x{5AE1}\x{5AE3}'
. '\x{5AE6}\x{5AE9}\x{5AFA}\x{5AFB}\x{5B09}\x{5B0B}\x{5B0C}\x{5B16}\x{5B22}'
. '\x{5B2A}\x{5B2C}\x{5B30}\x{5B32}\x{5B36}\x{5B3E}\x{5B40}\x{5B43}\x{5B45}'
. '\x{5B50}\x{5B51}\x{5B54}\x{5B55}\x{5B57}\x{5B58}\x{5B5A}\x{5B5B}\x{5B5C}'
. '\x{5B5D}\x{5B5F}\x{5B63}\x{5B64}\x{5B65}\x{5B66}\x{5B69}\x{5B6B}\x{5B70}'
. '\x{5B71}\x{5B73}\x{5B75}\x{5B78}\x{5B7A}\x{5B80}\x{5B83}\x{5B85}\x{5B87}'
. '\x{5B88}\x{5B89}\x{5B8B}\x{5B8C}\x{5B8D}\x{5B8F}\x{5B95}\x{5B97}\x{5B98}'
. '\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9F}\x{5BA2}\x{5BA3}\x{5BA4}'
. '\x{5BA5}\x{5BA6}\x{5BAE}\x{5BB0}\x{5BB3}\x{5BB4}\x{5BB5}\x{5BB6}\x{5BB8}'
. '\x{5BB9}\x{5BBF}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BC9}'
. '\x{5BCC}\x{5BD0}\x{5BD2}\x{5BD3}\x{5BD4}\x{5BDB}\x{5BDD}\x{5BDE}\x{5BDF}'
. '\x{5BE1}\x{5BE2}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}\x{5BE8}\x{5BE9}\x{5BEB}'
. '\x{5BEE}\x{5BF0}\x{5BF3}\x{5BF5}\x{5BF6}\x{5BF8}\x{5BFA}\x{5BFE}\x{5BFF}'
. '\x{5C01}\x{5C02}\x{5C04}\x{5C05}\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}'
. '\x{5C0B}\x{5C0D}\x{5C0E}\x{5C0F}\x{5C11}\x{5C13}\x{5C16}\x{5C1A}\x{5C20}'
. '\x{5C22}\x{5C24}\x{5C28}\x{5C2D}\x{5C31}\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}'
. '\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}\x{5C41}\x{5C45}\x{5C46}\x{5C48}'
. '\x{5C4A}\x{5C4B}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C53}\x{5C55}'
. '\x{5C5E}\x{5C60}\x{5C61}\x{5C64}\x{5C65}\x{5C6C}\x{5C6E}\x{5C6F}\x{5C71}'
. '\x{5C76}\x{5C79}\x{5C8C}\x{5C90}\x{5C91}\x{5C94}\x{5CA1}\x{5CA8}\x{5CA9}'
. '\x{5CAB}\x{5CAC}\x{5CB1}\x{5CB3}\x{5CB6}\x{5CB7}\x{5CB8}\x{5CBB}\x{5CBC}'
. '\x{5CBE}\x{5CC5}\x{5CC7}\x{5CD9}\x{5CE0}\x{5CE1}\x{5CE8}\x{5CE9}\x{5CEA}'
. '\x{5CED}\x{5CEF}\x{5CF0}\x{5CF6}\x{5CFA}\x{5CFB}\x{5CFD}\x{5D07}\x{5D0B}'
. '\x{5D0E}\x{5D11}\x{5D14}\x{5D15}\x{5D16}\x{5D17}\x{5D18}\x{5D19}\x{5D1A}'
. '\x{5D1B}\x{5D1F}\x{5D22}\x{5D29}\x{5D4B}\x{5D4C}\x{5D4E}\x{5D50}\x{5D52}'
. '\x{5D5C}\x{5D69}\x{5D6C}\x{5D6F}\x{5D73}\x{5D76}\x{5D82}\x{5D84}\x{5D87}'
. '\x{5D8B}\x{5D8C}\x{5D90}\x{5D9D}\x{5DA2}\x{5DAC}\x{5DAE}\x{5DB7}\x{5DBA}'
. '\x{5DBC}\x{5DBD}\x{5DC9}\x{5DCC}\x{5DCD}\x{5DD2}\x{5DD3}\x{5DD6}\x{5DDB}'
. '\x{5DDD}\x{5DDE}\x{5DE1}\x{5DE3}\x{5DE5}\x{5DE6}\x{5DE7}\x{5DE8}\x{5DEB}'
. '\x{5DEE}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DFB}\x{5DFD}'
. '\x{5DFE}\x{5E02}\x{5E03}\x{5E06}\x{5E0B}\x{5E0C}\x{5E11}\x{5E16}\x{5E19}'
. '\x{5E1A}\x{5E1B}\x{5E1D}\x{5E25}\x{5E2B}\x{5E2D}\x{5E2F}\x{5E30}\x{5E33}'
. '\x{5E36}\x{5E37}\x{5E38}\x{5E3D}\x{5E40}\x{5E43}\x{5E44}\x{5E45}\x{5E47}'
. '\x{5E4C}\x{5E4E}\x{5E54}\x{5E55}\x{5E57}\x{5E5F}\x{5E61}\x{5E62}\x{5E63}'
. '\x{5E64}\x{5E72}\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E78}\x{5E79}\x{5E7A}'
. '\x{5E7B}\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E81}\x{5E83}\x{5E84}\x{5E87}'
. '\x{5E8A}\x{5E8F}\x{5E95}\x{5E96}\x{5E97}\x{5E9A}\x{5E9C}\x{5EA0}\x{5EA6}'
. '\x{5EA7}\x{5EAB}\x{5EAD}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EC1}\x{5EC2}'
. '\x{5EC3}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECF}\x{5ED0}\x{5ED3}\x{5ED6}\x{5EDA}'
. '\x{5EDB}\x{5EDD}\x{5EDF}\x{5EE0}\x{5EE1}\x{5EE2}\x{5EE3}\x{5EE8}\x{5EE9}'
. '\x{5EEC}\x{5EF0}\x{5EF1}\x{5EF3}\x{5EF4}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}'
. '\x{5EFB}\x{5EFC}\x{5EFE}\x{5EFF}\x{5F01}\x{5F03}\x{5F04}\x{5F09}\x{5F0A}'
. '\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F10}\x{5F11}\x{5F13}\x{5F14}\x{5F15}'
. '\x{5F16}\x{5F17}\x{5F18}\x{5F1B}\x{5F1F}\x{5F25}\x{5F26}\x{5F27}\x{5F29}'
. '\x{5F2D}\x{5F2F}\x{5F31}\x{5F35}\x{5F37}\x{5F38}\x{5F3C}\x{5F3E}\x{5F41}'
. '\x{5F48}\x{5F4A}\x{5F4C}\x{5F4E}\x{5F51}\x{5F53}\x{5F56}\x{5F57}\x{5F59}'
. '\x{5F5C}\x{5F5D}\x{5F61}\x{5F62}\x{5F66}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}'
. '\x{5F6D}\x{5F70}\x{5F71}\x{5F73}\x{5F77}\x{5F79}\x{5F7C}\x{5F7F}\x{5F80}'
. '\x{5F81}\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F87}\x{5F88}\x{5F8A}\x{5F8B}'
. '\x{5F8C}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F97}\x{5F98}\x{5F99}\x{5F9E}'
. '\x{5FA0}\x{5FA1}\x{5FA8}\x{5FA9}\x{5FAA}\x{5FAD}\x{5FAE}\x{5FB3}\x{5FB4}'
. '\x{5FB9}\x{5FBC}\x{5FBD}\x{5FC3}\x{5FC5}\x{5FCC}\x{5FCD}\x{5FD6}\x{5FD7}'
. '\x{5FD8}\x{5FD9}\x{5FDC}\x{5FDD}\x{5FE0}\x{5FE4}\x{5FEB}\x{5FF0}\x{5FF1}'
. '\x{5FF5}\x{5FF8}\x{5FFB}\x{5FFD}\x{5FFF}\x{600E}\x{600F}\x{6010}\x{6012}'
. '\x{6015}\x{6016}\x{6019}\x{601B}\x{601C}\x{601D}\x{6020}\x{6021}\x{6025}'
. '\x{6026}\x{6027}\x{6028}\x{6029}\x{602A}\x{602B}\x{602F}\x{6031}\x{603A}'
. '\x{6041}\x{6042}\x{6043}\x{6046}\x{604A}\x{604B}\x{604D}\x{6050}\x{6052}'
. '\x{6055}\x{6059}\x{605A}\x{605F}\x{6060}\x{6062}\x{6063}\x{6064}\x{6065}'
. '\x{6068}\x{6069}\x{606A}\x{606B}\x{606C}\x{606D}\x{606F}\x{6070}\x{6075}'
. '\x{6077}\x{6081}\x{6083}\x{6084}\x{6089}\x{608B}\x{608C}\x{608D}\x{6092}'
. '\x{6094}\x{6096}\x{6097}\x{609A}\x{609B}\x{609F}\x{60A0}\x{60A3}\x{60A6}'
. '\x{60A7}\x{60A9}\x{60AA}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B8}'
. '\x{60BC}\x{60BD}\x{60C5}\x{60C6}\x{60C7}\x{60D1}\x{60D3}\x{60D8}\x{60DA}'
. '\x{60DC}\x{60DF}\x{60E0}\x{60E1}\x{60E3}\x{60E7}\x{60E8}\x{60F0}\x{60F1}'
. '\x{60F3}\x{60F4}\x{60F6}\x{60F7}\x{60F9}\x{60FA}\x{60FB}\x{6100}\x{6101}'
. '\x{6103}\x{6106}\x{6108}\x{6109}\x{610D}\x{610E}\x{610F}\x{6115}\x{611A}'
. '\x{611B}\x{611F}\x{6121}\x{6127}\x{6128}\x{612C}\x{6134}\x{613C}\x{613D}'
. '\x{613E}\x{613F}\x{6142}\x{6144}\x{6147}\x{6148}\x{614A}\x{614B}\x{614C}'
. '\x{614D}\x{614E}\x{6153}\x{6155}\x{6158}\x{6159}\x{615A}\x{615D}\x{615F}'
. '\x{6162}\x{6163}\x{6165}\x{6167}\x{6168}\x{616B}\x{616E}\x{616F}\x{6170}'
. '\x{6171}\x{6173}\x{6174}\x{6175}\x{6176}\x{6177}\x{617E}\x{6182}\x{6187}'
. '\x{618A}\x{618E}\x{6190}\x{6191}\x{6194}\x{6196}\x{6199}\x{619A}\x{61A4}'
. '\x{61A7}\x{61A9}\x{61AB}\x{61AC}\x{61AE}\x{61B2}\x{61B6}\x{61BA}\x{61BE}'
. '\x{61C3}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}'
. '\x{61D0}\x{61E3}\x{61E6}\x{61F2}\x{61F4}\x{61F6}\x{61F7}\x{61F8}\x{61FA}'
. '\x{61FC}\x{61FD}\x{61FE}\x{61FF}\x{6200}\x{6208}\x{6209}\x{620A}\x{620C}'
. '\x{620D}\x{620E}\x{6210}\x{6211}\x{6212}\x{6214}\x{6216}\x{621A}\x{621B}'
. '\x{621D}\x{621E}\x{621F}\x{6221}\x{6226}\x{622A}\x{622E}\x{622F}\x{6230}'
. '\x{6232}\x{6233}\x{6234}\x{6238}\x{623B}\x{623F}\x{6240}\x{6241}\x{6247}'
. '\x{6248}\x{6249}\x{624B}\x{624D}\x{624E}\x{6253}\x{6255}\x{6258}\x{625B}'
. '\x{625E}\x{6260}\x{6263}\x{6268}\x{626E}\x{6271}\x{6276}\x{6279}\x{627C}'
. '\x{627E}\x{627F}\x{6280}\x{6282}\x{6283}\x{6284}\x{6289}\x{628A}\x{6291}'
. '\x{6292}\x{6293}\x{6294}\x{6295}\x{6296}\x{6297}\x{6298}\x{629B}\x{629C}'
. '\x{629E}\x{62AB}\x{62AC}\x{62B1}\x{62B5}\x{62B9}\x{62BB}\x{62BC}\x{62BD}'
. '\x{62C2}\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CC}\x{62CD}'
. '\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D7}\x{62D8}\x{62D9}'
. '\x{62DB}\x{62DC}\x{62DD}\x{62E0}\x{62E1}\x{62EC}\x{62ED}\x{62EE}\x{62EF}'
. '\x{62F1}\x{62F3}\x{62F5}\x{62F6}\x{62F7}\x{62FE}\x{62FF}\x{6301}\x{6302}'
. '\x{6307}\x{6308}\x{6309}\x{630C}\x{6311}\x{6319}\x{631F}\x{6327}\x{6328}'
. '\x{632B}\x{632F}\x{633A}\x{633D}\x{633E}\x{633F}\x{6349}\x{634C}\x{634D}'
. '\x{634F}\x{6350}\x{6355}\x{6357}\x{635C}\x{6367}\x{6368}\x{6369}\x{636B}'
. '\x{636E}\x{6372}\x{6376}\x{6377}\x{637A}\x{637B}\x{6380}\x{6383}\x{6388}'
. '\x{6389}\x{638C}\x{638E}\x{638F}\x{6392}\x{6396}\x{6398}\x{639B}\x{639F}'
. '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A5}\x{63A7}\x{63A8}\x{63A9}\x{63AA}'
. '\x{63AB}\x{63AC}\x{63B2}\x{63B4}\x{63B5}\x{63BB}\x{63BE}\x{63C0}\x{63C3}'
. '\x{63C4}\x{63C6}\x{63C9}\x{63CF}\x{63D0}\x{63D2}\x{63D6}\x{63DA}\x{63DB}'
. '\x{63E1}\x{63E3}\x{63E9}\x{63EE}\x{63F4}\x{63F6}\x{63FA}\x{6406}\x{640D}'
. '\x{640F}\x{6413}\x{6416}\x{6417}\x{641C}\x{6426}\x{6428}\x{642C}\x{642D}'
. '\x{6434}\x{6436}\x{643A}\x{643E}\x{6442}\x{644E}\x{6458}\x{6467}\x{6469}'
. '\x{646F}\x{6476}\x{6478}\x{647A}\x{6483}\x{6488}\x{6492}\x{6493}\x{6495}'
. '\x{649A}\x{649E}\x{64A4}\x{64A5}\x{64A9}\x{64AB}\x{64AD}\x{64AE}\x{64B0}'
. '\x{64B2}\x{64B9}\x{64BB}\x{64BC}\x{64C1}\x{64C2}\x{64C5}\x{64C7}\x{64CD}'
. '\x{64D2}\x{64D4}\x{64D8}\x{64DA}\x{64E0}\x{64E1}\x{64E2}\x{64E3}\x{64E6}'
. '\x{64E7}\x{64EC}\x{64EF}\x{64F1}\x{64F2}\x{64F4}\x{64F6}\x{64FA}\x{64FD}'
. '\x{64FE}\x{6500}\x{6505}\x{6518}\x{651C}\x{651D}\x{6523}\x{6524}\x{652A}'
. '\x{652B}\x{652C}\x{652F}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}'
. '\x{653B}\x{653E}\x{653F}\x{6545}\x{6548}\x{654D}\x{654F}\x{6551}\x{6555}'
. '\x{6556}\x{6557}\x{6558}\x{6559}\x{655D}\x{655E}\x{6562}\x{6563}\x{6566}'
. '\x{656C}\x{6570}\x{6572}\x{6574}\x{6575}\x{6577}\x{6578}\x{6582}\x{6583}'
. '\x{6587}\x{6588}\x{6589}\x{658C}\x{658E}\x{6590}\x{6591}\x{6597}\x{6599}'
. '\x{659B}\x{659C}\x{659F}\x{65A1}\x{65A4}\x{65A5}\x{65A7}\x{65AB}\x{65AC}'
. '\x{65AD}\x{65AF}\x{65B0}\x{65B7}\x{65B9}\x{65BC}\x{65BD}\x{65C1}\x{65C3}'
. '\x{65C4}\x{65C5}\x{65C6}\x{65CB}\x{65CC}\x{65CF}\x{65D2}\x{65D7}\x{65D9}'
. '\x{65DB}\x{65E0}\x{65E1}\x{65E2}\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}'
. '\x{65EC}\x{65ED}\x{65F1}\x{65FA}\x{65FB}\x{6602}\x{6603}\x{6606}\x{6607}'
. '\x{660A}\x{660C}\x{660E}\x{660F}\x{6613}\x{6614}\x{661C}\x{661F}\x{6620}'
. '\x{6625}\x{6627}\x{6628}\x{662D}\x{662F}\x{6634}\x{6635}\x{6636}\x{663C}'
. '\x{663F}\x{6641}\x{6642}\x{6643}\x{6644}\x{6649}\x{664B}\x{664F}\x{6652}'
. '\x{665D}\x{665E}\x{665F}\x{6662}\x{6664}\x{6666}\x{6667}\x{6668}\x{6669}'
. '\x{666E}\x{666F}\x{6670}\x{6674}\x{6676}\x{667A}\x{6681}\x{6683}\x{6684}'
. '\x{6687}\x{6688}\x{6689}\x{668E}\x{6691}\x{6696}\x{6697}\x{6698}\x{669D}'
. '\x{66A2}\x{66A6}\x{66AB}\x{66AE}\x{66B4}\x{66B8}\x{66B9}\x{66BC}\x{66BE}'
. '\x{66C1}\x{66C4}\x{66C7}\x{66C9}\x{66D6}\x{66D9}\x{66DA}\x{66DC}\x{66DD}'
. '\x{66E0}\x{66E6}\x{66E9}\x{66F0}\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F7}'
. '\x{66F8}\x{66F9}\x{66FC}\x{66FD}\x{66FE}\x{66FF}\x{6700}\x{6703}\x{6708}'
. '\x{6709}\x{670B}\x{670D}\x{670F}\x{6714}\x{6715}\x{6716}\x{6717}\x{671B}'
. '\x{671D}\x{671E}\x{671F}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}'
. '\x{672D}\x{672E}\x{6731}\x{6734}\x{6736}\x{6737}\x{6738}\x{673A}\x{673D}'
. '\x{673F}\x{6741}\x{6746}\x{6749}\x{674E}\x{674F}\x{6750}\x{6751}\x{6753}'
. '\x{6756}\x{6759}\x{675C}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}'
. '\x{6764}\x{6765}\x{676A}\x{676D}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}'
. '\x{6775}\x{6777}\x{677C}\x{677E}\x{677F}\x{6785}\x{6787}\x{6789}\x{678B}'
. '\x{678C}\x{6790}\x{6795}\x{6797}\x{679A}\x{679C}\x{679D}\x{67A0}\x{67A1}'
. '\x{67A2}\x{67A6}\x{67A9}\x{67AF}\x{67B3}\x{67B4}\x{67B6}\x{67B7}\x{67B8}'
. '\x{67B9}\x{67C1}\x{67C4}\x{67C6}\x{67CA}\x{67CE}\x{67CF}\x{67D0}\x{67D1}'
. '\x{67D3}\x{67D4}\x{67D8}\x{67DA}\x{67DD}\x{67DE}\x{67E2}\x{67E4}\x{67E7}'
. '\x{67E9}\x{67EC}\x{67EE}\x{67EF}\x{67F1}\x{67F3}\x{67F4}\x{67F5}\x{67FB}'
. '\x{67FE}\x{67FF}\x{6802}\x{6803}\x{6804}\x{6813}\x{6816}\x{6817}\x{681E}'
. '\x{6821}\x{6822}\x{6829}\x{682A}\x{682B}\x{6832}\x{6834}\x{6838}\x{6839}'
. '\x{683C}\x{683D}\x{6840}\x{6841}\x{6842}\x{6843}\x{6846}\x{6848}\x{684D}'
. '\x{684E}\x{6850}\x{6851}\x{6853}\x{6854}\x{6859}\x{685C}\x{685D}\x{685F}'
. '\x{6863}\x{6867}\x{6874}\x{6876}\x{6877}\x{687E}\x{687F}\x{6881}\x{6883}'
. '\x{6885}\x{688D}\x{688F}\x{6893}\x{6894}\x{6897}\x{689B}\x{689D}\x{689F}'
. '\x{68A0}\x{68A2}\x{68A6}\x{68A7}\x{68A8}\x{68AD}\x{68AF}\x{68B0}\x{68B1}'
. '\x{68B3}\x{68B5}\x{68B6}\x{68B9}\x{68BA}\x{68BC}\x{68C4}\x{68C6}\x{68C9}'
. '\x{68CA}\x{68CB}\x{68CD}\x{68D2}\x{68D4}\x{68D5}\x{68D7}\x{68D8}\x{68DA}'
. '\x{68DF}\x{68E0}\x{68E1}\x{68E3}\x{68E7}\x{68EE}\x{68EF}\x{68F2}\x{68F9}'
. '\x{68FA}\x{6900}\x{6901}\x{6904}\x{6905}\x{6908}\x{690B}\x{690C}\x{690D}'
. '\x{690E}\x{690F}\x{6912}\x{6919}\x{691A}\x{691B}\x{691C}\x{6921}\x{6922}'
. '\x{6923}\x{6925}\x{6926}\x{6928}\x{692A}\x{6930}\x{6934}\x{6936}\x{6939}'
. '\x{693D}\x{693F}\x{694A}\x{6953}\x{6954}\x{6955}\x{6959}\x{695A}\x{695C}'
. '\x{695D}\x{695E}\x{6960}\x{6961}\x{6962}\x{696A}\x{696B}\x{696D}\x{696E}'
. '\x{696F}\x{6973}\x{6974}\x{6975}\x{6977}\x{6978}\x{6979}\x{697C}\x{697D}'
. '\x{697E}\x{6981}\x{6982}\x{698A}\x{698E}\x{6991}\x{6994}\x{6995}\x{699B}'
. '\x{699C}\x{69A0}\x{69A7}\x{69AE}\x{69B1}\x{69B2}\x{69B4}\x{69BB}\x{69BE}'
. '\x{69BF}\x{69C1}\x{69C3}\x{69C7}\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}'
. '\x{69D0}\x{69D3}\x{69D8}\x{69D9}\x{69DD}\x{69DE}\x{69E7}\x{69E8}\x{69EB}'
. '\x{69ED}\x{69F2}\x{69F9}\x{69FB}\x{69FD}\x{69FF}\x{6A02}\x{6A05}\x{6A0A}'
. '\x{6A0B}\x{6A0C}\x{6A12}\x{6A13}\x{6A14}\x{6A17}\x{6A19}\x{6A1B}\x{6A1E}'
. '\x{6A1F}\x{6A21}\x{6A22}\x{6A23}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2E}\x{6A35}'
. '\x{6A36}\x{6A38}\x{6A39}\x{6A3A}\x{6A3D}\x{6A44}\x{6A47}\x{6A48}\x{6A4B}'
. '\x{6A58}\x{6A59}\x{6A5F}\x{6A61}\x{6A62}\x{6A66}\x{6A72}\x{6A78}\x{6A7F}'
. '\x{6A80}\x{6A84}\x{6A8D}\x{6A8E}\x{6A90}\x{6A97}\x{6A9C}\x{6AA0}\x{6AA2}'
. '\x{6AA3}\x{6AAA}\x{6AAC}\x{6AAE}\x{6AB3}\x{6AB8}\x{6ABB}\x{6AC1}\x{6AC2}'
. '\x{6AC3}\x{6AD1}\x{6AD3}\x{6ADA}\x{6ADB}\x{6ADE}\x{6ADF}\x{6AE8}\x{6AEA}'
. '\x{6AFA}\x{6AFB}\x{6B04}\x{6B05}\x{6B0A}\x{6B12}\x{6B16}\x{6B1D}\x{6B1F}'
. '\x{6B20}\x{6B21}\x{6B23}\x{6B27}\x{6B32}\x{6B37}\x{6B38}\x{6B39}\x{6B3A}'
. '\x{6B3D}\x{6B3E}\x{6B43}\x{6B47}\x{6B49}\x{6B4C}\x{6B4E}\x{6B50}\x{6B53}'
. '\x{6B54}\x{6B59}\x{6B5B}\x{6B5F}\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B66}'
. '\x{6B69}\x{6B6A}\x{6B6F}\x{6B73}\x{6B74}\x{6B78}\x{6B79}\x{6B7B}\x{6B7F}'
. '\x{6B80}\x{6B83}\x{6B84}\x{6B86}\x{6B89}\x{6B8A}\x{6B8B}\x{6B8D}\x{6B95}'
. '\x{6B96}\x{6B98}\x{6B9E}\x{6BA4}\x{6BAA}\x{6BAB}\x{6BAF}\x{6BB1}\x{6BB2}'
. '\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB7}\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBF}\x{6BC0}'
. '\x{6BC5}\x{6BC6}\x{6BCB}\x{6BCD}\x{6BCE}\x{6BD2}\x{6BD3}\x{6BD4}\x{6BD8}'
. '\x{6BDB}\x{6BDF}\x{6BEB}\x{6BEC}\x{6BEF}\x{6BF3}\x{6C08}\x{6C0F}\x{6C11}'
. '\x{6C13}\x{6C14}\x{6C17}\x{6C1B}\x{6C23}\x{6C24}\x{6C34}\x{6C37}\x{6C38}'
. '\x{6C3E}\x{6C40}\x{6C41}\x{6C42}\x{6C4E}\x{6C50}\x{6C55}\x{6C57}\x{6C5A}'
. '\x{6C5D}\x{6C5E}\x{6C5F}\x{6C60}\x{6C62}\x{6C68}\x{6C6A}\x{6C70}\x{6C72}'
. '\x{6C73}\x{6C7A}\x{6C7D}\x{6C7E}\x{6C81}\x{6C82}\x{6C83}\x{6C88}\x{6C8C}'
. '\x{6C8D}\x{6C90}\x{6C92}\x{6C93}\x{6C96}\x{6C99}\x{6C9A}\x{6C9B}\x{6CA1}'
. '\x{6CA2}\x{6CAB}\x{6CAE}\x{6CB1}\x{6CB3}\x{6CB8}\x{6CB9}\x{6CBA}\x{6CBB}'
. '\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC1}\x{6CC4}\x{6CC5}\x{6CC9}\x{6CCA}'
. '\x{6CCC}\x{6CD3}\x{6CD5}\x{6CD7}\x{6CD9}\x{6CDB}\x{6CDD}\x{6CE1}\x{6CE2}'
. '\x{6CE3}\x{6CE5}\x{6CE8}\x{6CEA}\x{6CEF}\x{6CF0}\x{6CF1}\x{6CF3}\x{6D0B}'
. '\x{6D0C}\x{6D12}\x{6D17}\x{6D19}\x{6D1B}\x{6D1E}\x{6D1F}\x{6D25}\x{6D29}'
. '\x{6D2A}\x{6D2B}\x{6D32}\x{6D33}\x{6D35}\x{6D36}\x{6D38}\x{6D3B}\x{6D3D}'
. '\x{6D3E}\x{6D41}\x{6D44}\x{6D45}\x{6D59}\x{6D5A}\x{6D5C}\x{6D63}\x{6D64}'
. '\x{6D66}\x{6D69}\x{6D6A}\x{6D6C}\x{6D6E}\x{6D74}\x{6D77}\x{6D78}\x{6D79}'
. '\x{6D85}\x{6D88}\x{6D8C}\x{6D8E}\x{6D93}\x{6D95}\x{6D99}\x{6D9B}\x{6D9C}'
. '\x{6DAF}\x{6DB2}\x{6DB5}\x{6DB8}\x{6DBC}\x{6DC0}\x{6DC5}\x{6DC6}\x{6DC7}'
. '\x{6DCB}\x{6DCC}\x{6DD1}\x{6DD2}\x{6DD5}\x{6DD8}\x{6DD9}\x{6DDE}\x{6DE1}'
. '\x{6DE4}\x{6DE6}\x{6DE8}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DEE}\x{6DF1}\x{6DF3}'
. '\x{6DF5}\x{6DF7}\x{6DF9}\x{6DFA}\x{6DFB}\x{6E05}\x{6E07}\x{6E08}\x{6E09}'
. '\x{6E0A}\x{6E0B}\x{6E13}\x{6E15}\x{6E19}\x{6E1A}\x{6E1B}\x{6E1D}\x{6E1F}'
. '\x{6E20}\x{6E21}\x{6E23}\x{6E24}\x{6E25}\x{6E26}\x{6E29}\x{6E2B}\x{6E2C}'
. '\x{6E2D}\x{6E2E}\x{6E2F}\x{6E38}\x{6E3A}\x{6E3E}\x{6E43}\x{6E4A}\x{6E4D}'
. '\x{6E4E}\x{6E56}\x{6E58}\x{6E5B}\x{6E5F}\x{6E67}\x{6E6B}\x{6E6E}\x{6E6F}'
. '\x{6E72}\x{6E76}\x{6E7E}\x{6E7F}\x{6E80}\x{6E82}\x{6E8C}\x{6E8F}\x{6E90}'
. '\x{6E96}\x{6E98}\x{6E9C}\x{6E9D}\x{6E9F}\x{6EA2}\x{6EA5}\x{6EAA}\x{6EAF}'
. '\x{6EB2}\x{6EB6}\x{6EB7}\x{6EBA}\x{6EBD}\x{6EC2}\x{6EC4}\x{6EC5}\x{6EC9}'
. '\x{6ECB}\x{6ECC}\x{6ED1}\x{6ED3}\x{6ED4}\x{6ED5}\x{6EDD}\x{6EDE}\x{6EEC}'
. '\x{6EEF}\x{6EF2}\x{6EF4}\x{6EF7}\x{6EF8}\x{6EFE}\x{6EFF}\x{6F01}\x{6F02}'
. '\x{6F06}\x{6F09}\x{6F0F}\x{6F11}\x{6F13}\x{6F14}\x{6F15}\x{6F20}\x{6F22}'
. '\x{6F23}\x{6F2B}\x{6F2C}\x{6F31}\x{6F32}\x{6F38}\x{6F3E}\x{6F3F}\x{6F41}'
. '\x{6F45}\x{6F54}\x{6F58}\x{6F5B}\x{6F5C}\x{6F5F}\x{6F64}\x{6F66}\x{6F6D}'
. '\x{6F6E}\x{6F6F}\x{6F70}\x{6F74}\x{6F78}\x{6F7A}\x{6F7C}\x{6F80}\x{6F81}'
. '\x{6F82}\x{6F84}\x{6F86}\x{6F8E}\x{6F91}\x{6F97}\x{6FA1}\x{6FA3}\x{6FA4}'
. '\x{6FAA}\x{6FB1}\x{6FB3}\x{6FB9}\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC6}'
. '\x{6FD4}\x{6FD5}\x{6FD8}\x{6FDB}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE4}\x{6FEB}'
. '\x{6FEC}\x{6FEE}\x{6FEF}\x{6FF1}\x{6FF3}\x{6FF6}\x{6FFA}\x{6FFE}\x{7001}'
. '\x{7009}\x{700B}\x{700F}\x{7011}\x{7015}\x{7018}\x{701A}\x{701B}\x{701D}'
. '\x{701E}\x{701F}\x{7026}\x{7027}\x{702C}\x{7030}\x{7032}\x{703E}\x{704C}'
. '\x{7051}\x{7058}\x{7063}\x{706B}\x{706F}\x{7070}\x{7078}\x{707C}\x{707D}'
. '\x{7089}\x{708A}\x{708E}\x{7092}\x{7099}\x{70AC}\x{70AD}\x{70AE}\x{70AF}'
. '\x{70B3}\x{70B8}\x{70B9}\x{70BA}\x{70C8}\x{70CB}\x{70CF}\x{70D9}\x{70DD}'
. '\x{70DF}\x{70F1}\x{70F9}\x{70FD}\x{7109}\x{7114}\x{7119}\x{711A}\x{711C}'
. '\x{7121}\x{7126}\x{7136}\x{713C}\x{7149}\x{714C}\x{714E}\x{7155}\x{7156}'
. '\x{7159}\x{7162}\x{7164}\x{7165}\x{7166}\x{7167}\x{7169}\x{716C}\x{716E}'
. '\x{717D}\x{7184}\x{7188}\x{718A}\x{718F}\x{7194}\x{7195}\x{7199}\x{719F}'
. '\x{71A8}\x{71AC}\x{71B1}\x{71B9}\x{71BE}\x{71C3}\x{71C8}\x{71C9}\x{71CE}'
. '\x{71D0}\x{71D2}\x{71D4}\x{71D5}\x{71D7}\x{71DF}\x{71E0}\x{71E5}\x{71E6}'
. '\x{71E7}\x{71EC}\x{71ED}\x{71EE}\x{71F5}\x{71F9}\x{71FB}\x{71FC}\x{71FF}'
. '\x{7206}\x{720D}\x{7210}\x{721B}\x{7228}\x{722A}\x{722C}\x{722D}\x{7230}'
. '\x{7232}\x{7235}\x{7236}\x{723A}\x{723B}\x{723C}\x{723D}\x{723E}\x{723F}'
. '\x{7240}\x{7246}\x{7247}\x{7248}\x{724B}\x{724C}\x{7252}\x{7258}\x{7259}'
. '\x{725B}\x{725D}\x{725F}\x{7261}\x{7262}\x{7267}\x{7269}\x{7272}\x{7274}'
. '\x{7279}\x{727D}\x{727E}\x{7280}\x{7281}\x{7282}\x{7287}\x{7292}\x{7296}'
. '\x{72A0}\x{72A2}\x{72A7}\x{72AC}\x{72AF}\x{72B2}\x{72B6}\x{72B9}\x{72C2}'
. '\x{72C3}\x{72C4}\x{72C6}\x{72CE}\x{72D0}\x{72D2}\x{72D7}\x{72D9}\x{72DB}'
. '\x{72E0}\x{72E1}\x{72E2}\x{72E9}\x{72EC}\x{72ED}\x{72F7}\x{72F8}\x{72F9}'
. '\x{72FC}\x{72FD}\x{730A}\x{7316}\x{7317}\x{731B}\x{731C}\x{731D}\x{731F}'
. '\x{7325}\x{7329}\x{732A}\x{732B}\x{732E}\x{732F}\x{7334}\x{7336}\x{7337}'
. '\x{733E}\x{733F}\x{7344}\x{7345}\x{734E}\x{734F}\x{7357}\x{7363}\x{7368}'
. '\x{736A}\x{7370}\x{7372}\x{7375}\x{7378}\x{737A}\x{737B}\x{7384}\x{7387}'
. '\x{7389}\x{738B}\x{7396}\x{73A9}\x{73B2}\x{73B3}\x{73BB}\x{73C0}\x{73C2}'
. '\x{73C8}\x{73CA}\x{73CD}\x{73CE}\x{73DE}\x{73E0}\x{73E5}\x{73EA}\x{73ED}'
. '\x{73EE}\x{73F1}\x{73F8}\x{73FE}\x{7403}\x{7405}\x{7406}\x{7409}\x{7422}'
. '\x{7425}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{743A}\x{743F}\x{7441}'
. '\x{7455}\x{7459}\x{745A}\x{745B}\x{745C}\x{745E}\x{745F}\x{7460}\x{7463}'
. '\x{7464}\x{7469}\x{746A}\x{746F}\x{7470}\x{7473}\x{7476}\x{747E}\x{7483}'
. '\x{748B}\x{749E}\x{74A2}\x{74A7}\x{74B0}\x{74BD}\x{74CA}\x{74CF}\x{74D4}'
. '\x{74DC}\x{74E0}\x{74E2}\x{74E3}\x{74E6}\x{74E7}\x{74E9}\x{74EE}\x{74F0}'
. '\x{74F1}\x{74F2}\x{74F6}\x{74F7}\x{74F8}\x{7503}\x{7504}\x{7505}\x{750C}'
. '\x{750D}\x{750E}\x{7511}\x{7513}\x{7515}\x{7518}\x{751A}\x{751C}\x{751E}'
. '\x{751F}\x{7523}\x{7525}\x{7526}\x{7528}\x{752B}\x{752C}\x{7530}\x{7531}'
. '\x{7532}\x{7533}\x{7537}\x{7538}\x{753A}\x{753B}\x{753C}\x{7544}\x{7546}'
. '\x{7549}\x{754A}\x{754B}\x{754C}\x{754D}\x{754F}\x{7551}\x{7554}\x{7559}'
. '\x{755A}\x{755B}\x{755C}\x{755D}\x{7560}\x{7562}\x{7564}\x{7565}\x{7566}'
. '\x{7567}\x{7569}\x{756A}\x{756B}\x{756D}\x{7570}\x{7573}\x{7574}\x{7576}'
. '\x{7577}\x{7578}\x{757F}\x{7582}\x{7586}\x{7587}\x{7589}\x{758A}\x{758B}'
. '\x{758E}\x{758F}\x{7591}\x{7594}\x{759A}\x{759D}\x{75A3}\x{75A5}\x{75AB}'
. '\x{75B1}\x{75B2}\x{75B3}\x{75B5}\x{75B8}\x{75B9}\x{75BC}\x{75BD}\x{75BE}'
. '\x{75C2}\x{75C3}\x{75C5}\x{75C7}\x{75CA}\x{75CD}\x{75D2}\x{75D4}\x{75D5}'
. '\x{75D8}\x{75D9}\x{75DB}\x{75DE}\x{75E2}\x{75E3}\x{75E9}\x{75F0}\x{75F2}'
. '\x{75F3}\x{75F4}\x{75FA}\x{75FC}\x{75FE}\x{75FF}\x{7601}\x{7609}\x{760B}'
. '\x{760D}\x{761F}\x{7620}\x{7621}\x{7622}\x{7624}\x{7627}\x{7630}\x{7634}'
. '\x{763B}\x{7642}\x{7646}\x{7647}\x{7648}\x{764C}\x{7652}\x{7656}\x{7658}'
. '\x{765C}\x{7661}\x{7662}\x{7667}\x{7668}\x{7669}\x{766A}\x{766C}\x{7670}'
. '\x{7672}\x{7676}\x{7678}\x{767A}\x{767B}\x{767C}\x{767D}\x{767E}\x{7680}'
. '\x{7683}\x{7684}\x{7686}\x{7687}\x{7688}\x{768B}\x{768E}\x{7690}\x{7693}'
. '\x{7696}\x{7699}\x{769A}\x{76AE}\x{76B0}\x{76B4}\x{76B7}\x{76B8}\x{76B9}'
. '\x{76BA}\x{76BF}\x{76C2}\x{76C3}\x{76C6}\x{76C8}\x{76CA}\x{76CD}\x{76D2}'
. '\x{76D6}\x{76D7}\x{76DB}\x{76DC}\x{76DE}\x{76DF}\x{76E1}\x{76E3}\x{76E4}'
. '\x{76E5}\x{76E7}\x{76EA}\x{76EE}\x{76F2}\x{76F4}\x{76F8}\x{76FB}\x{76FE}'
. '\x{7701}\x{7704}\x{7707}\x{7708}\x{7709}\x{770B}\x{770C}\x{771B}\x{771E}'
. '\x{771F}\x{7720}\x{7724}\x{7725}\x{7726}\x{7729}\x{7737}\x{7738}\x{773A}'
. '\x{773C}\x{7740}\x{7747}\x{775A}\x{775B}\x{7761}\x{7763}\x{7765}\x{7766}'
. '\x{7768}\x{776B}\x{7779}\x{777E}\x{777F}\x{778B}\x{778E}\x{7791}\x{779E}'
. '\x{77A0}\x{77A5}\x{77AC}\x{77AD}\x{77B0}\x{77B3}\x{77B6}\x{77B9}\x{77BB}'
. '\x{77BC}\x{77BD}\x{77BF}\x{77C7}\x{77CD}\x{77D7}\x{77DA}\x{77DB}\x{77DC}'
. '\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E9}\x{77ED}\x{77EE}\x{77EF}\x{77F3}'
. '\x{77FC}\x{7802}\x{780C}\x{7812}\x{7814}\x{7815}\x{7820}\x{7825}\x{7826}'
. '\x{7827}\x{7832}\x{7834}\x{783A}\x{783F}\x{7845}\x{785D}\x{786B}\x{786C}'
. '\x{786F}\x{7872}\x{7874}\x{787C}\x{7881}\x{7886}\x{7887}\x{788C}\x{788D}'
. '\x{788E}\x{7891}\x{7893}\x{7895}\x{7897}\x{789A}\x{78A3}\x{78A7}\x{78A9}'
. '\x{78AA}\x{78AF}\x{78B5}\x{78BA}\x{78BC}\x{78BE}\x{78C1}\x{78C5}\x{78C6}'
. '\x{78CA}\x{78CB}\x{78D0}\x{78D1}\x{78D4}\x{78DA}\x{78E7}\x{78E8}\x{78EC}'
. '\x{78EF}\x{78F4}\x{78FD}\x{7901}\x{7907}\x{790E}\x{7911}\x{7912}\x{7919}'
. '\x{7926}\x{792A}\x{792B}\x{792C}\x{793A}\x{793C}\x{793E}\x{7940}\x{7941}'
. '\x{7947}\x{7948}\x{7949}\x{7950}\x{7953}\x{7955}\x{7956}\x{7957}\x{795A}'
. '\x{795D}\x{795E}\x{795F}\x{7960}\x{7962}\x{7965}\x{7968}\x{796D}\x{7977}'
. '\x{797A}\x{797F}\x{7980}\x{7981}\x{7984}\x{7985}\x{798A}\x{798D}\x{798E}'
. '\x{798F}\x{799D}\x{79A6}\x{79A7}\x{79AA}\x{79AE}\x{79B0}\x{79B3}\x{79B9}'
. '\x{79BA}\x{79BD}\x{79BE}\x{79BF}\x{79C0}\x{79C1}\x{79C9}\x{79CB}\x{79D1}'
. '\x{79D2}\x{79D5}\x{79D8}\x{79DF}\x{79E1}\x{79E3}\x{79E4}\x{79E6}\x{79E7}'
. '\x{79E9}\x{79EC}\x{79F0}\x{79FB}\x{7A00}\x{7A08}\x{7A0B}\x{7A0D}\x{7A0E}'
. '\x{7A14}\x{7A17}\x{7A18}\x{7A19}\x{7A1A}\x{7A1C}\x{7A1F}\x{7A20}\x{7A2E}'
. '\x{7A31}\x{7A32}\x{7A37}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}'
. '\x{7A42}\x{7A43}\x{7A46}\x{7A49}\x{7A4D}\x{7A4E}\x{7A4F}\x{7A50}\x{7A57}'
. '\x{7A61}\x{7A62}\x{7A63}\x{7A69}\x{7A6B}\x{7A70}\x{7A74}\x{7A76}\x{7A79}'
. '\x{7A7A}\x{7A7D}\x{7A7F}\x{7A81}\x{7A83}\x{7A84}\x{7A88}\x{7A92}\x{7A93}'
. '\x{7A95}\x{7A96}\x{7A97}\x{7A98}\x{7A9F}\x{7AA9}\x{7AAA}\x{7AAE}\x{7AAF}'
. '\x{7AB0}\x{7AB6}\x{7ABA}\x{7ABF}\x{7AC3}\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}'
. '\x{7ACA}\x{7ACB}\x{7ACD}\x{7ACF}\x{7AD2}\x{7AD3}\x{7AD5}\x{7AD9}\x{7ADA}'
. '\x{7ADC}\x{7ADD}\x{7ADF}\x{7AE0}\x{7AE1}\x{7AE2}\x{7AE3}\x{7AE5}\x{7AE6}'
. '\x{7AEA}\x{7AED}\x{7AEF}\x{7AF0}\x{7AF6}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFF}'
. '\x{7B02}\x{7B04}\x{7B06}\x{7B08}\x{7B0A}\x{7B0B}\x{7B0F}\x{7B11}\x{7B18}'
. '\x{7B19}\x{7B1B}\x{7B1E}\x{7B20}\x{7B25}\x{7B26}\x{7B28}\x{7B2C}\x{7B33}'
. '\x{7B35}\x{7B36}\x{7B39}\x{7B45}\x{7B46}\x{7B48}\x{7B49}\x{7B4B}\x{7B4C}'
. '\x{7B4D}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B56}\x{7B5D}\x{7B65}'
. '\x{7B67}\x{7B6C}\x{7B6E}\x{7B70}\x{7B71}\x{7B74}\x{7B75}\x{7B7A}\x{7B86}'
. '\x{7B87}\x{7B8B}\x{7B8D}\x{7B8F}\x{7B92}\x{7B94}\x{7B95}\x{7B97}\x{7B98}'
. '\x{7B99}\x{7B9A}\x{7B9C}\x{7B9D}\x{7B9F}\x{7BA1}\x{7BAA}\x{7BAD}\x{7BB1}'
. '\x{7BB4}\x{7BB8}\x{7BC0}\x{7BC1}\x{7BC4}\x{7BC6}\x{7BC7}\x{7BC9}\x{7BCB}'
. '\x{7BCC}\x{7BCF}\x{7BDD}\x{7BE0}\x{7BE4}\x{7BE5}\x{7BE6}\x{7BE9}\x{7BED}'
. '\x{7BF3}\x{7BF6}\x{7BF7}\x{7C00}\x{7C07}\x{7C0D}\x{7C11}\x{7C12}\x{7C13}'
. '\x{7C14}\x{7C17}\x{7C1F}\x{7C21}\x{7C23}\x{7C27}\x{7C2A}\x{7C2B}\x{7C37}'
. '\x{7C38}\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C43}\x{7C4C}\x{7C4D}\x{7C4F}'
. '\x{7C50}\x{7C54}\x{7C56}\x{7C58}\x{7C5F}\x{7C60}\x{7C64}\x{7C65}\x{7C6C}'
. '\x{7C73}\x{7C75}\x{7C7E}\x{7C81}\x{7C82}\x{7C83}\x{7C89}\x{7C8B}\x{7C8D}'
. '\x{7C90}\x{7C92}\x{7C95}\x{7C97}\x{7C98}\x{7C9B}\x{7C9F}\x{7CA1}\x{7CA2}'
. '\x{7CA4}\x{7CA5}\x{7CA7}\x{7CA8}\x{7CAB}\x{7CAD}\x{7CAE}\x{7CB1}\x{7CB2}'
. '\x{7CB3}\x{7CB9}\x{7CBD}\x{7CBE}\x{7CC0}\x{7CC2}\x{7CC5}\x{7CCA}\x{7CCE}'
. '\x{7CD2}\x{7CD6}\x{7CD8}\x{7CDC}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE7}'
. '\x{7CEF}\x{7CF2}\x{7CF4}\x{7CF6}\x{7CF8}\x{7CFA}\x{7CFB}\x{7CFE}\x{7D00}'
. '\x{7D02}\x{7D04}\x{7D05}\x{7D06}\x{7D0A}\x{7D0B}\x{7D0D}\x{7D10}\x{7D14}'
. '\x{7D15}\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D20}\x{7D21}'
. '\x{7D22}\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D32}\x{7D33}\x{7D35}'
. '\x{7D39}\x{7D3A}\x{7D3F}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}\x{7D4B}'
. '\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D56}\x{7D5B}\x{7D5E}\x{7D61}\x{7D62}'
. '\x{7D63}\x{7D66}\x{7D68}\x{7D6E}\x{7D71}\x{7D72}\x{7D73}\x{7D75}\x{7D76}'
. '\x{7D79}\x{7D7D}\x{7D89}\x{7D8F}\x{7D93}\x{7D99}\x{7D9A}\x{7D9B}\x{7D9C}'
. '\x{7D9F}\x{7DA2}\x{7DA3}\x{7DAB}\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}'
. '\x{7DB1}\x{7DB2}\x{7DB4}\x{7DB5}\x{7DB8}\x{7DBA}\x{7DBB}\x{7DBD}\x{7DBE}'
. '\x{7DBF}\x{7DC7}\x{7DCA}\x{7DCB}\x{7DCF}\x{7DD1}\x{7DD2}\x{7DD5}\x{7DD8}'
. '\x{7DDA}\x{7DDC}\x{7DDD}\x{7DDE}\x{7DE0}\x{7DE1}\x{7DE4}\x{7DE8}\x{7DE9}'
. '\x{7DEC}\x{7DEF}\x{7DF2}\x{7DF4}\x{7DFB}\x{7E01}\x{7E04}\x{7E05}\x{7E09}'
. '\x{7E0A}\x{7E0B}\x{7E12}\x{7E1B}\x{7E1E}\x{7E1F}\x{7E21}\x{7E22}\x{7E23}'
. '\x{7E26}\x{7E2B}\x{7E2E}\x{7E31}\x{7E32}\x{7E35}\x{7E37}\x{7E39}\x{7E3A}'
. '\x{7E3B}\x{7E3D}\x{7E3E}\x{7E41}\x{7E43}\x{7E46}\x{7E4A}\x{7E4B}\x{7E4D}'
. '\x{7E54}\x{7E55}\x{7E56}\x{7E59}\x{7E5A}\x{7E5D}\x{7E5E}\x{7E66}\x{7E67}'
. '\x{7E69}\x{7E6A}\x{7E6D}\x{7E70}\x{7E79}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7F}'
. '\x{7E82}\x{7E83}\x{7E88}\x{7E89}\x{7E8C}\x{7E8E}\x{7E8F}\x{7E90}\x{7E92}'
. '\x{7E93}\x{7E94}\x{7E96}\x{7E9B}\x{7E9C}\x{7F36}\x{7F38}\x{7F3A}\x{7F45}'
. '\x{7F4C}\x{7F4D}\x{7F4E}\x{7F50}\x{7F51}\x{7F54}\x{7F55}\x{7F58}\x{7F5F}'
. '\x{7F60}\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6E}\x{7F70}\x{7F72}'
. '\x{7F75}\x{7F77}\x{7F78}\x{7F79}\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}'
. '\x{7F88}\x{7F8A}\x{7F8C}\x{7F8E}\x{7F94}\x{7F9A}\x{7F9D}\x{7F9E}\x{7FA3}'
. '\x{7FA4}\x{7FA8}\x{7FA9}\x{7FAE}\x{7FAF}\x{7FB2}\x{7FB6}\x{7FB8}\x{7FB9}'
. '\x{7FBD}\x{7FC1}\x{7FC5}\x{7FC6}\x{7FCA}\x{7FCC}\x{7FD2}\x{7FD4}\x{7FD5}'
. '\x{7FE0}\x{7FE1}\x{7FE6}\x{7FE9}\x{7FEB}\x{7FF0}\x{7FF3}\x{7FF9}\x{7FFB}'
. '\x{7FFC}\x{8000}\x{8001}\x{8003}\x{8004}\x{8005}\x{8006}\x{800B}\x{800C}'
. '\x{8010}\x{8012}\x{8015}\x{8017}\x{8018}\x{8019}\x{801C}\x{8021}\x{8028}'
. '\x{8033}\x{8036}\x{803B}\x{803D}\x{803F}\x{8046}\x{804A}\x{8052}\x{8056}'
. '\x{8058}\x{805A}\x{805E}\x{805F}\x{8061}\x{8062}\x{8068}\x{806F}\x{8070}'
. '\x{8072}\x{8073}\x{8074}\x{8076}\x{8077}\x{8079}\x{807D}\x{807E}\x{807F}'
. '\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808B}\x{808C}\x{8093}\x{8096}'
. '\x{8098}\x{809A}\x{809B}\x{809D}\x{80A1}\x{80A2}\x{80A5}\x{80A9}\x{80AA}'
. '\x{80AC}\x{80AD}\x{80AF}\x{80B1}\x{80B2}\x{80B4}\x{80BA}\x{80C3}\x{80C4}'
. '\x{80C6}\x{80CC}\x{80CE}\x{80D6}\x{80D9}\x{80DA}\x{80DB}\x{80DD}\x{80DE}'
. '\x{80E1}\x{80E4}\x{80E5}\x{80EF}\x{80F1}\x{80F4}\x{80F8}\x{80FC}\x{80FD}'
. '\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{811A}\x{811B}'
. '\x{8123}\x{8129}\x{812F}\x{8131}\x{8133}\x{8139}\x{813E}\x{8146}\x{814B}'
. '\x{814E}\x{8150}\x{8151}\x{8153}\x{8154}\x{8155}\x{815F}\x{8165}\x{8166}'
. '\x{816B}\x{816E}\x{8170}\x{8171}\x{8174}\x{8178}\x{8179}\x{817A}\x{817F}'
. '\x{8180}\x{8182}\x{8183}\x{8188}\x{818A}\x{818F}\x{8193}\x{8195}\x{819A}'
. '\x{819C}\x{819D}\x{81A0}\x{81A3}\x{81A4}\x{81A8}\x{81A9}\x{81B0}\x{81B3}'
. '\x{81B5}\x{81B8}\x{81BA}\x{81BD}\x{81BE}\x{81BF}\x{81C0}\x{81C2}\x{81C6}'
. '\x{81C8}\x{81C9}\x{81CD}\x{81D1}\x{81D3}\x{81D8}\x{81D9}\x{81DA}\x{81DF}'
. '\x{81E0}\x{81E3}\x{81E5}\x{81E7}\x{81E8}\x{81EA}\x{81ED}\x{81F3}\x{81F4}'
. '\x{81FA}\x{81FB}\x{81FC}\x{81FE}\x{8201}\x{8202}\x{8205}\x{8207}\x{8208}'
. '\x{8209}\x{820A}\x{820C}\x{820D}\x{820E}\x{8210}\x{8212}\x{8216}\x{8217}'
. '\x{8218}\x{821B}\x{821C}\x{821E}\x{821F}\x{8229}\x{822A}\x{822B}\x{822C}'
. '\x{822E}\x{8233}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{8240}\x{8247}'
. '\x{8258}\x{8259}\x{825A}\x{825D}\x{825F}\x{8262}\x{8264}\x{8266}\x{8268}'
. '\x{826A}\x{826B}\x{826E}\x{826F}\x{8271}\x{8272}\x{8276}\x{8277}\x{8278}'
. '\x{827E}\x{828B}\x{828D}\x{8292}\x{8299}\x{829D}\x{829F}\x{82A5}\x{82A6}'
. '\x{82AB}\x{82AC}\x{82AD}\x{82AF}\x{82B1}\x{82B3}\x{82B8}\x{82B9}\x{82BB}'
. '\x{82BD}\x{82C5}\x{82D1}\x{82D2}\x{82D3}\x{82D4}\x{82D7}\x{82D9}\x{82DB}'
. '\x{82DC}\x{82DE}\x{82DF}\x{82E1}\x{82E3}\x{82E5}\x{82E6}\x{82E7}\x{82EB}'
. '\x{82F1}\x{82F3}\x{82F4}\x{82F9}\x{82FA}\x{82FB}\x{8302}\x{8303}\x{8304}'
. '\x{8305}\x{8306}\x{8309}\x{830E}\x{8316}\x{8317}\x{8318}\x{831C}\x{8323}'
. '\x{8328}\x{832B}\x{832F}\x{8331}\x{8332}\x{8334}\x{8335}\x{8336}\x{8338}'
. '\x{8339}\x{8340}\x{8345}\x{8349}\x{834A}\x{834F}\x{8350}\x{8352}\x{8358}'
. '\x{8373}\x{8375}\x{8377}\x{837B}\x{837C}\x{8385}\x{8387}\x{8389}\x{838A}'
. '\x{838E}\x{8393}\x{8396}\x{839A}\x{839E}\x{839F}\x{83A0}\x{83A2}\x{83A8}'
. '\x{83AA}\x{83AB}\x{83B1}\x{83B5}\x{83BD}\x{83C1}\x{83C5}\x{83CA}\x{83CC}'
. '\x{83CE}\x{83D3}\x{83D6}\x{83D8}\x{83DC}\x{83DF}\x{83E0}\x{83E9}\x{83EB}'
. '\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F4}\x{83F7}\x{83FB}\x{83FD}\x{8403}'
. '\x{8404}\x{8407}\x{840B}\x{840C}\x{840D}\x{840E}\x{8413}\x{8420}\x{8422}'
. '\x{8429}\x{842A}\x{842C}\x{8431}\x{8435}\x{8438}\x{843C}\x{843D}\x{8446}'
. '\x{8449}\x{844E}\x{8457}\x{845B}\x{8461}\x{8462}\x{8463}\x{8466}\x{8469}'
. '\x{846B}\x{846C}\x{846D}\x{846E}\x{846F}\x{8471}\x{8475}\x{8477}\x{8479}'
. '\x{847A}\x{8482}\x{8484}\x{848B}\x{8490}\x{8494}\x{8499}\x{849C}\x{849F}'
. '\x{84A1}\x{84AD}\x{84B2}\x{84B8}\x{84B9}\x{84BB}\x{84BC}\x{84BF}\x{84C1}'
. '\x{84C4}\x{84C6}\x{84C9}\x{84CA}\x{84CB}\x{84CD}\x{84D0}\x{84D1}\x{84D6}'
. '\x{84D9}\x{84DA}\x{84EC}\x{84EE}\x{84F4}\x{84FC}\x{84FF}\x{8500}\x{8506}'
. '\x{8511}\x{8513}\x{8514}\x{8515}\x{8517}\x{8518}\x{851A}\x{851F}\x{8521}'
. '\x{8526}\x{852C}\x{852D}\x{8535}\x{853D}\x{8540}\x{8541}\x{8543}\x{8548}'
. '\x{8549}\x{854A}\x{854B}\x{854E}\x{8555}\x{8557}\x{8558}\x{855A}\x{8563}'
. '\x{8568}\x{8569}\x{856A}\x{856D}\x{8577}\x{857E}\x{8580}\x{8584}\x{8587}'
. '\x{8588}\x{858A}\x{8590}\x{8591}\x{8594}\x{8597}\x{8599}\x{859B}\x{859C}'
. '\x{85A4}\x{85A6}\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AE}\x{85AF}'
. '\x{85B9}\x{85BA}\x{85C1}\x{85C9}\x{85CD}\x{85CF}\x{85D0}\x{85D5}\x{85DC}'
. '\x{85DD}\x{85E4}\x{85E5}\x{85E9}\x{85EA}\x{85F7}\x{85F9}\x{85FA}\x{85FB}'
. '\x{85FE}\x{8602}\x{8606}\x{8607}\x{860A}\x{860B}\x{8613}\x{8616}\x{8617}'
. '\x{861A}\x{8622}\x{862D}\x{862F}\x{8630}\x{863F}\x{864D}\x{864E}\x{8650}'
. '\x{8654}\x{8655}\x{865A}\x{865C}\x{865E}\x{865F}\x{8667}\x{866B}\x{8671}'
. '\x{8679}\x{867B}\x{868A}\x{868B}\x{868C}\x{8693}\x{8695}\x{86A3}\x{86A4}'
. '\x{86A9}\x{86AA}\x{86AB}\x{86AF}\x{86B0}\x{86B6}\x{86C4}\x{86C6}\x{86C7}'
. '\x{86C9}\x{86CB}\x{86CD}\x{86CE}\x{86D4}\x{86D9}\x{86DB}\x{86DE}\x{86DF}'
. '\x{86E4}\x{86E9}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F8}\x{86F9}\x{86FB}'
. '\x{86FE}\x{8700}\x{8702}\x{8703}\x{8706}\x{8708}\x{8709}\x{870A}\x{870D}'
. '\x{8711}\x{8712}\x{8718}\x{871A}\x{871C}\x{8725}\x{8729}\x{8734}\x{8737}'
. '\x{873B}\x{873F}\x{8749}\x{874B}\x{874C}\x{874E}\x{8753}\x{8755}\x{8757}'
. '\x{8759}\x{875F}\x{8760}\x{8763}\x{8766}\x{8768}\x{876A}\x{876E}\x{8774}'
. '\x{8776}\x{8778}\x{877F}\x{8782}\x{878D}\x{879F}\x{87A2}\x{87AB}\x{87AF}'
. '\x{87B3}\x{87BA}\x{87BB}\x{87BD}\x{87C0}\x{87C4}\x{87C6}\x{87C7}\x{87CB}'
. '\x{87D0}\x{87D2}\x{87E0}\x{87EF}\x{87F2}\x{87F6}\x{87F7}\x{87F9}\x{87FB}'
. '\x{87FE}\x{8805}\x{880D}\x{880E}\x{880F}\x{8811}\x{8815}\x{8816}\x{8821}'
. '\x{8822}\x{8823}\x{8827}\x{8831}\x{8836}\x{8839}\x{883B}\x{8840}\x{8842}'
. '\x{8844}\x{8846}\x{884C}\x{884D}\x{8852}\x{8853}\x{8857}\x{8859}\x{885B}'
. '\x{885D}\x{885E}\x{8861}\x{8862}\x{8863}\x{8868}\x{886B}\x{8870}\x{8872}'
. '\x{8875}\x{8877}\x{887D}\x{887E}\x{887F}\x{8881}\x{8882}\x{8888}\x{888B}'
. '\x{888D}\x{8892}\x{8896}\x{8897}\x{8899}\x{889E}\x{88A2}\x{88A4}\x{88AB}'
. '\x{88AE}\x{88B0}\x{88B1}\x{88B4}\x{88B5}\x{88B7}\x{88BF}\x{88C1}\x{88C2}'
. '\x{88C3}\x{88C4}\x{88C5}\x{88CF}\x{88D4}\x{88D5}\x{88D8}\x{88D9}\x{88DC}'
. '\x{88DD}\x{88DF}\x{88E1}\x{88E8}\x{88F2}\x{88F3}\x{88F4}\x{88F8}\x{88F9}'
. '\x{88FC}\x{88FD}\x{88FE}\x{8902}\x{8904}\x{8907}\x{890A}\x{890C}\x{8910}'
. '\x{8912}\x{8913}\x{891D}\x{891E}\x{8925}\x{892A}\x{892B}\x{8936}\x{8938}'
. '\x{893B}\x{8941}\x{8943}\x{8944}\x{894C}\x{894D}\x{8956}\x{895E}\x{895F}'
. '\x{8960}\x{8964}\x{8966}\x{896A}\x{896D}\x{896F}\x{8972}\x{8974}\x{8977}'
. '\x{897E}\x{897F}\x{8981}\x{8983}\x{8986}\x{8987}\x{8988}\x{898A}\x{898B}'
. '\x{898F}\x{8993}\x{8996}\x{8997}\x{8998}\x{899A}\x{89A1}\x{89A6}\x{89A7}'
. '\x{89A9}\x{89AA}\x{89AC}\x{89AF}\x{89B2}\x{89B3}\x{89BA}\x{89BD}\x{89BF}'
. '\x{89C0}\x{89D2}\x{89DA}\x{89DC}\x{89DD}\x{89E3}\x{89E6}\x{89E7}\x{89F4}'
. '\x{89F8}\x{8A00}\x{8A02}\x{8A03}\x{8A08}\x{8A0A}\x{8A0C}\x{8A0E}\x{8A10}'
. '\x{8A13}\x{8A16}\x{8A17}\x{8A18}\x{8A1B}\x{8A1D}\x{8A1F}\x{8A23}\x{8A25}'
. '\x{8A2A}\x{8A2D}\x{8A31}\x{8A33}\x{8A34}\x{8A36}\x{8A3A}\x{8A3B}\x{8A3C}'
. '\x{8A41}\x{8A46}\x{8A48}\x{8A50}\x{8A51}\x{8A52}\x{8A54}\x{8A55}\x{8A5B}'
. '\x{8A5E}\x{8A60}\x{8A62}\x{8A63}\x{8A66}\x{8A69}\x{8A6B}\x{8A6C}\x{8A6D}'
. '\x{8A6E}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A7C}\x{8A82}\x{8A84}\x{8A85}'
. '\x{8A87}\x{8A89}\x{8A8C}\x{8A8D}\x{8A91}\x{8A93}\x{8A95}\x{8A98}\x{8A9A}'
. '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA8}\x{8AAC}'
. '\x{8AAD}\x{8AB0}\x{8AB2}\x{8AB9}\x{8ABC}\x{8ABF}\x{8AC2}\x{8AC4}\x{8AC7}'
. '\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACF}\x{8AD2}\x{8AD6}\x{8ADA}\x{8ADB}\x{8ADC}'
. '\x{8ADE}\x{8AE0}\x{8AE1}\x{8AE2}\x{8AE4}\x{8AE6}\x{8AE7}\x{8AEB}\x{8AED}'
. '\x{8AEE}\x{8AF1}\x{8AF3}\x{8AF7}\x{8AF8}\x{8AFA}\x{8AFE}\x{8B00}\x{8B01}'
. '\x{8B02}\x{8B04}\x{8B07}\x{8B0C}\x{8B0E}\x{8B10}\x{8B14}\x{8B16}\x{8B17}'
. '\x{8B19}\x{8B1A}\x{8B1B}\x{8B1D}\x{8B20}\x{8B21}\x{8B26}\x{8B28}\x{8B2B}'
. '\x{8B2C}\x{8B33}\x{8B39}\x{8B3E}\x{8B41}\x{8B49}\x{8B4C}\x{8B4E}\x{8B4F}'
. '\x{8B56}\x{8B58}\x{8B5A}\x{8B5B}\x{8B5C}\x{8B5F}\x{8B66}\x{8B6B}\x{8B6C}'
. '\x{8B6F}\x{8B70}\x{8B71}\x{8B72}\x{8B74}\x{8B77}\x{8B7D}\x{8B80}\x{8B83}'
. '\x{8B8A}\x{8B8C}\x{8B8E}\x{8B90}\x{8B92}\x{8B93}\x{8B96}\x{8B99}\x{8B9A}'
. '\x{8C37}\x{8C3A}\x{8C3F}\x{8C41}\x{8C46}\x{8C48}\x{8C4A}\x{8C4C}\x{8C4E}'
. '\x{8C50}\x{8C55}\x{8C5A}\x{8C61}\x{8C62}\x{8C6A}\x{8C6B}\x{8C6C}\x{8C78}'
. '\x{8C79}\x{8C7A}\x{8C7C}\x{8C82}\x{8C85}\x{8C89}\x{8C8A}\x{8C8C}\x{8C8D}'
. '\x{8C8E}\x{8C94}\x{8C98}\x{8C9D}\x{8C9E}\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA7}'
. '\x{8CA8}\x{8CA9}\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}'
. '\x{8CB2}\x{8CB3}\x{8CB4}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CBB}\x{8CBC}\x{8CBD}'
. '\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}\x{8CC7}\x{8CC8}\x{8CCA}'
. '\x{8CCD}\x{8CCE}\x{8CD1}\x{8CD3}\x{8CDA}\x{8CDB}\x{8CDC}\x{8CDE}\x{8CE0}'
. '\x{8CE2}\x{8CE3}\x{8CE4}\x{8CE6}\x{8CEA}\x{8CED}\x{8CFA}\x{8CFB}\x{8CFC}'
. '\x{8CFD}\x{8D04}\x{8D05}\x{8D07}\x{8D08}\x{8D0A}\x{8D0B}\x{8D0D}\x{8D0F}'
. '\x{8D10}\x{8D13}\x{8D14}\x{8D16}\x{8D64}\x{8D66}\x{8D67}\x{8D6B}\x{8D6D}'
. '\x{8D70}\x{8D71}\x{8D73}\x{8D74}\x{8D77}\x{8D81}\x{8D85}\x{8D8A}\x{8D99}'
. '\x{8DA3}\x{8DA8}\x{8DB3}\x{8DBA}\x{8DBE}\x{8DC2}\x{8DCB}\x{8DCC}\x{8DCF}'
. '\x{8DD6}\x{8DDA}\x{8DDB}\x{8DDD}\x{8DDF}\x{8DE1}\x{8DE3}\x{8DE8}\x{8DEA}'
. '\x{8DEB}\x{8DEF}\x{8DF3}\x{8DF5}\x{8DFC}\x{8DFF}\x{8E08}\x{8E09}\x{8E0A}'
. '\x{8E0F}\x{8E10}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E2A}\x{8E30}\x{8E34}\x{8E35}'
. '\x{8E42}\x{8E44}\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4C}\x{8E50}\x{8E55}'
. '\x{8E59}\x{8E5F}\x{8E60}\x{8E63}\x{8E64}\x{8E72}\x{8E74}\x{8E76}\x{8E7C}'
. '\x{8E81}\x{8E84}\x{8E85}\x{8E87}\x{8E8A}\x{8E8B}\x{8E8D}\x{8E91}\x{8E93}'
. '\x{8E94}\x{8E99}\x{8EA1}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAF}\x{8EB0}\x{8EB1}'
. '\x{8EBE}\x{8EC5}\x{8EC6}\x{8EC8}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ED2}'
. '\x{8EDB}\x{8EDF}\x{8EE2}\x{8EE3}\x{8EEB}\x{8EF8}\x{8EFB}\x{8EFC}\x{8EFD}'
. '\x{8EFE}\x{8F03}\x{8F05}\x{8F09}\x{8F0A}\x{8F0C}\x{8F12}\x{8F13}\x{8F14}'
. '\x{8F15}\x{8F19}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1F}\x{8F26}\x{8F29}\x{8F2A}'
. '\x{8F2F}\x{8F33}\x{8F38}\x{8F39}\x{8F3B}\x{8F3E}\x{8F3F}\x{8F42}\x{8F44}'
. '\x{8F45}\x{8F46}\x{8F49}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F57}\x{8F5C}\x{8F5F}'
. '\x{8F61}\x{8F62}\x{8F63}\x{8F64}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA3}'
. '\x{8FA7}\x{8FA8}\x{8FAD}\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB7}'
. '\x{8FBA}\x{8FBB}\x{8FBC}\x{8FBF}\x{8FC2}\x{8FC4}\x{8FC5}\x{8FCE}\x{8FD1}'
. '\x{8FD4}\x{8FDA}\x{8FE2}\x{8FE5}\x{8FE6}\x{8FE9}\x{8FEA}\x{8FEB}\x{8FED}'
. '\x{8FEF}\x{8FF0}\x{8FF4}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}\x{8FFD}\x{9000}'
. '\x{9001}\x{9003}\x{9005}\x{9006}\x{900B}\x{900D}\x{900E}\x{900F}\x{9010}'
. '\x{9011}\x{9013}\x{9014}\x{9015}\x{9016}\x{9017}\x{9019}\x{901A}\x{901D}'
. '\x{901E}\x{901F}\x{9020}\x{9021}\x{9022}\x{9023}\x{9027}\x{902E}\x{9031}'
. '\x{9032}\x{9035}\x{9036}\x{9038}\x{9039}\x{903C}\x{903E}\x{9041}\x{9042}'
. '\x{9045}\x{9047}\x{9049}\x{904A}\x{904B}\x{904D}\x{904E}\x{904F}\x{9050}'
. '\x{9051}\x{9052}\x{9053}\x{9054}\x{9055}\x{9056}\x{9058}\x{9059}\x{905C}'
. '\x{905E}\x{9060}\x{9061}\x{9063}\x{9065}\x{9068}\x{9069}\x{906D}\x{906E}'
. '\x{906F}\x{9072}\x{9075}\x{9076}\x{9077}\x{9078}\x{907A}\x{907C}\x{907D}'
. '\x{907F}\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9087}\x{9089}\x{908A}'
. '\x{908F}\x{9091}\x{90A3}\x{90A6}\x{90A8}\x{90AA}\x{90AF}\x{90B1}\x{90B5}'
. '\x{90B8}\x{90C1}\x{90CA}\x{90CE}\x{90DB}\x{90E1}\x{90E2}\x{90E4}\x{90E8}'
. '\x{90ED}\x{90F5}\x{90F7}\x{90FD}\x{9102}\x{9112}\x{9119}\x{912D}\x{9130}'
. '\x{9132}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}\x{914E}\x{9152}\x{9154}'
. '\x{9156}\x{9158}\x{9162}\x{9163}\x{9165}\x{9169}\x{916A}\x{916C}\x{9172}'
. '\x{9173}\x{9175}\x{9177}\x{9178}\x{9182}\x{9187}\x{9189}\x{918B}\x{918D}'
. '\x{9190}\x{9192}\x{9197}\x{919C}\x{91A2}\x{91A4}\x{91AA}\x{91AB}\x{91AF}'
. '\x{91B4}\x{91B5}\x{91B8}\x{91BA}\x{91C0}\x{91C1}\x{91C6}\x{91C7}\x{91C8}'
. '\x{91C9}\x{91CB}\x{91CC}\x{91CD}\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D6}'
. '\x{91D8}\x{91DB}\x{91DC}\x{91DD}\x{91DF}\x{91E1}\x{91E3}\x{91E6}\x{91E7}'
. '\x{91F5}\x{91F6}\x{91FC}\x{91FF}\x{920D}\x{920E}\x{9211}\x{9214}\x{9215}'
. '\x{921E}\x{9229}\x{922C}\x{9234}\x{9237}\x{923F}\x{9244}\x{9245}\x{9248}'
. '\x{9249}\x{924B}\x{9250}\x{9257}\x{925A}\x{925B}\x{925E}\x{9262}\x{9264}'
. '\x{9266}\x{9271}\x{927E}\x{9280}\x{9283}\x{9285}\x{9291}\x{9293}\x{9295}'
. '\x{9296}\x{9298}\x{929A}\x{929B}\x{929C}\x{92AD}\x{92B7}\x{92B9}\x{92CF}'
. '\x{92D2}\x{92E4}\x{92E9}\x{92EA}\x{92ED}\x{92F2}\x{92F3}\x{92F8}\x{92FA}'
. '\x{92FC}\x{9306}\x{930F}\x{9310}\x{9318}\x{9319}\x{931A}\x{9320}\x{9322}'
. '\x{9323}\x{9326}\x{9328}\x{932B}\x{932C}\x{932E}\x{932F}\x{9332}\x{9335}'
. '\x{933A}\x{933B}\x{9344}\x{934B}\x{934D}\x{9354}\x{9356}\x{935B}\x{935C}'
. '\x{9360}\x{936C}\x{936E}\x{9375}\x{937C}\x{937E}\x{938C}\x{9394}\x{9396}'
. '\x{9397}\x{939A}\x{93A7}\x{93AC}\x{93AD}\x{93AE}\x{93B0}\x{93B9}\x{93C3}'
. '\x{93C8}\x{93D0}\x{93D1}\x{93D6}\x{93D7}\x{93D8}\x{93DD}\x{93E1}\x{93E4}'
. '\x{93E5}\x{93E8}\x{9403}\x{9407}\x{9410}\x{9413}\x{9414}\x{9418}\x{9419}'
. '\x{941A}\x{9421}\x{942B}\x{9435}\x{9436}\x{9438}\x{943A}\x{9441}\x{9444}'
. '\x{9451}\x{9452}\x{9453}\x{945A}\x{945B}\x{945E}\x{9460}\x{9462}\x{946A}'
. '\x{9470}\x{9475}\x{9477}\x{947C}\x{947D}\x{947E}\x{947F}\x{9481}\x{9577}'
. '\x{9580}\x{9582}\x{9583}\x{9587}\x{9589}\x{958A}\x{958B}\x{958F}\x{9591}'
. '\x{9593}\x{9594}\x{9596}\x{9598}\x{9599}\x{95A0}\x{95A2}\x{95A3}\x{95A4}'
. '\x{95A5}\x{95A7}\x{95A8}\x{95AD}\x{95B2}\x{95B9}\x{95BB}\x{95BC}\x{95BE}'
. '\x{95C3}\x{95C7}\x{95CA}\x{95CC}\x{95CD}\x{95D4}\x{95D5}\x{95D6}\x{95D8}'
. '\x{95DC}\x{95E1}\x{95E2}\x{95E5}\x{961C}\x{9621}\x{9628}\x{962A}\x{962E}'
. '\x{962F}\x{9632}\x{963B}\x{963F}\x{9640}\x{9642}\x{9644}\x{964B}\x{964C}'
. '\x{964D}\x{964F}\x{9650}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9662}'
. '\x{9663}\x{9664}\x{9665}\x{9666}\x{966A}\x{966C}\x{9670}\x{9672}\x{9673}'
. '\x{9675}\x{9676}\x{9677}\x{9678}\x{967A}\x{967D}\x{9685}\x{9686}\x{9688}'
. '\x{968A}\x{968B}\x{968D}\x{968E}\x{968F}\x{9694}\x{9695}\x{9697}\x{9698}'
. '\x{9699}\x{969B}\x{969C}\x{96A0}\x{96A3}\x{96A7}\x{96A8}\x{96AA}\x{96B0}'
. '\x{96B1}\x{96B2}\x{96B4}\x{96B6}\x{96B7}\x{96B8}\x{96B9}\x{96BB}\x{96BC}'
. '\x{96C0}\x{96C1}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C9}\x{96CB}\x{96CC}'
. '\x{96CD}\x{96CE}\x{96D1}\x{96D5}\x{96D6}\x{96D9}\x{96DB}\x{96DC}\x{96E2}'
. '\x{96E3}\x{96E8}\x{96EA}\x{96EB}\x{96F0}\x{96F2}\x{96F6}\x{96F7}\x{96F9}'
. '\x{96FB}\x{9700}\x{9704}\x{9706}\x{9707}\x{9708}\x{970A}\x{970D}\x{970E}'
. '\x{970F}\x{9711}\x{9713}\x{9716}\x{9719}\x{971C}\x{971E}\x{9724}\x{9727}'
. '\x{972A}\x{9730}\x{9732}\x{9738}\x{9739}\x{973D}\x{973E}\x{9742}\x{9744}'
. '\x{9746}\x{9748}\x{9749}\x{9752}\x{9756}\x{9759}\x{975C}\x{975E}\x{9760}'
. '\x{9761}\x{9762}\x{9764}\x{9766}\x{9768}\x{9769}\x{976B}\x{976D}\x{9771}'
. '\x{9774}\x{9779}\x{977A}\x{977C}\x{9781}\x{9784}\x{9785}\x{9786}\x{978B}'
. '\x{978D}\x{978F}\x{9790}\x{9798}\x{979C}\x{97A0}\x{97A3}\x{97A6}\x{97A8}'
. '\x{97AB}\x{97AD}\x{97B3}\x{97B4}\x{97C3}\x{97C6}\x{97C8}\x{97CB}\x{97D3}'
. '\x{97DC}\x{97ED}\x{97EE}\x{97F2}\x{97F3}\x{97F5}\x{97F6}\x{97FB}\x{97FF}'
. '\x{9801}\x{9802}\x{9803}\x{9805}\x{9806}\x{9808}\x{980C}\x{980F}\x{9810}'
. '\x{9811}\x{9812}\x{9813}\x{9817}\x{9818}\x{981A}\x{9821}\x{9824}\x{982C}'
. '\x{982D}\x{9834}\x{9837}\x{9838}\x{983B}\x{983C}\x{983D}\x{9846}\x{984B}'
. '\x{984C}\x{984D}\x{984E}\x{984F}\x{9854}\x{9855}\x{9858}\x{985B}\x{985E}'
. '\x{9867}\x{986B}\x{986F}\x{9870}\x{9871}\x{9873}\x{9874}\x{98A8}\x{98AA}'
. '\x{98AF}\x{98B1}\x{98B6}\x{98C3}\x{98C4}\x{98C6}\x{98DB}\x{98DC}\x{98DF}'
. '\x{98E2}\x{98E9}\x{98EB}\x{98ED}\x{98EE}\x{98EF}\x{98F2}\x{98F4}\x{98FC}'
. '\x{98FD}\x{98FE}\x{9903}\x{9905}\x{9909}\x{990A}\x{990C}\x{9910}\x{9912}'
. '\x{9913}\x{9914}\x{9918}\x{991D}\x{991E}\x{9920}\x{9921}\x{9924}\x{9928}'
. '\x{992C}\x{992E}\x{993D}\x{993E}\x{9942}\x{9945}\x{9949}\x{994B}\x{994C}'
. '\x{9950}\x{9951}\x{9952}\x{9955}\x{9957}\x{9996}\x{9997}\x{9998}\x{9999}'
. '\x{99A5}\x{99A8}\x{99AC}\x{99AD}\x{99AE}\x{99B3}\x{99B4}\x{99BC}\x{99C1}'
. '\x{99C4}\x{99C5}\x{99C6}\x{99C8}\x{99D0}\x{99D1}\x{99D2}\x{99D5}\x{99D8}'
. '\x{99DB}\x{99DD}\x{99DF}\x{99E2}\x{99ED}\x{99EE}\x{99F1}\x{99F2}\x{99F8}'
. '\x{99FB}\x{99FF}\x{9A01}\x{9A05}\x{9A0E}\x{9A0F}\x{9A12}\x{9A13}\x{9A19}'
. '\x{9A28}\x{9A2B}\x{9A30}\x{9A37}\x{9A3E}\x{9A40}\x{9A42}\x{9A43}\x{9A45}'
. '\x{9A4D}\x{9A55}\x{9A57}\x{9A5A}\x{9A5B}\x{9A5F}\x{9A62}\x{9A64}\x{9A65}'
. '\x{9A69}\x{9A6A}\x{9A6B}\x{9AA8}\x{9AAD}\x{9AB0}\x{9AB8}\x{9ABC}\x{9AC0}'
. '\x{9AC4}\x{9ACF}\x{9AD1}\x{9AD3}\x{9AD4}\x{9AD8}\x{9ADE}\x{9ADF}\x{9AE2}'
. '\x{9AE3}\x{9AE6}\x{9AEA}\x{9AEB}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF4}'
. '\x{9AF7}\x{9AFB}\x{9B06}\x{9B18}\x{9B1A}\x{9B1F}\x{9B22}\x{9B23}\x{9B25}'
. '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2E}\x{9B2F}\x{9B31}\x{9B32}\x{9B3B}'
. '\x{9B3C}\x{9B41}\x{9B42}\x{9B43}\x{9B44}\x{9B45}\x{9B4D}\x{9B4E}\x{9B4F}'
. '\x{9B51}\x{9B54}\x{9B58}\x{9B5A}\x{9B6F}\x{9B74}\x{9B83}\x{9B8E}\x{9B91}'
. '\x{9B92}\x{9B93}\x{9B96}\x{9B97}\x{9B9F}\x{9BA0}\x{9BA8}\x{9BAA}\x{9BAB}'
. '\x{9BAD}\x{9BAE}\x{9BB4}\x{9BB9}\x{9BC0}\x{9BC6}\x{9BC9}\x{9BCA}\x{9BCF}'
. '\x{9BD1}\x{9BD2}\x{9BD4}\x{9BD6}\x{9BDB}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}'
. '\x{9BE8}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF5}\x{9C04}\x{9C06}\x{9C08}\x{9C09}'
. '\x{9C0A}\x{9C0C}\x{9C0D}\x{9C10}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C1B}'
. '\x{9C21}\x{9C24}\x{9C25}\x{9C2D}\x{9C2E}\x{9C2F}\x{9C30}\x{9C32}\x{9C39}'
. '\x{9C3A}\x{9C3B}\x{9C3E}\x{9C46}\x{9C47}\x{9C48}\x{9C52}\x{9C57}\x{9C5A}'
. '\x{9C60}\x{9C67}\x{9C76}\x{9C78}\x{9CE5}\x{9CE7}\x{9CE9}\x{9CEB}\x{9CEC}'
. '\x{9CF0}\x{9CF3}\x{9CF4}\x{9CF6}\x{9D03}\x{9D06}\x{9D07}\x{9D08}\x{9D09}'
. '\x{9D0E}\x{9D12}\x{9D15}\x{9D1B}\x{9D1F}\x{9D23}\x{9D26}\x{9D28}\x{9D2A}'
. '\x{9D2B}\x{9D2C}\x{9D3B}\x{9D3E}\x{9D3F}\x{9D41}\x{9D44}\x{9D46}\x{9D48}'
. '\x{9D50}\x{9D51}\x{9D59}\x{9D5C}\x{9D5D}\x{9D5E}\x{9D60}\x{9D61}\x{9D64}'
. '\x{9D6C}\x{9D6F}\x{9D72}\x{9D7A}\x{9D87}\x{9D89}\x{9D8F}\x{9D9A}\x{9DA4}'
. '\x{9DA9}\x{9DAB}\x{9DAF}\x{9DB2}\x{9DB4}\x{9DB8}\x{9DBA}\x{9DBB}\x{9DC1}'
. '\x{9DC2}\x{9DC4}\x{9DC6}\x{9DCF}\x{9DD3}\x{9DD9}\x{9DE6}\x{9DED}\x{9DEF}'
. '\x{9DF2}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFD}\x{9E1A}\x{9E1B}\x{9E1E}\x{9E75}'
. '\x{9E78}\x{9E79}\x{9E7D}\x{9E7F}\x{9E81}\x{9E88}\x{9E8B}\x{9E8C}\x{9E91}'
. '\x{9E92}\x{9E93}\x{9E95}\x{9E97}\x{9E9D}\x{9E9F}\x{9EA5}\x{9EA6}\x{9EA9}'
. '\x{9EAA}\x{9EAD}\x{9EB8}\x{9EB9}\x{9EBA}\x{9EBB}\x{9EBC}\x{9EBE}\x{9EBF}'
. '\x{9EC4}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED2}\x{9ED4}\x{9ED8}'
. '\x{9ED9}\x{9EDB}\x{9EDC}\x{9EDD}\x{9EDE}\x{9EE0}\x{9EE5}\x{9EE8}\x{9EEF}'
. '\x{9EF4}\x{9EF6}\x{9EF7}\x{9EF9}\x{9EFB}\x{9EFC}\x{9EFD}\x{9F07}\x{9F08}'
. '\x{9F0E}\x{9F13}\x{9F15}\x{9F20}\x{9F21}\x{9F2C}\x{9F3B}\x{9F3E}\x{9F4A}'
. '\x{9F4B}\x{9F4E}\x{9F4F}\x{9F52}\x{9F54}\x{9F5F}\x{9F60}\x{9F61}\x{9F62}'
. '\x{9F63}\x{9F66}\x{9F67}\x{9F6A}\x{9F6C}\x{9F72}\x{9F76}\x{9F77}\x{9F8D}'
. '\x{9F95}\x{9F9C}\x{9F9D}\x{9FA0}]{1,15}$/iu',
12 => '/^[\x{002d}0-9a-z\x{3447}\x{3473}\x{359E}\x{360E}\x{361A}\x{3918}\x{396E}\x{39CF}\x{39D0}'
. '\x{39DF}\x{3A73}\x{3B4E}\x{3C6E}\x{3CE0}\x{4056}\x{415F}\x{4337}\x{43AC}'
. '\x{43B1}\x{43DD}\x{44D6}\x{464C}\x{4661}\x{4723}\x{4729}\x{477C}\x{478D}'
. '\x{4947}\x{497A}\x{497D}\x{4982}\x{4983}\x{4985}\x{4986}\x{499B}\x{499F}'
. '\x{49B6}\x{49B7}\x{4C77}\x{4C9F}\x{4CA0}\x{4CA1}\x{4CA2}\x{4CA3}\x{4D13}'
. '\x{4D14}\x{4D15}\x{4D16}\x{4D17}\x{4D18}\x{4D19}\x{4DAE}\x{4E00}\x{4E01}'
. '\x{4E02}\x{4E03}\x{4E04}\x{4E05}\x{4E06}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}'
. '\x{4E0B}\x{4E0C}\x{4E0D}\x{4E0E}\x{4E0F}\x{4E10}\x{4E11}\x{4E13}\x{4E14}'
. '\x{4E15}\x{4E16}\x{4E17}\x{4E18}\x{4E19}\x{4E1A}\x{4E1B}\x{4E1C}\x{4E1D}'
. '\x{4E1E}\x{4E1F}\x{4E20}\x{4E21}\x{4E22}\x{4E23}\x{4E24}\x{4E25}\x{4E26}'
. '\x{4E27}\x{4E28}\x{4E2A}\x{4E2B}\x{4E2C}\x{4E2D}\x{4E2E}\x{4E2F}\x{4E30}'
. '\x{4E31}\x{4E32}\x{4E33}\x{4E34}\x{4E35}\x{4E36}\x{4E37}\x{4E38}\x{4E39}'
. '\x{4E3A}\x{4E3B}\x{4E3C}\x{4E3D}\x{4E3E}\x{4E3F}\x{4E40}\x{4E41}\x{4E42}'
. '\x{4E43}\x{4E44}\x{4E45}\x{4E46}\x{4E47}\x{4E48}\x{4E49}\x{4E4A}\x{4E4B}'
. '\x{4E4C}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E50}\x{4E51}\x{4E52}\x{4E53}\x{4E54}'
. '\x{4E56}\x{4E57}\x{4E58}\x{4E59}\x{4E5A}\x{4E5B}\x{4E5C}\x{4E5D}\x{4E5E}'
. '\x{4E5F}\x{4E60}\x{4E61}\x{4E62}\x{4E63}\x{4E64}\x{4E65}\x{4E66}\x{4E67}'
. '\x{4E69}\x{4E6A}\x{4E6B}\x{4E6C}\x{4E6D}\x{4E6E}\x{4E6F}\x{4E70}\x{4E71}'
. '\x{4E72}\x{4E73}\x{4E74}\x{4E75}\x{4E76}\x{4E77}\x{4E78}\x{4E7A}\x{4E7B}'
. '\x{4E7C}\x{4E7D}\x{4E7E}\x{4E7F}\x{4E80}\x{4E81}\x{4E82}\x{4E83}\x{4E84}'
. '\x{4E85}\x{4E86}\x{4E87}\x{4E88}\x{4E89}\x{4E8B}\x{4E8C}\x{4E8D}\x{4E8E}'
. '\x{4E8F}\x{4E90}\x{4E91}\x{4E92}\x{4E93}\x{4E94}\x{4E95}\x{4E97}\x{4E98}'
. '\x{4E99}\x{4E9A}\x{4E9B}\x{4E9C}\x{4E9D}\x{4E9E}\x{4E9F}\x{4EA0}\x{4EA1}'
. '\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA7}\x{4EA8}\x{4EA9}\x{4EAA}\x{4EAB}'
. '\x{4EAC}\x{4EAD}\x{4EAE}\x{4EAF}\x{4EB0}\x{4EB1}\x{4EB2}\x{4EB3}\x{4EB4}'
. '\x{4EB5}\x{4EB6}\x{4EB7}\x{4EB8}\x{4EB9}\x{4EBA}\x{4EBB}\x{4EBD}\x{4EBE}'
. '\x{4EBF}\x{4EC0}\x{4EC1}\x{4EC2}\x{4EC3}\x{4EC4}\x{4EC5}\x{4EC6}\x{4EC7}'
. '\x{4EC8}\x{4EC9}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED0}\x{4ED1}'
. '\x{4ED2}\x{4ED3}\x{4ED4}\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDA}'
. '\x{4EDB}\x{4EDC}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE0}\x{4EE1}\x{4EE2}\x{4EE3}'
. '\x{4EE4}\x{4EE5}\x{4EE6}\x{4EE8}\x{4EE9}\x{4EEA}\x{4EEB}\x{4EEC}\x{4EEF}'
. '\x{4EF0}\x{4EF1}\x{4EF2}\x{4EF3}\x{4EF4}\x{4EF5}\x{4EF6}\x{4EF7}\x{4EFB}'
. '\x{4EFD}\x{4EFF}\x{4F00}\x{4F01}\x{4F02}\x{4F03}\x{4F04}\x{4F05}\x{4F06}'
. '\x{4F08}\x{4F09}\x{4F0A}\x{4F0B}\x{4F0C}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}'
. '\x{4F11}\x{4F12}\x{4F13}\x{4F14}\x{4F15}\x{4F17}\x{4F18}\x{4F19}\x{4F1A}'
. '\x{4F1B}\x{4F1C}\x{4F1D}\x{4F1E}\x{4F1F}\x{4F20}\x{4F21}\x{4F22}\x{4F23}'
. '\x{4F24}\x{4F25}\x{4F26}\x{4F27}\x{4F29}\x{4F2A}\x{4F2B}\x{4F2C}\x{4F2D}'
. '\x{4F2E}\x{4F2F}\x{4F30}\x{4F32}\x{4F33}\x{4F34}\x{4F36}\x{4F38}\x{4F39}'
. '\x{4F3A}\x{4F3B}\x{4F3C}\x{4F3D}\x{4F3E}\x{4F3F}\x{4F41}\x{4F42}\x{4F43}'
. '\x{4F45}\x{4F46}\x{4F47}\x{4F48}\x{4F49}\x{4F4A}\x{4F4B}\x{4F4C}\x{4F4D}'
. '\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}\x{4F52}\x{4F53}\x{4F54}\x{4F55}\x{4F56}'
. '\x{4F57}\x{4F58}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}\x{4F5F}'
. '\x{4F60}\x{4F61}\x{4F62}\x{4F63}\x{4F64}\x{4F65}\x{4F66}\x{4F67}\x{4F68}'
. '\x{4F69}\x{4F6A}\x{4F6B}\x{4F6C}\x{4F6D}\x{4F6E}\x{4F6F}\x{4F70}\x{4F72}'
. '\x{4F73}\x{4F74}\x{4F75}\x{4F76}\x{4F77}\x{4F78}\x{4F79}\x{4F7A}\x{4F7B}'
. '\x{4F7C}\x{4F7D}\x{4F7E}\x{4F7F}\x{4F80}\x{4F81}\x{4F82}\x{4F83}\x{4F84}'
. '\x{4F85}\x{4F86}\x{4F87}\x{4F88}\x{4F89}\x{4F8A}\x{4F8B}\x{4F8D}\x{4F8F}'
. '\x{4F90}\x{4F91}\x{4F92}\x{4F93}\x{4F94}\x{4F95}\x{4F96}\x{4F97}\x{4F98}'
. '\x{4F99}\x{4F9A}\x{4F9B}\x{4F9C}\x{4F9D}\x{4F9E}\x{4F9F}\x{4FA0}\x{4FA1}'
. '\x{4FA3}\x{4FA4}\x{4FA5}\x{4FA6}\x{4FA7}\x{4FA8}\x{4FA9}\x{4FAA}\x{4FAB}'
. '\x{4FAC}\x{4FAE}\x{4FAF}\x{4FB0}\x{4FB1}\x{4FB2}\x{4FB3}\x{4FB4}\x{4FB5}'
. '\x{4FB6}\x{4FB7}\x{4FB8}\x{4FB9}\x{4FBA}\x{4FBB}\x{4FBC}\x{4FBE}\x{4FBF}'
. '\x{4FC0}\x{4FC1}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FC5}\x{4FC7}\x{4FC9}\x{4FCA}'
. '\x{4FCB}\x{4FCD}\x{4FCE}\x{4FCF}\x{4FD0}\x{4FD1}\x{4FD2}\x{4FD3}\x{4FD4}'
. '\x{4FD5}\x{4FD6}\x{4FD7}\x{4FD8}\x{4FD9}\x{4FDA}\x{4FDB}\x{4FDC}\x{4FDD}'
. '\x{4FDE}\x{4FDF}\x{4FE0}\x{4FE1}\x{4FE3}\x{4FE4}\x{4FE5}\x{4FE6}\x{4FE7}'
. '\x{4FE8}\x{4FE9}\x{4FEA}\x{4FEB}\x{4FEC}\x{4FED}\x{4FEE}\x{4FEF}\x{4FF0}'
. '\x{4FF1}\x{4FF2}\x{4FF3}\x{4FF4}\x{4FF5}\x{4FF6}\x{4FF7}\x{4FF8}\x{4FF9}'
. '\x{4FFA}\x{4FFB}\x{4FFE}\x{4FFF}\x{5000}\x{5001}\x{5002}\x{5003}\x{5004}'
. '\x{5005}\x{5006}\x{5007}\x{5008}\x{5009}\x{500A}\x{500B}\x{500C}\x{500D}'
. '\x{500E}\x{500F}\x{5011}\x{5012}\x{5013}\x{5014}\x{5015}\x{5016}\x{5017}'
. '\x{5018}\x{5019}\x{501A}\x{501B}\x{501C}\x{501D}\x{501E}\x{501F}\x{5020}'
. '\x{5021}\x{5022}\x{5023}\x{5024}\x{5025}\x{5026}\x{5027}\x{5028}\x{5029}'
. '\x{502A}\x{502B}\x{502C}\x{502D}\x{502E}\x{502F}\x{5030}\x{5031}\x{5032}'
. '\x{5033}\x{5035}\x{5036}\x{5037}\x{5039}\x{503A}\x{503B}\x{503C}\x{503E}'
. '\x{503F}\x{5040}\x{5041}\x{5043}\x{5044}\x{5045}\x{5046}\x{5047}\x{5048}'
. '\x{5049}\x{504A}\x{504B}\x{504C}\x{504D}\x{504E}\x{504F}\x{5051}\x{5053}'
. '\x{5054}\x{5055}\x{5056}\x{5057}\x{5059}\x{505A}\x{505B}\x{505C}\x{505D}'
. '\x{505E}\x{505F}\x{5060}\x{5061}\x{5062}\x{5063}\x{5064}\x{5065}\x{5066}'
. '\x{5067}\x{5068}\x{5069}\x{506A}\x{506B}\x{506C}\x{506D}\x{506E}\x{506F}'
. '\x{5070}\x{5071}\x{5072}\x{5073}\x{5074}\x{5075}\x{5076}\x{5077}\x{5078}'
. '\x{5079}\x{507A}\x{507B}\x{507D}\x{507E}\x{507F}\x{5080}\x{5082}\x{5083}'
. '\x{5084}\x{5085}\x{5086}\x{5087}\x{5088}\x{5089}\x{508A}\x{508B}\x{508C}'
. '\x{508D}\x{508E}\x{508F}\x{5090}\x{5091}\x{5092}\x{5094}\x{5095}\x{5096}'
. '\x{5098}\x{5099}\x{509A}\x{509B}\x{509C}\x{509D}\x{509E}\x{50A2}\x{50A3}'
. '\x{50A4}\x{50A5}\x{50A6}\x{50A7}\x{50A8}\x{50A9}\x{50AA}\x{50AB}\x{50AC}'
. '\x{50AD}\x{50AE}\x{50AF}\x{50B0}\x{50B1}\x{50B2}\x{50B3}\x{50B4}\x{50B5}'
. '\x{50B6}\x{50B7}\x{50B8}\x{50BA}\x{50BB}\x{50BC}\x{50BD}\x{50BE}\x{50BF}'
. '\x{50C0}\x{50C1}\x{50C2}\x{50C4}\x{50C5}\x{50C6}\x{50C7}\x{50C8}\x{50C9}'
. '\x{50CA}\x{50CB}\x{50CC}\x{50CD}\x{50CE}\x{50CF}\x{50D0}\x{50D1}\x{50D2}'
. '\x{50D3}\x{50D4}\x{50D5}\x{50D6}\x{50D7}\x{50D9}\x{50DA}\x{50DB}\x{50DC}'
. '\x{50DD}\x{50DE}\x{50E0}\x{50E3}\x{50E4}\x{50E5}\x{50E6}\x{50E7}\x{50E8}'
. '\x{50E9}\x{50EA}\x{50EC}\x{50ED}\x{50EE}\x{50EF}\x{50F0}\x{50F1}\x{50F2}'
. '\x{50F3}\x{50F5}\x{50F6}\x{50F8}\x{50F9}\x{50FA}\x{50FB}\x{50FC}\x{50FD}'
. '\x{50FE}\x{50FF}\x{5100}\x{5101}\x{5102}\x{5103}\x{5104}\x{5105}\x{5106}'
. '\x{5107}\x{5108}\x{5109}\x{510A}\x{510B}\x{510C}\x{510D}\x{510E}\x{510F}'
. '\x{5110}\x{5111}\x{5112}\x{5113}\x{5114}\x{5115}\x{5116}\x{5117}\x{5118}'
. '\x{5119}\x{511A}\x{511C}\x{511D}\x{511E}\x{511F}\x{5120}\x{5121}\x{5122}'
. '\x{5123}\x{5124}\x{5125}\x{5126}\x{5127}\x{5129}\x{512A}\x{512C}\x{512D}'
. '\x{512E}\x{512F}\x{5130}\x{5131}\x{5132}\x{5133}\x{5134}\x{5135}\x{5136}'
. '\x{5137}\x{5138}\x{5139}\x{513A}\x{513B}\x{513C}\x{513D}\x{513E}\x{513F}'
. '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}'
. '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5151}\x{5152}\x{5154}\x{5155}'
. '\x{5156}\x{5157}\x{5159}\x{515A}\x{515B}\x{515C}\x{515D}\x{515E}\x{515F}'
. '\x{5161}\x{5162}\x{5163}\x{5165}\x{5166}\x{5167}\x{5168}\x{5169}\x{516A}'
. '\x{516B}\x{516C}\x{516D}\x{516E}\x{516F}\x{5170}\x{5171}\x{5173}\x{5174}'
. '\x{5175}\x{5176}\x{5177}\x{5178}\x{5179}\x{517A}\x{517B}\x{517C}\x{517D}'
. '\x{517F}\x{5180}\x{5181}\x{5182}\x{5185}\x{5186}\x{5187}\x{5188}\x{5189}'
. '\x{518A}\x{518B}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}\x{5193}'
. '\x{5194}\x{5195}\x{5196}\x{5197}\x{5198}\x{5199}\x{519A}\x{519B}\x{519C}'
. '\x{519D}\x{519E}\x{519F}\x{51A0}\x{51A2}\x{51A4}\x{51A5}\x{51A6}\x{51A7}'
. '\x{51A8}\x{51AA}\x{51AB}\x{51AC}\x{51AE}\x{51AF}\x{51B0}\x{51B1}\x{51B2}'
. '\x{51B3}\x{51B5}\x{51B6}\x{51B7}\x{51B9}\x{51BB}\x{51BC}\x{51BD}\x{51BE}'
. '\x{51BF}\x{51C0}\x{51C1}\x{51C3}\x{51C4}\x{51C5}\x{51C6}\x{51C7}\x{51C8}'
. '\x{51C9}\x{51CA}\x{51CB}\x{51CC}\x{51CD}\x{51CE}\x{51CF}\x{51D0}\x{51D1}'
. '\x{51D4}\x{51D5}\x{51D6}\x{51D7}\x{51D8}\x{51D9}\x{51DA}\x{51DB}\x{51DC}'
. '\x{51DD}\x{51DE}\x{51E0}\x{51E1}\x{51E2}\x{51E3}\x{51E4}\x{51E5}\x{51E7}'
. '\x{51E8}\x{51E9}\x{51EA}\x{51EB}\x{51ED}\x{51EF}\x{51F0}\x{51F1}\x{51F3}'
. '\x{51F4}\x{51F5}\x{51F6}\x{51F7}\x{51F8}\x{51F9}\x{51FA}\x{51FB}\x{51FC}'
. '\x{51FD}\x{51FE}\x{51FF}\x{5200}\x{5201}\x{5202}\x{5203}\x{5204}\x{5205}'
. '\x{5206}\x{5207}\x{5208}\x{5209}\x{520A}\x{520B}\x{520C}\x{520D}\x{520E}'
. '\x{520F}\x{5210}\x{5211}\x{5212}\x{5213}\x{5214}\x{5215}\x{5216}\x{5217}'
. '\x{5218}\x{5219}\x{521A}\x{521B}\x{521C}\x{521D}\x{521E}\x{521F}\x{5220}'
. '\x{5221}\x{5222}\x{5223}\x{5224}\x{5225}\x{5226}\x{5228}\x{5229}\x{522A}'
. '\x{522B}\x{522C}\x{522D}\x{522E}\x{522F}\x{5230}\x{5231}\x{5232}\x{5233}'
. '\x{5234}\x{5235}\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{523C}'
. '\x{523D}\x{523E}\x{523F}\x{5240}\x{5241}\x{5242}\x{5243}\x{5244}\x{5245}'
. '\x{5246}\x{5247}\x{5248}\x{5249}\x{524A}\x{524B}\x{524C}\x{524D}\x{524E}'
. '\x{5250}\x{5251}\x{5252}\x{5254}\x{5255}\x{5256}\x{5257}\x{5258}\x{5259}'
. '\x{525A}\x{525B}\x{525C}\x{525D}\x{525E}\x{525F}\x{5260}\x{5261}\x{5262}'
. '\x{5263}\x{5264}\x{5265}\x{5267}\x{5268}\x{5269}\x{526A}\x{526B}\x{526C}'
. '\x{526D}\x{526E}\x{526F}\x{5270}\x{5272}\x{5273}\x{5274}\x{5275}\x{5276}'
. '\x{5277}\x{5278}\x{527A}\x{527B}\x{527C}\x{527D}\x{527E}\x{527F}\x{5280}'
. '\x{5281}\x{5282}\x{5283}\x{5284}\x{5286}\x{5287}\x{5288}\x{5289}\x{528A}'
. '\x{528B}\x{528C}\x{528D}\x{528F}\x{5290}\x{5291}\x{5292}\x{5293}\x{5294}'
. '\x{5295}\x{5296}\x{5297}\x{5298}\x{5299}\x{529A}\x{529B}\x{529C}\x{529D}'
. '\x{529E}\x{529F}\x{52A0}\x{52A1}\x{52A2}\x{52A3}\x{52A5}\x{52A6}\x{52A7}'
. '\x{52A8}\x{52A9}\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52AE}\x{52AF}\x{52B0}'
. '\x{52B1}\x{52B2}\x{52B3}\x{52B4}\x{52B5}\x{52B6}\x{52B7}\x{52B8}\x{52B9}'
. '\x{52BA}\x{52BB}\x{52BC}\x{52BD}\x{52BE}\x{52BF}\x{52C0}\x{52C1}\x{52C2}'
. '\x{52C3}\x{52C6}\x{52C7}\x{52C9}\x{52CA}\x{52CB}\x{52CD}\x{52CF}\x{52D0}'
. '\x{52D2}\x{52D3}\x{52D5}\x{52D6}\x{52D7}\x{52D8}\x{52D9}\x{52DA}\x{52DB}'
. '\x{52DC}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}\x{52E4}\x{52E6}'
. '\x{52E7}\x{52E8}\x{52E9}\x{52EA}\x{52EB}\x{52EC}\x{52ED}\x{52EF}\x{52F0}'
. '\x{52F1}\x{52F2}\x{52F3}\x{52F4}\x{52F5}\x{52F6}\x{52F7}\x{52F8}\x{52F9}'
. '\x{52FA}\x{52FB}\x{52FC}\x{52FD}\x{52FE}\x{52FF}\x{5300}\x{5301}\x{5302}'
. '\x{5305}\x{5306}\x{5307}\x{5308}\x{5309}\x{530A}\x{530B}\x{530C}\x{530D}'
. '\x{530E}\x{530F}\x{5310}\x{5311}\x{5312}\x{5313}\x{5314}\x{5315}\x{5316}'
. '\x{5317}\x{5319}\x{531A}\x{531C}\x{531D}\x{531F}\x{5320}\x{5321}\x{5322}'
. '\x{5323}\x{5324}\x{5325}\x{5326}\x{5328}\x{532A}\x{532B}\x{532C}\x{532D}'
. '\x{532E}\x{532F}\x{5330}\x{5331}\x{5333}\x{5334}\x{5337}\x{5339}\x{533A}'
. '\x{533B}\x{533C}\x{533D}\x{533E}\x{533F}\x{5340}\x{5341}\x{5343}\x{5344}'
. '\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}\x{534A}\x{534B}\x{534C}\x{534D}'
. '\x{534E}\x{534F}\x{5350}\x{5351}\x{5352}\x{5353}\x{5354}\x{5355}\x{5356}'
. '\x{5357}\x{5358}\x{5359}\x{535A}\x{535C}\x{535E}\x{535F}\x{5360}\x{5361}'
. '\x{5362}\x{5363}\x{5364}\x{5365}\x{5366}\x{5367}\x{5369}\x{536B}\x{536C}'
. '\x{536E}\x{536F}\x{5370}\x{5371}\x{5372}\x{5373}\x{5374}\x{5375}\x{5376}'
. '\x{5377}\x{5378}\x{5379}\x{537A}\x{537B}\x{537C}\x{537D}\x{537E}\x{537F}'
. '\x{5381}\x{5382}\x{5383}\x{5384}\x{5385}\x{5386}\x{5387}\x{5388}\x{5389}'
. '\x{538A}\x{538B}\x{538C}\x{538D}\x{538E}\x{538F}\x{5390}\x{5391}\x{5392}'
. '\x{5393}\x{5394}\x{5395}\x{5396}\x{5397}\x{5398}\x{5399}\x{539A}\x{539B}'
. '\x{539C}\x{539D}\x{539E}\x{539F}\x{53A0}\x{53A2}\x{53A3}\x{53A4}\x{53A5}'
. '\x{53A6}\x{53A7}\x{53A8}\x{53A9}\x{53AC}\x{53AD}\x{53AE}\x{53B0}\x{53B1}'
. '\x{53B2}\x{53B3}\x{53B4}\x{53B5}\x{53B6}\x{53B7}\x{53B8}\x{53B9}\x{53BB}'
. '\x{53BC}\x{53BD}\x{53BE}\x{53BF}\x{53C0}\x{53C1}\x{53C2}\x{53C3}\x{53C4}'
. '\x{53C6}\x{53C7}\x{53C8}\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}'
. '\x{53D0}\x{53D1}\x{53D2}\x{53D3}\x{53D4}\x{53D5}\x{53D6}\x{53D7}\x{53D8}'
. '\x{53D9}\x{53DB}\x{53DC}\x{53DF}\x{53E0}\x{53E1}\x{53E2}\x{53E3}\x{53E4}'
. '\x{53E5}\x{53E6}\x{53E8}\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}'
. '\x{53EF}\x{53F0}\x{53F1}\x{53F2}\x{53F3}\x{53F4}\x{53F5}\x{53F6}\x{53F7}'
. '\x{53F8}\x{53F9}\x{53FA}\x{53FB}\x{53FC}\x{53FD}\x{53FE}\x{5401}\x{5402}'
. '\x{5403}\x{5404}\x{5405}\x{5406}\x{5407}\x{5408}\x{5409}\x{540A}\x{540B}'
. '\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}\x{5411}\x{5412}\x{5413}\x{5414}'
. '\x{5415}\x{5416}\x{5417}\x{5418}\x{5419}\x{541B}\x{541C}\x{541D}\x{541E}'
. '\x{541F}\x{5420}\x{5421}\x{5423}\x{5424}\x{5425}\x{5426}\x{5427}\x{5428}'
. '\x{5429}\x{542A}\x{542B}\x{542C}\x{542D}\x{542E}\x{542F}\x{5430}\x{5431}'
. '\x{5432}\x{5433}\x{5434}\x{5435}\x{5436}\x{5437}\x{5438}\x{5439}\x{543A}'
. '\x{543B}\x{543C}\x{543D}\x{543E}\x{543F}\x{5440}\x{5441}\x{5442}\x{5443}'
. '\x{5444}\x{5445}\x{5446}\x{5447}\x{5448}\x{5449}\x{544A}\x{544B}\x{544D}'
. '\x{544E}\x{544F}\x{5450}\x{5451}\x{5452}\x{5453}\x{5454}\x{5455}\x{5456}'
. '\x{5457}\x{5458}\x{5459}\x{545A}\x{545B}\x{545C}\x{545E}\x{545F}\x{5460}'
. '\x{5461}\x{5462}\x{5463}\x{5464}\x{5465}\x{5466}\x{5467}\x{5468}\x{546A}'
. '\x{546B}\x{546C}\x{546D}\x{546E}\x{546F}\x{5470}\x{5471}\x{5472}\x{5473}'
. '\x{5474}\x{5475}\x{5476}\x{5477}\x{5478}\x{5479}\x{547A}\x{547B}\x{547C}'
. '\x{547D}\x{547E}\x{547F}\x{5480}\x{5481}\x{5482}\x{5483}\x{5484}\x{5485}'
. '\x{5486}\x{5487}\x{5488}\x{5489}\x{548B}\x{548C}\x{548D}\x{548E}\x{548F}'
. '\x{5490}\x{5491}\x{5492}\x{5493}\x{5494}\x{5495}\x{5496}\x{5497}\x{5498}'
. '\x{5499}\x{549A}\x{549B}\x{549C}\x{549D}\x{549E}\x{549F}\x{54A0}\x{54A1}'
. '\x{54A2}\x{54A3}\x{54A4}\x{54A5}\x{54A6}\x{54A7}\x{54A8}\x{54A9}\x{54AA}'
. '\x{54AB}\x{54AC}\x{54AD}\x{54AE}\x{54AF}\x{54B0}\x{54B1}\x{54B2}\x{54B3}'
. '\x{54B4}\x{54B6}\x{54B7}\x{54B8}\x{54B9}\x{54BA}\x{54BB}\x{54BC}\x{54BD}'
. '\x{54BE}\x{54BF}\x{54C0}\x{54C1}\x{54C2}\x{54C3}\x{54C4}\x{54C5}\x{54C6}'
. '\x{54C7}\x{54C8}\x{54C9}\x{54CA}\x{54CB}\x{54CC}\x{54CD}\x{54CE}\x{54CF}'
. '\x{54D0}\x{54D1}\x{54D2}\x{54D3}\x{54D4}\x{54D5}\x{54D6}\x{54D7}\x{54D8}'
. '\x{54D9}\x{54DA}\x{54DB}\x{54DC}\x{54DD}\x{54DE}\x{54DF}\x{54E0}\x{54E1}'
. '\x{54E2}\x{54E3}\x{54E4}\x{54E5}\x{54E6}\x{54E7}\x{54E8}\x{54E9}\x{54EA}'
. '\x{54EB}\x{54EC}\x{54ED}\x{54EE}\x{54EF}\x{54F0}\x{54F1}\x{54F2}\x{54F3}'
. '\x{54F4}\x{54F5}\x{54F7}\x{54F8}\x{54F9}\x{54FA}\x{54FB}\x{54FC}\x{54FD}'
. '\x{54FE}\x{54FF}\x{5500}\x{5501}\x{5502}\x{5503}\x{5504}\x{5505}\x{5506}'
. '\x{5507}\x{5508}\x{5509}\x{550A}\x{550B}\x{550C}\x{550D}\x{550E}\x{550F}'
. '\x{5510}\x{5511}\x{5512}\x{5513}\x{5514}\x{5516}\x{5517}\x{551A}\x{551B}'
. '\x{551C}\x{551D}\x{551E}\x{551F}\x{5520}\x{5521}\x{5522}\x{5523}\x{5524}'
. '\x{5525}\x{5526}\x{5527}\x{5528}\x{5529}\x{552A}\x{552B}\x{552C}\x{552D}'
. '\x{552E}\x{552F}\x{5530}\x{5531}\x{5532}\x{5533}\x{5534}\x{5535}\x{5536}'
. '\x{5537}\x{5538}\x{5539}\x{553A}\x{553B}\x{553C}\x{553D}\x{553E}\x{553F}'
. '\x{5540}\x{5541}\x{5542}\x{5543}\x{5544}\x{5545}\x{5546}\x{5548}\x{5549}'
. '\x{554A}\x{554B}\x{554C}\x{554D}\x{554E}\x{554F}\x{5550}\x{5551}\x{5552}'
. '\x{5553}\x{5554}\x{5555}\x{5556}\x{5557}\x{5558}\x{5559}\x{555A}\x{555B}'
. '\x{555C}\x{555D}\x{555E}\x{555F}\x{5561}\x{5562}\x{5563}\x{5564}\x{5565}'
. '\x{5566}\x{5567}\x{5568}\x{5569}\x{556A}\x{556B}\x{556C}\x{556D}\x{556E}'
. '\x{556F}\x{5570}\x{5571}\x{5572}\x{5573}\x{5574}\x{5575}\x{5576}\x{5577}'
. '\x{5578}\x{5579}\x{557B}\x{557C}\x{557D}\x{557E}\x{557F}\x{5580}\x{5581}'
. '\x{5582}\x{5583}\x{5584}\x{5585}\x{5586}\x{5587}\x{5588}\x{5589}\x{558A}'
. '\x{558B}\x{558C}\x{558D}\x{558E}\x{558F}\x{5590}\x{5591}\x{5592}\x{5593}'
. '\x{5594}\x{5595}\x{5596}\x{5597}\x{5598}\x{5599}\x{559A}\x{559B}\x{559C}'
. '\x{559D}\x{559E}\x{559F}\x{55A0}\x{55A1}\x{55A2}\x{55A3}\x{55A4}\x{55A5}'
. '\x{55A6}\x{55A7}\x{55A8}\x{55A9}\x{55AA}\x{55AB}\x{55AC}\x{55AD}\x{55AE}'
. '\x{55AF}\x{55B0}\x{55B1}\x{55B2}\x{55B3}\x{55B4}\x{55B5}\x{55B6}\x{55B7}'
. '\x{55B8}\x{55B9}\x{55BA}\x{55BB}\x{55BC}\x{55BD}\x{55BE}\x{55BF}\x{55C0}'
. '\x{55C1}\x{55C2}\x{55C3}\x{55C4}\x{55C5}\x{55C6}\x{55C7}\x{55C8}\x{55C9}'
. '\x{55CA}\x{55CB}\x{55CC}\x{55CD}\x{55CE}\x{55CF}\x{55D0}\x{55D1}\x{55D2}'
. '\x{55D3}\x{55D4}\x{55D5}\x{55D6}\x{55D7}\x{55D8}\x{55D9}\x{55DA}\x{55DB}'
. '\x{55DC}\x{55DD}\x{55DE}\x{55DF}\x{55E1}\x{55E2}\x{55E3}\x{55E4}\x{55E5}'
. '\x{55E6}\x{55E7}\x{55E8}\x{55E9}\x{55EA}\x{55EB}\x{55EC}\x{55ED}\x{55EE}'
. '\x{55EF}\x{55F0}\x{55F1}\x{55F2}\x{55F3}\x{55F4}\x{55F5}\x{55F6}\x{55F7}'
. '\x{55F9}\x{55FA}\x{55FB}\x{55FC}\x{55FD}\x{55FE}\x{55FF}\x{5600}\x{5601}'
. '\x{5602}\x{5603}\x{5604}\x{5606}\x{5607}\x{5608}\x{5609}\x{560C}\x{560D}'
. '\x{560E}\x{560F}\x{5610}\x{5611}\x{5612}\x{5613}\x{5614}\x{5615}\x{5616}'
. '\x{5617}\x{5618}\x{5619}\x{561A}\x{561B}\x{561C}\x{561D}\x{561E}\x{561F}'
. '\x{5621}\x{5622}\x{5623}\x{5624}\x{5625}\x{5626}\x{5627}\x{5628}\x{5629}'
. '\x{562A}\x{562C}\x{562D}\x{562E}\x{562F}\x{5630}\x{5631}\x{5632}\x{5633}'
. '\x{5634}\x{5635}\x{5636}\x{5638}\x{5639}\x{563A}\x{563B}\x{563D}\x{563E}'
. '\x{563F}\x{5640}\x{5641}\x{5642}\x{5643}\x{5645}\x{5646}\x{5647}\x{5648}'
. '\x{5649}\x{564A}\x{564C}\x{564D}\x{564E}\x{564F}\x{5650}\x{5652}\x{5653}'
. '\x{5654}\x{5655}\x{5657}\x{5658}\x{5659}\x{565A}\x{565B}\x{565C}\x{565D}'
. '\x{565E}\x{5660}\x{5662}\x{5663}\x{5664}\x{5665}\x{5666}\x{5667}\x{5668}'
. '\x{5669}\x{566A}\x{566B}\x{566C}\x{566D}\x{566E}\x{566F}\x{5670}\x{5671}'
. '\x{5672}\x{5673}\x{5674}\x{5676}\x{5677}\x{5678}\x{5679}\x{567A}\x{567B}'
. '\x{567C}\x{567E}\x{567F}\x{5680}\x{5681}\x{5682}\x{5683}\x{5684}\x{5685}'
. '\x{5686}\x{5687}\x{568A}\x{568C}\x{568D}\x{568E}\x{568F}\x{5690}\x{5691}'
. '\x{5692}\x{5693}\x{5694}\x{5695}\x{5697}\x{5698}\x{5699}\x{569A}\x{569B}'
. '\x{569C}\x{569D}\x{569F}\x{56A0}\x{56A1}\x{56A3}\x{56A4}\x{56A5}\x{56A6}'
. '\x{56A7}\x{56A8}\x{56A9}\x{56AA}\x{56AB}\x{56AC}\x{56AD}\x{56AE}\x{56AF}'
. '\x{56B0}\x{56B1}\x{56B2}\x{56B3}\x{56B4}\x{56B5}\x{56B6}\x{56B7}\x{56B8}'
. '\x{56B9}\x{56BB}\x{56BC}\x{56BD}\x{56BE}\x{56BF}\x{56C0}\x{56C1}\x{56C2}'
. '\x{56C3}\x{56C4}\x{56C5}\x{56C6}\x{56C7}\x{56C8}\x{56C9}\x{56CA}\x{56CB}'
. '\x{56CC}\x{56CD}\x{56CE}\x{56D0}\x{56D1}\x{56D2}\x{56D3}\x{56D4}\x{56D5}'
. '\x{56D6}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DC}\x{56DD}\x{56DE}\x{56DF}'
. '\x{56E0}\x{56E1}\x{56E2}\x{56E3}\x{56E4}\x{56E5}\x{56E7}\x{56E8}\x{56E9}'
. '\x{56EA}\x{56EB}\x{56EC}\x{56ED}\x{56EE}\x{56EF}\x{56F0}\x{56F1}\x{56F2}'
. '\x{56F3}\x{56F4}\x{56F5}\x{56F7}\x{56F9}\x{56FA}\x{56FD}\x{56FE}\x{56FF}'
. '\x{5700}\x{5701}\x{5702}\x{5703}\x{5704}\x{5706}\x{5707}\x{5708}\x{5709}'
. '\x{570A}\x{570B}\x{570C}\x{570D}\x{570E}\x{570F}\x{5710}\x{5712}\x{5713}'
. '\x{5714}\x{5715}\x{5716}\x{5718}\x{5719}\x{571A}\x{571B}\x{571C}\x{571D}'
. '\x{571E}\x{571F}\x{5720}\x{5722}\x{5723}\x{5725}\x{5726}\x{5727}\x{5728}'
. '\x{5729}\x{572A}\x{572B}\x{572C}\x{572D}\x{572E}\x{572F}\x{5730}\x{5731}'
. '\x{5732}\x{5733}\x{5734}\x{5735}\x{5736}\x{5737}\x{5738}\x{5739}\x{573A}'
. '\x{573B}\x{573C}\x{573E}\x{573F}\x{5740}\x{5741}\x{5742}\x{5744}\x{5745}'
. '\x{5746}\x{5747}\x{5749}\x{574A}\x{574B}\x{574C}\x{574D}\x{574E}\x{574F}'
. '\x{5750}\x{5751}\x{5752}\x{5753}\x{5754}\x{5757}\x{5759}\x{575A}\x{575B}'
. '\x{575C}\x{575D}\x{575E}\x{575F}\x{5760}\x{5761}\x{5762}\x{5764}\x{5765}'
. '\x{5766}\x{5767}\x{5768}\x{5769}\x{576A}\x{576B}\x{576C}\x{576D}\x{576F}'
. '\x{5770}\x{5771}\x{5772}\x{5773}\x{5774}\x{5775}\x{5776}\x{5777}\x{5779}'
. '\x{577A}\x{577B}\x{577C}\x{577D}\x{577E}\x{577F}\x{5780}\x{5782}\x{5783}'
. '\x{5784}\x{5785}\x{5786}\x{5788}\x{5789}\x{578A}\x{578B}\x{578C}\x{578D}'
. '\x{578E}\x{578F}\x{5790}\x{5791}\x{5792}\x{5793}\x{5794}\x{5795}\x{5797}'
. '\x{5798}\x{5799}\x{579A}\x{579B}\x{579C}\x{579D}\x{579E}\x{579F}\x{57A0}'
. '\x{57A1}\x{57A2}\x{57A3}\x{57A4}\x{57A5}\x{57A6}\x{57A7}\x{57A9}\x{57AA}'
. '\x{57AB}\x{57AC}\x{57AD}\x{57AE}\x{57AF}\x{57B0}\x{57B1}\x{57B2}\x{57B3}'
. '\x{57B4}\x{57B5}\x{57B6}\x{57B7}\x{57B8}\x{57B9}\x{57BA}\x{57BB}\x{57BC}'
. '\x{57BD}\x{57BE}\x{57BF}\x{57C0}\x{57C1}\x{57C2}\x{57C3}\x{57C4}\x{57C5}'
. '\x{57C6}\x{57C7}\x{57C8}\x{57C9}\x{57CB}\x{57CC}\x{57CD}\x{57CE}\x{57CF}'
. '\x{57D0}\x{57D2}\x{57D3}\x{57D4}\x{57D5}\x{57D6}\x{57D8}\x{57D9}\x{57DA}'
. '\x{57DC}\x{57DD}\x{57DF}\x{57E0}\x{57E1}\x{57E2}\x{57E3}\x{57E4}\x{57E5}'
. '\x{57E6}\x{57E7}\x{57E8}\x{57E9}\x{57EA}\x{57EB}\x{57EC}\x{57ED}\x{57EE}'
. '\x{57EF}\x{57F0}\x{57F1}\x{57F2}\x{57F3}\x{57F4}\x{57F5}\x{57F6}\x{57F7}'
. '\x{57F8}\x{57F9}\x{57FA}\x{57FB}\x{57FC}\x{57FD}\x{57FE}\x{57FF}\x{5800}'
. '\x{5801}\x{5802}\x{5803}\x{5804}\x{5805}\x{5806}\x{5807}\x{5808}\x{5809}'
. '\x{580A}\x{580B}\x{580C}\x{580D}\x{580E}\x{580F}\x{5810}\x{5811}\x{5812}'
. '\x{5813}\x{5814}\x{5815}\x{5816}\x{5819}\x{581A}\x{581B}\x{581C}\x{581D}'
. '\x{581E}\x{581F}\x{5820}\x{5821}\x{5822}\x{5823}\x{5824}\x{5825}\x{5826}'
. '\x{5827}\x{5828}\x{5829}\x{582A}\x{582B}\x{582C}\x{582D}\x{582E}\x{582F}'
. '\x{5830}\x{5831}\x{5832}\x{5833}\x{5834}\x{5835}\x{5836}\x{5837}\x{5838}'
. '\x{5839}\x{583A}\x{583B}\x{583C}\x{583D}\x{583E}\x{583F}\x{5840}\x{5842}'
. '\x{5843}\x{5844}\x{5845}\x{5846}\x{5847}\x{5848}\x{5849}\x{584A}\x{584B}'
. '\x{584C}\x{584D}\x{584E}\x{584F}\x{5851}\x{5852}\x{5853}\x{5854}\x{5855}'
. '\x{5857}\x{5858}\x{5859}\x{585A}\x{585B}\x{585C}\x{585D}\x{585E}\x{585F}'
. '\x{5861}\x{5862}\x{5863}\x{5864}\x{5865}\x{5868}\x{5869}\x{586A}\x{586B}'
. '\x{586C}\x{586D}\x{586E}\x{586F}\x{5870}\x{5871}\x{5872}\x{5873}\x{5874}'
. '\x{5875}\x{5876}\x{5878}\x{5879}\x{587A}\x{587B}\x{587C}\x{587D}\x{587E}'
. '\x{587F}\x{5880}\x{5881}\x{5882}\x{5883}\x{5884}\x{5885}\x{5886}\x{5887}'
. '\x{5888}\x{5889}\x{588A}\x{588B}\x{588C}\x{588D}\x{588E}\x{588F}\x{5890}'
. '\x{5891}\x{5892}\x{5893}\x{5894}\x{5896}\x{5897}\x{5898}\x{5899}\x{589A}'
. '\x{589B}\x{589C}\x{589D}\x{589E}\x{589F}\x{58A0}\x{58A1}\x{58A2}\x{58A3}'
. '\x{58A4}\x{58A5}\x{58A6}\x{58A7}\x{58A8}\x{58A9}\x{58AB}\x{58AC}\x{58AD}'
. '\x{58AE}\x{58AF}\x{58B0}\x{58B1}\x{58B2}\x{58B3}\x{58B4}\x{58B7}\x{58B8}'
. '\x{58B9}\x{58BA}\x{58BB}\x{58BC}\x{58BD}\x{58BE}\x{58BF}\x{58C1}\x{58C2}'
. '\x{58C5}\x{58C6}\x{58C7}\x{58C8}\x{58C9}\x{58CA}\x{58CB}\x{58CE}\x{58CF}'
. '\x{58D1}\x{58D2}\x{58D3}\x{58D4}\x{58D5}\x{58D6}\x{58D7}\x{58D8}\x{58D9}'
. '\x{58DA}\x{58DB}\x{58DD}\x{58DE}\x{58DF}\x{58E0}\x{58E2}\x{58E3}\x{58E4}'
. '\x{58E5}\x{58E7}\x{58E8}\x{58E9}\x{58EA}\x{58EB}\x{58EC}\x{58ED}\x{58EE}'
. '\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F3}\x{58F4}\x{58F6}\x{58F7}\x{58F8}'
. '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{58FE}\x{58FF}\x{5900}\x{5902}'
. '\x{5903}\x{5904}\x{5906}\x{5907}\x{5909}\x{590A}\x{590B}\x{590C}\x{590D}'
. '\x{590E}\x{590F}\x{5910}\x{5912}\x{5914}\x{5915}\x{5916}\x{5917}\x{5918}'
. '\x{5919}\x{591A}\x{591B}\x{591C}\x{591D}\x{591E}\x{591F}\x{5920}\x{5921}'
. '\x{5922}\x{5924}\x{5925}\x{5926}\x{5927}\x{5928}\x{5929}\x{592A}\x{592B}'
. '\x{592C}\x{592D}\x{592E}\x{592F}\x{5930}\x{5931}\x{5932}\x{5934}\x{5935}'
. '\x{5937}\x{5938}\x{5939}\x{593A}\x{593B}\x{593C}\x{593D}\x{593E}\x{593F}'
. '\x{5940}\x{5941}\x{5942}\x{5943}\x{5944}\x{5945}\x{5946}\x{5947}\x{5948}'
. '\x{5949}\x{594A}\x{594B}\x{594C}\x{594D}\x{594E}\x{594F}\x{5950}\x{5951}'
. '\x{5952}\x{5953}\x{5954}\x{5955}\x{5956}\x{5957}\x{5958}\x{595A}\x{595C}'
. '\x{595D}\x{595E}\x{595F}\x{5960}\x{5961}\x{5962}\x{5963}\x{5964}\x{5965}'
. '\x{5966}\x{5967}\x{5968}\x{5969}\x{596A}\x{596B}\x{596C}\x{596D}\x{596E}'
. '\x{596F}\x{5970}\x{5971}\x{5972}\x{5973}\x{5974}\x{5975}\x{5976}\x{5977}'
. '\x{5978}\x{5979}\x{597A}\x{597B}\x{597C}\x{597D}\x{597E}\x{597F}\x{5980}'
. '\x{5981}\x{5982}\x{5983}\x{5984}\x{5985}\x{5986}\x{5987}\x{5988}\x{5989}'
. '\x{598A}\x{598B}\x{598C}\x{598D}\x{598E}\x{598F}\x{5990}\x{5991}\x{5992}'
. '\x{5993}\x{5994}\x{5995}\x{5996}\x{5997}\x{5998}\x{5999}\x{599A}\x{599C}'
. '\x{599D}\x{599E}\x{599F}\x{59A0}\x{59A1}\x{59A2}\x{59A3}\x{59A4}\x{59A5}'
. '\x{59A6}\x{59A7}\x{59A8}\x{59A9}\x{59AA}\x{59AB}\x{59AC}\x{59AD}\x{59AE}'
. '\x{59AF}\x{59B0}\x{59B1}\x{59B2}\x{59B3}\x{59B4}\x{59B5}\x{59B6}\x{59B8}'
. '\x{59B9}\x{59BA}\x{59BB}\x{59BC}\x{59BD}\x{59BE}\x{59BF}\x{59C0}\x{59C1}'
. '\x{59C2}\x{59C3}\x{59C4}\x{59C5}\x{59C6}\x{59C7}\x{59C8}\x{59C9}\x{59CA}'
. '\x{59CB}\x{59CC}\x{59CD}\x{59CE}\x{59CF}\x{59D0}\x{59D1}\x{59D2}\x{59D3}'
. '\x{59D4}\x{59D5}\x{59D6}\x{59D7}\x{59D8}\x{59D9}\x{59DA}\x{59DB}\x{59DC}'
. '\x{59DD}\x{59DE}\x{59DF}\x{59E0}\x{59E1}\x{59E2}\x{59E3}\x{59E4}\x{59E5}'
. '\x{59E6}\x{59E8}\x{59E9}\x{59EA}\x{59EB}\x{59EC}\x{59ED}\x{59EE}\x{59EF}'
. '\x{59F0}\x{59F1}\x{59F2}\x{59F3}\x{59F4}\x{59F5}\x{59F6}\x{59F7}\x{59F8}'
. '\x{59F9}\x{59FA}\x{59FB}\x{59FC}\x{59FD}\x{59FE}\x{59FF}\x{5A00}\x{5A01}'
. '\x{5A02}\x{5A03}\x{5A04}\x{5A05}\x{5A06}\x{5A07}\x{5A08}\x{5A09}\x{5A0A}'
. '\x{5A0B}\x{5A0C}\x{5A0D}\x{5A0E}\x{5A0F}\x{5A10}\x{5A11}\x{5A12}\x{5A13}'
. '\x{5A14}\x{5A15}\x{5A16}\x{5A17}\x{5A18}\x{5A19}\x{5A1A}\x{5A1B}\x{5A1C}'
. '\x{5A1D}\x{5A1E}\x{5A1F}\x{5A20}\x{5A21}\x{5A22}\x{5A23}\x{5A25}\x{5A27}'
. '\x{5A28}\x{5A29}\x{5A2A}\x{5A2B}\x{5A2D}\x{5A2E}\x{5A2F}\x{5A31}\x{5A32}'
. '\x{5A33}\x{5A34}\x{5A35}\x{5A36}\x{5A37}\x{5A38}\x{5A39}\x{5A3A}\x{5A3B}'
. '\x{5A3C}\x{5A3D}\x{5A3E}\x{5A3F}\x{5A40}\x{5A41}\x{5A42}\x{5A43}\x{5A44}'
. '\x{5A45}\x{5A46}\x{5A47}\x{5A48}\x{5A49}\x{5A4A}\x{5A4B}\x{5A4C}\x{5A4D}'
. '\x{5A4E}\x{5A4F}\x{5A50}\x{5A51}\x{5A52}\x{5A53}\x{5A55}\x{5A56}\x{5A57}'
. '\x{5A58}\x{5A5A}\x{5A5B}\x{5A5C}\x{5A5D}\x{5A5E}\x{5A5F}\x{5A60}\x{5A61}'
. '\x{5A62}\x{5A63}\x{5A64}\x{5A65}\x{5A66}\x{5A67}\x{5A68}\x{5A69}\x{5A6A}'
. '\x{5A6B}\x{5A6C}\x{5A6D}\x{5A6E}\x{5A70}\x{5A72}\x{5A73}\x{5A74}\x{5A75}'
. '\x{5A76}\x{5A77}\x{5A78}\x{5A79}\x{5A7A}\x{5A7B}\x{5A7C}\x{5A7D}\x{5A7E}'
. '\x{5A7F}\x{5A80}\x{5A81}\x{5A82}\x{5A83}\x{5A84}\x{5A85}\x{5A86}\x{5A88}'
. '\x{5A89}\x{5A8A}\x{5A8B}\x{5A8C}\x{5A8E}\x{5A8F}\x{5A90}\x{5A91}\x{5A92}'
. '\x{5A93}\x{5A94}\x{5A95}\x{5A96}\x{5A97}\x{5A98}\x{5A99}\x{5A9A}\x{5A9B}'
. '\x{5A9C}\x{5A9D}\x{5A9E}\x{5A9F}\x{5AA0}\x{5AA1}\x{5AA2}\x{5AA3}\x{5AA4}'
. '\x{5AA5}\x{5AA6}\x{5AA7}\x{5AA8}\x{5AA9}\x{5AAA}\x{5AAC}\x{5AAD}\x{5AAE}'
. '\x{5AAF}\x{5AB0}\x{5AB1}\x{5AB2}\x{5AB3}\x{5AB4}\x{5AB5}\x{5AB6}\x{5AB7}'
. '\x{5AB8}\x{5AB9}\x{5ABA}\x{5ABB}\x{5ABC}\x{5ABD}\x{5ABE}\x{5ABF}\x{5AC0}'
. '\x{5AC1}\x{5AC2}\x{5AC3}\x{5AC4}\x{5AC5}\x{5AC6}\x{5AC7}\x{5AC8}\x{5AC9}'
. '\x{5ACA}\x{5ACB}\x{5ACC}\x{5ACD}\x{5ACE}\x{5ACF}\x{5AD1}\x{5AD2}\x{5AD4}'
. '\x{5AD5}\x{5AD6}\x{5AD7}\x{5AD8}\x{5AD9}\x{5ADA}\x{5ADB}\x{5ADC}\x{5ADD}'
. '\x{5ADE}\x{5ADF}\x{5AE0}\x{5AE1}\x{5AE2}\x{5AE3}\x{5AE4}\x{5AE5}\x{5AE6}'
. '\x{5AE7}\x{5AE8}\x{5AE9}\x{5AEA}\x{5AEB}\x{5AEC}\x{5AED}\x{5AEE}\x{5AF1}'
. '\x{5AF2}\x{5AF3}\x{5AF4}\x{5AF5}\x{5AF6}\x{5AF7}\x{5AF8}\x{5AF9}\x{5AFA}'
. '\x{5AFB}\x{5AFC}\x{5AFD}\x{5AFE}\x{5AFF}\x{5B00}\x{5B01}\x{5B02}\x{5B03}'
. '\x{5B04}\x{5B05}\x{5B06}\x{5B07}\x{5B08}\x{5B09}\x{5B0B}\x{5B0C}\x{5B0E}'
. '\x{5B0F}\x{5B10}\x{5B11}\x{5B12}\x{5B13}\x{5B14}\x{5B15}\x{5B16}\x{5B17}'
. '\x{5B18}\x{5B19}\x{5B1A}\x{5B1B}\x{5B1C}\x{5B1D}\x{5B1E}\x{5B1F}\x{5B20}'
. '\x{5B21}\x{5B22}\x{5B23}\x{5B24}\x{5B25}\x{5B26}\x{5B27}\x{5B28}\x{5B29}'
. '\x{5B2A}\x{5B2B}\x{5B2C}\x{5B2D}\x{5B2E}\x{5B2F}\x{5B30}\x{5B31}\x{5B32}'
. '\x{5B33}\x{5B34}\x{5B35}\x{5B36}\x{5B37}\x{5B38}\x{5B3A}\x{5B3B}\x{5B3C}'
. '\x{5B3D}\x{5B3E}\x{5B3F}\x{5B40}\x{5B41}\x{5B42}\x{5B43}\x{5B44}\x{5B45}'
. '\x{5B47}\x{5B48}\x{5B49}\x{5B4A}\x{5B4B}\x{5B4C}\x{5B4D}\x{5B4E}\x{5B50}'
. '\x{5B51}\x{5B53}\x{5B54}\x{5B55}\x{5B56}\x{5B57}\x{5B58}\x{5B59}\x{5B5A}'
. '\x{5B5B}\x{5B5C}\x{5B5D}\x{5B5E}\x{5B5F}\x{5B62}\x{5B63}\x{5B64}\x{5B65}'
. '\x{5B66}\x{5B67}\x{5B68}\x{5B69}\x{5B6A}\x{5B6B}\x{5B6C}\x{5B6D}\x{5B6E}'
. '\x{5B70}\x{5B71}\x{5B72}\x{5B73}\x{5B74}\x{5B75}\x{5B76}\x{5B77}\x{5B78}'
. '\x{5B7A}\x{5B7B}\x{5B7C}\x{5B7D}\x{5B7F}\x{5B80}\x{5B81}\x{5B82}\x{5B83}'
. '\x{5B84}\x{5B85}\x{5B87}\x{5B88}\x{5B89}\x{5B8A}\x{5B8B}\x{5B8C}\x{5B8D}'
. '\x{5B8E}\x{5B8F}\x{5B91}\x{5B92}\x{5B93}\x{5B94}\x{5B95}\x{5B96}\x{5B97}'
. '\x{5B98}\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9E}\x{5B9F}\x{5BA0}'
. '\x{5BA1}\x{5BA2}\x{5BA3}\x{5BA4}\x{5BA5}\x{5BA6}\x{5BA7}\x{5BA8}\x{5BAA}'
. '\x{5BAB}\x{5BAC}\x{5BAD}\x{5BAE}\x{5BAF}\x{5BB0}\x{5BB1}\x{5BB3}\x{5BB4}'
. '\x{5BB5}\x{5BB6}\x{5BB8}\x{5BB9}\x{5BBA}\x{5BBB}\x{5BBD}\x{5BBE}\x{5BBF}'
. '\x{5BC0}\x{5BC1}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BCA}'
. '\x{5BCB}\x{5BCC}\x{5BCD}\x{5BCE}\x{5BCF}\x{5BD0}\x{5BD1}\x{5BD2}\x{5BD3}'
. '\x{5BD4}\x{5BD5}\x{5BD6}\x{5BD8}\x{5BD9}\x{5BDB}\x{5BDC}\x{5BDD}\x{5BDE}'
. '\x{5BDF}\x{5BE0}\x{5BE1}\x{5BE2}\x{5BE3}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}'
. '\x{5BE8}\x{5BE9}\x{5BEA}\x{5BEB}\x{5BEC}\x{5BED}\x{5BEE}\x{5BEF}\x{5BF0}'
. '\x{5BF1}\x{5BF2}\x{5BF3}\x{5BF4}\x{5BF5}\x{5BF6}\x{5BF7}\x{5BF8}\x{5BF9}'
. '\x{5BFA}\x{5BFB}\x{5BFC}\x{5BFD}\x{5BFF}\x{5C01}\x{5C03}\x{5C04}\x{5C05}'
. '\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}\x{5C0B}\x{5C0C}\x{5C0D}\x{5C0E}'
. '\x{5C0F}\x{5C10}\x{5C11}\x{5C12}\x{5C13}\x{5C14}\x{5C15}\x{5C16}\x{5C17}'
. '\x{5C18}\x{5C19}\x{5C1A}\x{5C1C}\x{5C1D}\x{5C1E}\x{5C1F}\x{5C20}\x{5C21}'
. '\x{5C22}\x{5C24}\x{5C25}\x{5C27}\x{5C28}\x{5C2A}\x{5C2B}\x{5C2C}\x{5C2D}'
. '\x{5C2E}\x{5C2F}\x{5C30}\x{5C31}\x{5C32}\x{5C33}\x{5C34}\x{5C35}\x{5C37}'
. '\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}'
. '\x{5C41}\x{5C42}\x{5C43}\x{5C44}\x{5C45}\x{5C46}\x{5C47}\x{5C48}\x{5C49}'
. '\x{5C4A}\x{5C4B}\x{5C4C}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C52}'
. '\x{5C53}\x{5C54}\x{5C55}\x{5C56}\x{5C57}\x{5C58}\x{5C59}\x{5C5B}\x{5C5C}'
. '\x{5C5D}\x{5C5E}\x{5C5F}\x{5C60}\x{5C61}\x{5C62}\x{5C63}\x{5C64}\x{5C65}'
. '\x{5C66}\x{5C67}\x{5C68}\x{5C69}\x{5C6A}\x{5C6B}\x{5C6C}\x{5C6D}\x{5C6E}'
. '\x{5C6F}\x{5C70}\x{5C71}\x{5C72}\x{5C73}\x{5C74}\x{5C75}\x{5C76}\x{5C77}'
. '\x{5C78}\x{5C79}\x{5C7A}\x{5C7B}\x{5C7C}\x{5C7D}\x{5C7E}\x{5C7F}\x{5C80}'
. '\x{5C81}\x{5C82}\x{5C83}\x{5C84}\x{5C86}\x{5C87}\x{5C88}\x{5C89}\x{5C8A}'
. '\x{5C8B}\x{5C8C}\x{5C8D}\x{5C8E}\x{5C8F}\x{5C90}\x{5C91}\x{5C92}\x{5C93}'
. '\x{5C94}\x{5C95}\x{5C96}\x{5C97}\x{5C98}\x{5C99}\x{5C9A}\x{5C9B}\x{5C9C}'
. '\x{5C9D}\x{5C9E}\x{5C9F}\x{5CA0}\x{5CA1}\x{5CA2}\x{5CA3}\x{5CA4}\x{5CA5}'
. '\x{5CA6}\x{5CA7}\x{5CA8}\x{5CA9}\x{5CAA}\x{5CAB}\x{5CAC}\x{5CAD}\x{5CAE}'
. '\x{5CAF}\x{5CB0}\x{5CB1}\x{5CB2}\x{5CB3}\x{5CB5}\x{5CB6}\x{5CB7}\x{5CB8}'
. '\x{5CBA}\x{5CBB}\x{5CBC}\x{5CBD}\x{5CBE}\x{5CBF}\x{5CC1}\x{5CC2}\x{5CC3}'
. '\x{5CC4}\x{5CC5}\x{5CC6}\x{5CC7}\x{5CC8}\x{5CC9}\x{5CCA}\x{5CCB}\x{5CCC}'
. '\x{5CCD}\x{5CCE}\x{5CCF}\x{5CD0}\x{5CD1}\x{5CD2}\x{5CD3}\x{5CD4}\x{5CD6}'
. '\x{5CD7}\x{5CD8}\x{5CD9}\x{5CDA}\x{5CDB}\x{5CDC}\x{5CDE}\x{5CDF}\x{5CE0}'
. '\x{5CE1}\x{5CE2}\x{5CE3}\x{5CE4}\x{5CE5}\x{5CE6}\x{5CE7}\x{5CE8}\x{5CE9}'
. '\x{5CEA}\x{5CEB}\x{5CEC}\x{5CED}\x{5CEE}\x{5CEF}\x{5CF0}\x{5CF1}\x{5CF2}'
. '\x{5CF3}\x{5CF4}\x{5CF6}\x{5CF7}\x{5CF8}\x{5CF9}\x{5CFA}\x{5CFB}\x{5CFC}'
. '\x{5CFD}\x{5CFE}\x{5CFF}\x{5D00}\x{5D01}\x{5D02}\x{5D03}\x{5D04}\x{5D05}'
. '\x{5D06}\x{5D07}\x{5D08}\x{5D09}\x{5D0A}\x{5D0B}\x{5D0C}\x{5D0D}\x{5D0E}'
. '\x{5D0F}\x{5D10}\x{5D11}\x{5D12}\x{5D13}\x{5D14}\x{5D15}\x{5D16}\x{5D17}'
. '\x{5D18}\x{5D19}\x{5D1A}\x{5D1B}\x{5D1C}\x{5D1D}\x{5D1E}\x{5D1F}\x{5D20}'
. '\x{5D21}\x{5D22}\x{5D23}\x{5D24}\x{5D25}\x{5D26}\x{5D27}\x{5D28}\x{5D29}'
. '\x{5D2A}\x{5D2C}\x{5D2D}\x{5D2E}\x{5D30}\x{5D31}\x{5D32}\x{5D33}\x{5D34}'
. '\x{5D35}\x{5D36}\x{5D37}\x{5D38}\x{5D39}\x{5D3A}\x{5D3C}\x{5D3D}\x{5D3E}'
. '\x{5D3F}\x{5D40}\x{5D41}\x{5D42}\x{5D43}\x{5D44}\x{5D45}\x{5D46}\x{5D47}'
. '\x{5D48}\x{5D49}\x{5D4A}\x{5D4B}\x{5D4C}\x{5D4D}\x{5D4E}\x{5D4F}\x{5D50}'
. '\x{5D51}\x{5D52}\x{5D54}\x{5D55}\x{5D56}\x{5D58}\x{5D59}\x{5D5A}\x{5D5B}'
. '\x{5D5D}\x{5D5E}\x{5D5F}\x{5D61}\x{5D62}\x{5D63}\x{5D64}\x{5D65}\x{5D66}'
. '\x{5D67}\x{5D68}\x{5D69}\x{5D6A}\x{5D6B}\x{5D6C}\x{5D6D}\x{5D6E}\x{5D6F}'
. '\x{5D70}\x{5D71}\x{5D72}\x{5D73}\x{5D74}\x{5D75}\x{5D76}\x{5D77}\x{5D78}'
. '\x{5D79}\x{5D7A}\x{5D7B}\x{5D7C}\x{5D7D}\x{5D7E}\x{5D7F}\x{5D80}\x{5D81}'
. '\x{5D82}\x{5D84}\x{5D85}\x{5D86}\x{5D87}\x{5D88}\x{5D89}\x{5D8A}\x{5D8B}'
. '\x{5D8C}\x{5D8D}\x{5D8E}\x{5D8F}\x{5D90}\x{5D91}\x{5D92}\x{5D93}\x{5D94}'
. '\x{5D95}\x{5D97}\x{5D98}\x{5D99}\x{5D9A}\x{5D9B}\x{5D9C}\x{5D9D}\x{5D9E}'
. '\x{5D9F}\x{5DA0}\x{5DA1}\x{5DA2}\x{5DA5}\x{5DA6}\x{5DA7}\x{5DA8}\x{5DA9}'
. '\x{5DAA}\x{5DAC}\x{5DAD}\x{5DAE}\x{5DAF}\x{5DB0}\x{5DB1}\x{5DB2}\x{5DB4}'
. '\x{5DB5}\x{5DB6}\x{5DB7}\x{5DB8}\x{5DBA}\x{5DBB}\x{5DBC}\x{5DBD}\x{5DBE}'
. '\x{5DBF}\x{5DC0}\x{5DC1}\x{5DC2}\x{5DC3}\x{5DC5}\x{5DC6}\x{5DC7}\x{5DC8}'
. '\x{5DC9}\x{5DCA}\x{5DCB}\x{5DCC}\x{5DCD}\x{5DCE}\x{5DCF}\x{5DD0}\x{5DD1}'
. '\x{5DD2}\x{5DD3}\x{5DD4}\x{5DD5}\x{5DD6}\x{5DD8}\x{5DD9}\x{5DDB}\x{5DDD}'
. '\x{5DDE}\x{5DDF}\x{5DE0}\x{5DE1}\x{5DE2}\x{5DE3}\x{5DE4}\x{5DE5}\x{5DE6}'
. '\x{5DE7}\x{5DE8}\x{5DE9}\x{5DEA}\x{5DEB}\x{5DEC}\x{5DED}\x{5DEE}\x{5DEF}'
. '\x{5DF0}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DF8}\x{5DF9}'
. '\x{5DFA}\x{5DFB}\x{5DFC}\x{5DFD}\x{5DFE}\x{5DFF}\x{5E00}\x{5E01}\x{5E02}'
. '\x{5E03}\x{5E04}\x{5E05}\x{5E06}\x{5E07}\x{5E08}\x{5E09}\x{5E0A}\x{5E0B}'
. '\x{5E0C}\x{5E0D}\x{5E0E}\x{5E0F}\x{5E10}\x{5E11}\x{5E13}\x{5E14}\x{5E15}'
. '\x{5E16}\x{5E17}\x{5E18}\x{5E19}\x{5E1A}\x{5E1B}\x{5E1C}\x{5E1D}\x{5E1E}'
. '\x{5E1F}\x{5E20}\x{5E21}\x{5E22}\x{5E23}\x{5E24}\x{5E25}\x{5E26}\x{5E27}'
. '\x{5E28}\x{5E29}\x{5E2A}\x{5E2B}\x{5E2C}\x{5E2D}\x{5E2E}\x{5E2F}\x{5E30}'
. '\x{5E31}\x{5E32}\x{5E33}\x{5E34}\x{5E35}\x{5E36}\x{5E37}\x{5E38}\x{5E39}'
. '\x{5E3A}\x{5E3B}\x{5E3C}\x{5E3D}\x{5E3E}\x{5E40}\x{5E41}\x{5E42}\x{5E43}'
. '\x{5E44}\x{5E45}\x{5E46}\x{5E47}\x{5E49}\x{5E4A}\x{5E4B}\x{5E4C}\x{5E4D}'
. '\x{5E4E}\x{5E4F}\x{5E50}\x{5E52}\x{5E53}\x{5E54}\x{5E55}\x{5E56}\x{5E57}'
. '\x{5E58}\x{5E59}\x{5E5A}\x{5E5B}\x{5E5C}\x{5E5D}\x{5E5E}\x{5E5F}\x{5E60}'
. '\x{5E61}\x{5E62}\x{5E63}\x{5E64}\x{5E65}\x{5E66}\x{5E67}\x{5E68}\x{5E69}'
. '\x{5E6A}\x{5E6B}\x{5E6C}\x{5E6D}\x{5E6E}\x{5E6F}\x{5E70}\x{5E71}\x{5E72}'
. '\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E77}\x{5E78}\x{5E79}\x{5E7A}\x{5E7B}'
. '\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E80}\x{5E81}\x{5E82}\x{5E83}\x{5E84}'
. '\x{5E85}\x{5E86}\x{5E87}\x{5E88}\x{5E89}\x{5E8A}\x{5E8B}\x{5E8C}\x{5E8D}'
. '\x{5E8E}\x{5E8F}\x{5E90}\x{5E91}\x{5E93}\x{5E94}\x{5E95}\x{5E96}\x{5E97}'
. '\x{5E98}\x{5E99}\x{5E9A}\x{5E9B}\x{5E9C}\x{5E9D}\x{5E9E}\x{5E9F}\x{5EA0}'
. '\x{5EA1}\x{5EA2}\x{5EA3}\x{5EA4}\x{5EA5}\x{5EA6}\x{5EA7}\x{5EA8}\x{5EA9}'
. '\x{5EAA}\x{5EAB}\x{5EAC}\x{5EAD}\x{5EAE}\x{5EAF}\x{5EB0}\x{5EB1}\x{5EB2}'
. '\x{5EB3}\x{5EB4}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EB9}\x{5EBB}\x{5EBC}'
. '\x{5EBD}\x{5EBE}\x{5EBF}\x{5EC1}\x{5EC2}\x{5EC3}\x{5EC4}\x{5EC5}\x{5EC6}'
. '\x{5EC7}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECB}\x{5ECC}\x{5ECD}\x{5ECE}\x{5ECF}'
. '\x{5ED0}\x{5ED1}\x{5ED2}\x{5ED3}\x{5ED4}\x{5ED5}\x{5ED6}\x{5ED7}\x{5ED8}'
. '\x{5ED9}\x{5EDA}\x{5EDB}\x{5EDC}\x{5EDD}\x{5EDE}\x{5EDF}\x{5EE0}\x{5EE1}'
. '\x{5EE2}\x{5EE3}\x{5EE4}\x{5EE5}\x{5EE6}\x{5EE7}\x{5EE8}\x{5EE9}\x{5EEA}'
. '\x{5EEC}\x{5EED}\x{5EEE}\x{5EEF}\x{5EF0}\x{5EF1}\x{5EF2}\x{5EF3}\x{5EF4}'
. '\x{5EF5}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}\x{5EFB}\x{5EFC}\x{5EFD}\x{5EFE}'
. '\x{5EFF}\x{5F00}\x{5F01}\x{5F02}\x{5F03}\x{5F04}\x{5F05}\x{5F06}\x{5F07}'
. '\x{5F08}\x{5F0A}\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F11}\x{5F12}\x{5F13}'
. '\x{5F14}\x{5F15}\x{5F16}\x{5F17}\x{5F18}\x{5F19}\x{5F1A}\x{5F1B}\x{5F1C}'
. '\x{5F1D}\x{5F1E}\x{5F1F}\x{5F20}\x{5F21}\x{5F22}\x{5F23}\x{5F24}\x{5F25}'
. '\x{5F26}\x{5F27}\x{5F28}\x{5F29}\x{5F2A}\x{5F2B}\x{5F2C}\x{5F2D}\x{5F2E}'
. '\x{5F2F}\x{5F30}\x{5F31}\x{5F32}\x{5F33}\x{5F34}\x{5F35}\x{5F36}\x{5F37}'
. '\x{5F38}\x{5F39}\x{5F3A}\x{5F3C}\x{5F3E}\x{5F3F}\x{5F40}\x{5F41}\x{5F42}'
. '\x{5F43}\x{5F44}\x{5F45}\x{5F46}\x{5F47}\x{5F48}\x{5F49}\x{5F4A}\x{5F4B}'
. '\x{5F4C}\x{5F4D}\x{5F4E}\x{5F4F}\x{5F50}\x{5F51}\x{5F52}\x{5F53}\x{5F54}'
. '\x{5F55}\x{5F56}\x{5F57}\x{5F58}\x{5F59}\x{5F5A}\x{5F5B}\x{5F5C}\x{5F5D}'
. '\x{5F5E}\x{5F5F}\x{5F60}\x{5F61}\x{5F62}\x{5F63}\x{5F64}\x{5F65}\x{5F66}'
. '\x{5F67}\x{5F68}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}\x{5F6D}\x{5F6E}\x{5F6F}'
. '\x{5F70}\x{5F71}\x{5F72}\x{5F73}\x{5F74}\x{5F75}\x{5F76}\x{5F77}\x{5F78}'
. '\x{5F79}\x{5F7A}\x{5F7B}\x{5F7C}\x{5F7D}\x{5F7E}\x{5F7F}\x{5F80}\x{5F81}'
. '\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F86}\x{5F87}\x{5F88}\x{5F89}\x{5F8A}'
. '\x{5F8B}\x{5F8C}\x{5F8D}\x{5F8E}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F94}'
. '\x{5F95}\x{5F96}\x{5F97}\x{5F98}\x{5F99}\x{5F9B}\x{5F9C}\x{5F9D}\x{5F9E}'
. '\x{5F9F}\x{5FA0}\x{5FA1}\x{5FA2}\x{5FA5}\x{5FA6}\x{5FA7}\x{5FA8}\x{5FA9}'
. '\x{5FAA}\x{5FAB}\x{5FAC}\x{5FAD}\x{5FAE}\x{5FAF}\x{5FB1}\x{5FB2}\x{5FB3}'
. '\x{5FB4}\x{5FB5}\x{5FB6}\x{5FB7}\x{5FB8}\x{5FB9}\x{5FBA}\x{5FBB}\x{5FBC}'
. '\x{5FBD}\x{5FBE}\x{5FBF}\x{5FC0}\x{5FC1}\x{5FC3}\x{5FC4}\x{5FC5}\x{5FC6}'
. '\x{5FC7}\x{5FC8}\x{5FC9}\x{5FCA}\x{5FCB}\x{5FCC}\x{5FCD}\x{5FCF}\x{5FD0}'
. '\x{5FD1}\x{5FD2}\x{5FD3}\x{5FD4}\x{5FD5}\x{5FD6}\x{5FD7}\x{5FD8}\x{5FD9}'
. '\x{5FDA}\x{5FDC}\x{5FDD}\x{5FDE}\x{5FE0}\x{5FE1}\x{5FE3}\x{5FE4}\x{5FE5}'
. '\x{5FE6}\x{5FE7}\x{5FE8}\x{5FE9}\x{5FEA}\x{5FEB}\x{5FED}\x{5FEE}\x{5FEF}'
. '\x{5FF0}\x{5FF1}\x{5FF2}\x{5FF3}\x{5FF4}\x{5FF5}\x{5FF6}\x{5FF7}\x{5FF8}'
. '\x{5FF9}\x{5FFA}\x{5FFB}\x{5FFD}\x{5FFE}\x{5FFF}\x{6000}\x{6001}\x{6002}'
. '\x{6003}\x{6004}\x{6005}\x{6006}\x{6007}\x{6008}\x{6009}\x{600A}\x{600B}'
. '\x{600C}\x{600D}\x{600E}\x{600F}\x{6010}\x{6011}\x{6012}\x{6013}\x{6014}'
. '\x{6015}\x{6016}\x{6017}\x{6018}\x{6019}\x{601A}\x{601B}\x{601C}\x{601D}'
. '\x{601E}\x{601F}\x{6020}\x{6021}\x{6022}\x{6024}\x{6025}\x{6026}\x{6027}'
. '\x{6028}\x{6029}\x{602A}\x{602B}\x{602C}\x{602D}\x{602E}\x{602F}\x{6030}'
. '\x{6031}\x{6032}\x{6033}\x{6034}\x{6035}\x{6036}\x{6037}\x{6038}\x{6039}'
. '\x{603A}\x{603B}\x{603C}\x{603D}\x{603E}\x{603F}\x{6040}\x{6041}\x{6042}'
. '\x{6043}\x{6044}\x{6045}\x{6046}\x{6047}\x{6048}\x{6049}\x{604A}\x{604B}'
. '\x{604C}\x{604D}\x{604E}\x{604F}\x{6050}\x{6051}\x{6052}\x{6053}\x{6054}'
. '\x{6055}\x{6057}\x{6058}\x{6059}\x{605A}\x{605B}\x{605C}\x{605D}\x{605E}'
. '\x{605F}\x{6062}\x{6063}\x{6064}\x{6065}\x{6066}\x{6067}\x{6068}\x{6069}'
. '\x{606A}\x{606B}\x{606C}\x{606D}\x{606E}\x{606F}\x{6070}\x{6072}\x{6073}'
. '\x{6075}\x{6076}\x{6077}\x{6078}\x{6079}\x{607A}\x{607B}\x{607C}\x{607D}'
. '\x{607E}\x{607F}\x{6080}\x{6081}\x{6082}\x{6083}\x{6084}\x{6085}\x{6086}'
. '\x{6087}\x{6088}\x{6089}\x{608A}\x{608B}\x{608C}\x{608D}\x{608E}\x{608F}'
. '\x{6090}\x{6092}\x{6094}\x{6095}\x{6096}\x{6097}\x{6098}\x{6099}\x{609A}'
. '\x{609B}\x{609C}\x{609D}\x{609E}\x{609F}\x{60A0}\x{60A1}\x{60A2}\x{60A3}'
. '\x{60A4}\x{60A6}\x{60A7}\x{60A8}\x{60AA}\x{60AB}\x{60AC}\x{60AD}\x{60AE}'
. '\x{60AF}\x{60B0}\x{60B1}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B7}'
. '\x{60B8}\x{60B9}\x{60BA}\x{60BB}\x{60BC}\x{60BD}\x{60BE}\x{60BF}\x{60C0}'
. '\x{60C1}\x{60C2}\x{60C3}\x{60C4}\x{60C5}\x{60C6}\x{60C7}\x{60C8}\x{60C9}'
. '\x{60CA}\x{60CB}\x{60CC}\x{60CD}\x{60CE}\x{60CF}\x{60D0}\x{60D1}\x{60D3}'
. '\x{60D4}\x{60D5}\x{60D7}\x{60D8}\x{60D9}\x{60DA}\x{60DB}\x{60DC}\x{60DD}'
. '\x{60DF}\x{60E0}\x{60E1}\x{60E2}\x{60E4}\x{60E6}\x{60E7}\x{60E8}\x{60E9}'
. '\x{60EA}\x{60EB}\x{60EC}\x{60ED}\x{60EE}\x{60EF}\x{60F0}\x{60F1}\x{60F2}'
. '\x{60F3}\x{60F4}\x{60F5}\x{60F6}\x{60F7}\x{60F8}\x{60F9}\x{60FA}\x{60FB}'
. '\x{60FC}\x{60FE}\x{60FF}\x{6100}\x{6101}\x{6103}\x{6104}\x{6105}\x{6106}'
. '\x{6108}\x{6109}\x{610A}\x{610B}\x{610C}\x{610D}\x{610E}\x{610F}\x{6110}'
. '\x{6112}\x{6113}\x{6114}\x{6115}\x{6116}\x{6117}\x{6118}\x{6119}\x{611A}'
. '\x{611B}\x{611C}\x{611D}\x{611F}\x{6120}\x{6122}\x{6123}\x{6124}\x{6125}'
. '\x{6126}\x{6127}\x{6128}\x{6129}\x{612A}\x{612B}\x{612C}\x{612D}\x{612E}'
. '\x{612F}\x{6130}\x{6132}\x{6134}\x{6136}\x{6137}\x{613A}\x{613B}\x{613C}'
. '\x{613D}\x{613E}\x{613F}\x{6140}\x{6141}\x{6142}\x{6143}\x{6144}\x{6145}'
. '\x{6146}\x{6147}\x{6148}\x{6149}\x{614A}\x{614B}\x{614C}\x{614D}\x{614E}'
. '\x{614F}\x{6150}\x{6151}\x{6152}\x{6153}\x{6154}\x{6155}\x{6156}\x{6157}'
. '\x{6158}\x{6159}\x{615A}\x{615B}\x{615C}\x{615D}\x{615E}\x{615F}\x{6161}'
. '\x{6162}\x{6163}\x{6164}\x{6165}\x{6166}\x{6167}\x{6168}\x{6169}\x{616A}'
. '\x{616B}\x{616C}\x{616D}\x{616E}\x{6170}\x{6171}\x{6172}\x{6173}\x{6174}'
. '\x{6175}\x{6176}\x{6177}\x{6178}\x{6179}\x{617A}\x{617C}\x{617E}\x{6180}'
. '\x{6181}\x{6182}\x{6183}\x{6184}\x{6185}\x{6187}\x{6188}\x{6189}\x{618A}'
. '\x{618B}\x{618C}\x{618D}\x{618E}\x{618F}\x{6190}\x{6191}\x{6192}\x{6193}'
. '\x{6194}\x{6195}\x{6196}\x{6198}\x{6199}\x{619A}\x{619B}\x{619D}\x{619E}'
. '\x{619F}\x{61A0}\x{61A1}\x{61A2}\x{61A3}\x{61A4}\x{61A5}\x{61A6}\x{61A7}'
. '\x{61A8}\x{61A9}\x{61AA}\x{61AB}\x{61AC}\x{61AD}\x{61AE}\x{61AF}\x{61B0}'
. '\x{61B1}\x{61B2}\x{61B3}\x{61B4}\x{61B5}\x{61B6}\x{61B7}\x{61B8}\x{61BA}'
. '\x{61BC}\x{61BD}\x{61BE}\x{61BF}\x{61C0}\x{61C1}\x{61C2}\x{61C3}\x{61C4}'
. '\x{61C5}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}'
. '\x{61CE}\x{61CF}\x{61D0}\x{61D1}\x{61D2}\x{61D4}\x{61D6}\x{61D7}\x{61D8}'
. '\x{61D9}\x{61DA}\x{61DB}\x{61DC}\x{61DD}\x{61DE}\x{61DF}\x{61E0}\x{61E1}'
. '\x{61E2}\x{61E3}\x{61E4}\x{61E5}\x{61E6}\x{61E7}\x{61E8}\x{61E9}\x{61EA}'
. '\x{61EB}\x{61ED}\x{61EE}\x{61F0}\x{61F1}\x{61F2}\x{61F3}\x{61F5}\x{61F6}'
. '\x{61F7}\x{61F8}\x{61F9}\x{61FA}\x{61FB}\x{61FC}\x{61FD}\x{61FE}\x{61FF}'
. '\x{6200}\x{6201}\x{6202}\x{6203}\x{6204}\x{6206}\x{6207}\x{6208}\x{6209}'
. '\x{620A}\x{620B}\x{620C}\x{620D}\x{620E}\x{620F}\x{6210}\x{6211}\x{6212}'
. '\x{6213}\x{6214}\x{6215}\x{6216}\x{6217}\x{6218}\x{6219}\x{621A}\x{621B}'
. '\x{621C}\x{621D}\x{621E}\x{621F}\x{6220}\x{6221}\x{6222}\x{6223}\x{6224}'
. '\x{6225}\x{6226}\x{6227}\x{6228}\x{6229}\x{622A}\x{622B}\x{622C}\x{622D}'
. '\x{622E}\x{622F}\x{6230}\x{6231}\x{6232}\x{6233}\x{6234}\x{6236}\x{6237}'
. '\x{6238}\x{623A}\x{623B}\x{623C}\x{623D}\x{623E}\x{623F}\x{6240}\x{6241}'
. '\x{6242}\x{6243}\x{6244}\x{6245}\x{6246}\x{6247}\x{6248}\x{6249}\x{624A}'
. '\x{624B}\x{624C}\x{624D}\x{624E}\x{624F}\x{6250}\x{6251}\x{6252}\x{6253}'
. '\x{6254}\x{6255}\x{6256}\x{6258}\x{6259}\x{625A}\x{625B}\x{625C}\x{625D}'
. '\x{625E}\x{625F}\x{6260}\x{6261}\x{6262}\x{6263}\x{6264}\x{6265}\x{6266}'
. '\x{6267}\x{6268}\x{6269}\x{626A}\x{626B}\x{626C}\x{626D}\x{626E}\x{626F}'
. '\x{6270}\x{6271}\x{6272}\x{6273}\x{6274}\x{6275}\x{6276}\x{6277}\x{6278}'
. '\x{6279}\x{627A}\x{627B}\x{627C}\x{627D}\x{627E}\x{627F}\x{6280}\x{6281}'
. '\x{6283}\x{6284}\x{6285}\x{6286}\x{6287}\x{6288}\x{6289}\x{628A}\x{628B}'
. '\x{628C}\x{628E}\x{628F}\x{6290}\x{6291}\x{6292}\x{6293}\x{6294}\x{6295}'
. '\x{6296}\x{6297}\x{6298}\x{6299}\x{629A}\x{629B}\x{629C}\x{629E}\x{629F}'
. '\x{62A0}\x{62A1}\x{62A2}\x{62A3}\x{62A4}\x{62A5}\x{62A7}\x{62A8}\x{62A9}'
. '\x{62AA}\x{62AB}\x{62AC}\x{62AD}\x{62AE}\x{62AF}\x{62B0}\x{62B1}\x{62B2}'
. '\x{62B3}\x{62B4}\x{62B5}\x{62B6}\x{62B7}\x{62B8}\x{62B9}\x{62BA}\x{62BB}'
. '\x{62BC}\x{62BD}\x{62BE}\x{62BF}\x{62C0}\x{62C1}\x{62C2}\x{62C3}\x{62C4}'
. '\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CB}\x{62CC}\x{62CD}'
. '\x{62CE}\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D5}\x{62D6}'
. '\x{62D7}\x{62D8}\x{62D9}\x{62DA}\x{62DB}\x{62DC}\x{62DD}\x{62DF}\x{62E0}'
. '\x{62E1}\x{62E2}\x{62E3}\x{62E4}\x{62E5}\x{62E6}\x{62E7}\x{62E8}\x{62E9}'
. '\x{62EB}\x{62EC}\x{62ED}\x{62EE}\x{62EF}\x{62F0}\x{62F1}\x{62F2}\x{62F3}'
. '\x{62F4}\x{62F5}\x{62F6}\x{62F7}\x{62F8}\x{62F9}\x{62FA}\x{62FB}\x{62FC}'
. '\x{62FD}\x{62FE}\x{62FF}\x{6300}\x{6301}\x{6302}\x{6303}\x{6304}\x{6305}'
. '\x{6306}\x{6307}\x{6308}\x{6309}\x{630B}\x{630C}\x{630D}\x{630E}\x{630F}'
. '\x{6310}\x{6311}\x{6312}\x{6313}\x{6314}\x{6315}\x{6316}\x{6318}\x{6319}'
. '\x{631A}\x{631B}\x{631C}\x{631D}\x{631E}\x{631F}\x{6320}\x{6321}\x{6322}'
. '\x{6323}\x{6324}\x{6325}\x{6326}\x{6327}\x{6328}\x{6329}\x{632A}\x{632B}'
. '\x{632C}\x{632D}\x{632E}\x{632F}\x{6330}\x{6332}\x{6333}\x{6334}\x{6336}'
. '\x{6338}\x{6339}\x{633A}\x{633B}\x{633C}\x{633D}\x{633E}\x{6340}\x{6341}'
. '\x{6342}\x{6343}\x{6344}\x{6345}\x{6346}\x{6347}\x{6348}\x{6349}\x{634A}'
. '\x{634B}\x{634C}\x{634D}\x{634E}\x{634F}\x{6350}\x{6351}\x{6352}\x{6353}'
. '\x{6354}\x{6355}\x{6356}\x{6357}\x{6358}\x{6359}\x{635A}\x{635C}\x{635D}'
. '\x{635E}\x{635F}\x{6360}\x{6361}\x{6362}\x{6363}\x{6364}\x{6365}\x{6366}'
. '\x{6367}\x{6368}\x{6369}\x{636A}\x{636B}\x{636C}\x{636D}\x{636E}\x{636F}'
. '\x{6370}\x{6371}\x{6372}\x{6373}\x{6374}\x{6375}\x{6376}\x{6377}\x{6378}'
. '\x{6379}\x{637A}\x{637B}\x{637C}\x{637D}\x{637E}\x{6380}\x{6381}\x{6382}'
. '\x{6383}\x{6384}\x{6385}\x{6386}\x{6387}\x{6388}\x{6389}\x{638A}\x{638C}'
. '\x{638D}\x{638E}\x{638F}\x{6390}\x{6391}\x{6392}\x{6394}\x{6395}\x{6396}'
. '\x{6397}\x{6398}\x{6399}\x{639A}\x{639B}\x{639C}\x{639D}\x{639E}\x{639F}'
. '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A4}\x{63A5}\x{63A6}\x{63A7}\x{63A8}'
. '\x{63A9}\x{63AA}\x{63AB}\x{63AC}\x{63AD}\x{63AE}\x{63AF}\x{63B0}\x{63B1}'
. '\x{63B2}\x{63B3}\x{63B4}\x{63B5}\x{63B6}\x{63B7}\x{63B8}\x{63B9}\x{63BA}'
. '\x{63BC}\x{63BD}\x{63BE}\x{63BF}\x{63C0}\x{63C1}\x{63C2}\x{63C3}\x{63C4}'
. '\x{63C5}\x{63C6}\x{63C7}\x{63C8}\x{63C9}\x{63CA}\x{63CB}\x{63CC}\x{63CD}'
. '\x{63CE}\x{63CF}\x{63D0}\x{63D2}\x{63D3}\x{63D4}\x{63D5}\x{63D6}\x{63D7}'
. '\x{63D8}\x{63D9}\x{63DA}\x{63DB}\x{63DC}\x{63DD}\x{63DE}\x{63DF}\x{63E0}'
. '\x{63E1}\x{63E2}\x{63E3}\x{63E4}\x{63E5}\x{63E6}\x{63E7}\x{63E8}\x{63E9}'
. '\x{63EA}\x{63EB}\x{63EC}\x{63ED}\x{63EE}\x{63EF}\x{63F0}\x{63F1}\x{63F2}'
. '\x{63F3}\x{63F4}\x{63F5}\x{63F6}\x{63F7}\x{63F8}\x{63F9}\x{63FA}\x{63FB}'
. '\x{63FC}\x{63FD}\x{63FE}\x{63FF}\x{6400}\x{6401}\x{6402}\x{6403}\x{6404}'
. '\x{6405}\x{6406}\x{6408}\x{6409}\x{640A}\x{640B}\x{640C}\x{640D}\x{640E}'
. '\x{640F}\x{6410}\x{6411}\x{6412}\x{6413}\x{6414}\x{6415}\x{6416}\x{6417}'
. '\x{6418}\x{6419}\x{641A}\x{641B}\x{641C}\x{641D}\x{641E}\x{641F}\x{6420}'
. '\x{6421}\x{6422}\x{6423}\x{6424}\x{6425}\x{6426}\x{6427}\x{6428}\x{6429}'
. '\x{642A}\x{642B}\x{642C}\x{642D}\x{642E}\x{642F}\x{6430}\x{6431}\x{6432}'
. '\x{6433}\x{6434}\x{6435}\x{6436}\x{6437}\x{6438}\x{6439}\x{643A}\x{643D}'
. '\x{643E}\x{643F}\x{6440}\x{6441}\x{6443}\x{6444}\x{6445}\x{6446}\x{6447}'
. '\x{6448}\x{644A}\x{644B}\x{644C}\x{644D}\x{644E}\x{644F}\x{6450}\x{6451}'
. '\x{6452}\x{6453}\x{6454}\x{6455}\x{6456}\x{6457}\x{6458}\x{6459}\x{645B}'
. '\x{645C}\x{645D}\x{645E}\x{645F}\x{6460}\x{6461}\x{6462}\x{6463}\x{6464}'
. '\x{6465}\x{6466}\x{6467}\x{6468}\x{6469}\x{646A}\x{646B}\x{646C}\x{646D}'
. '\x{646E}\x{646F}\x{6470}\x{6471}\x{6472}\x{6473}\x{6474}\x{6475}\x{6476}'
. '\x{6477}\x{6478}\x{6479}\x{647A}\x{647B}\x{647C}\x{647D}\x{647F}\x{6480}'
. '\x{6481}\x{6482}\x{6483}\x{6484}\x{6485}\x{6487}\x{6488}\x{6489}\x{648A}'
. '\x{648B}\x{648C}\x{648D}\x{648E}\x{648F}\x{6490}\x{6491}\x{6492}\x{6493}'
. '\x{6494}\x{6495}\x{6496}\x{6497}\x{6498}\x{6499}\x{649A}\x{649B}\x{649C}'
. '\x{649D}\x{649E}\x{649F}\x{64A0}\x{64A2}\x{64A3}\x{64A4}\x{64A5}\x{64A6}'
. '\x{64A7}\x{64A8}\x{64A9}\x{64AA}\x{64AB}\x{64AC}\x{64AD}\x{64AE}\x{64B0}'
. '\x{64B1}\x{64B2}\x{64B3}\x{64B4}\x{64B5}\x{64B7}\x{64B8}\x{64B9}\x{64BA}'
. '\x{64BB}\x{64BC}\x{64BD}\x{64BE}\x{64BF}\x{64C0}\x{64C1}\x{64C2}\x{64C3}'
. '\x{64C4}\x{64C5}\x{64C6}\x{64C7}\x{64C9}\x{64CA}\x{64CB}\x{64CC}\x{64CD}'
. '\x{64CE}\x{64CF}\x{64D0}\x{64D1}\x{64D2}\x{64D3}\x{64D4}\x{64D6}\x{64D7}'
. '\x{64D8}\x{64D9}\x{64DA}\x{64DB}\x{64DC}\x{64DD}\x{64DE}\x{64DF}\x{64E0}'
. '\x{64E2}\x{64E3}\x{64E4}\x{64E6}\x{64E7}\x{64E8}\x{64E9}\x{64EA}\x{64EB}'
. '\x{64EC}\x{64ED}\x{64EF}\x{64F0}\x{64F1}\x{64F2}\x{64F3}\x{64F4}\x{64F6}'
. '\x{64F7}\x{64F8}\x{64FA}\x{64FB}\x{64FC}\x{64FD}\x{64FE}\x{64FF}\x{6500}'
. '\x{6501}\x{6503}\x{6504}\x{6505}\x{6506}\x{6507}\x{6508}\x{6509}\x{650B}'
. '\x{650C}\x{650D}\x{650E}\x{650F}\x{6510}\x{6511}\x{6512}\x{6513}\x{6514}'
. '\x{6515}\x{6516}\x{6517}\x{6518}\x{6519}\x{651A}\x{651B}\x{651C}\x{651D}'
. '\x{651E}\x{6520}\x{6521}\x{6522}\x{6523}\x{6524}\x{6525}\x{6526}\x{6527}'
. '\x{6529}\x{652A}\x{652B}\x{652C}\x{652D}\x{652E}\x{652F}\x{6530}\x{6531}'
. '\x{6532}\x{6533}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}\x{653A}'
. '\x{653B}\x{653C}\x{653D}\x{653E}\x{653F}\x{6541}\x{6543}\x{6544}\x{6545}'
. '\x{6546}\x{6547}\x{6548}\x{6549}\x{654A}\x{654B}\x{654C}\x{654D}\x{654E}'
. '\x{654F}\x{6550}\x{6551}\x{6552}\x{6553}\x{6554}\x{6555}\x{6556}\x{6557}'
. '\x{6558}\x{6559}\x{655B}\x{655C}\x{655D}\x{655E}\x{6560}\x{6561}\x{6562}'
. '\x{6563}\x{6564}\x{6565}\x{6566}\x{6567}\x{6568}\x{6569}\x{656A}\x{656B}'
. '\x{656C}\x{656E}\x{656F}\x{6570}\x{6571}\x{6572}\x{6573}\x{6574}\x{6575}'
. '\x{6576}\x{6577}\x{6578}\x{6579}\x{657A}\x{657B}\x{657C}\x{657E}\x{657F}'
. '\x{6580}\x{6581}\x{6582}\x{6583}\x{6584}\x{6585}\x{6586}\x{6587}\x{6588}'
. '\x{6589}\x{658B}\x{658C}\x{658D}\x{658E}\x{658F}\x{6590}\x{6591}\x{6592}'
. '\x{6593}\x{6594}\x{6595}\x{6596}\x{6597}\x{6598}\x{6599}\x{659B}\x{659C}'
. '\x{659D}\x{659E}\x{659F}\x{65A0}\x{65A1}\x{65A2}\x{65A3}\x{65A4}\x{65A5}'
. '\x{65A6}\x{65A7}\x{65A8}\x{65A9}\x{65AA}\x{65AB}\x{65AC}\x{65AD}\x{65AE}'
. '\x{65AF}\x{65B0}\x{65B1}\x{65B2}\x{65B3}\x{65B4}\x{65B6}\x{65B7}\x{65B8}'
. '\x{65B9}\x{65BA}\x{65BB}\x{65BC}\x{65BD}\x{65BF}\x{65C0}\x{65C1}\x{65C2}'
. '\x{65C3}\x{65C4}\x{65C5}\x{65C6}\x{65C7}\x{65CA}\x{65CB}\x{65CC}\x{65CD}'
. '\x{65CE}\x{65CF}\x{65D0}\x{65D2}\x{65D3}\x{65D4}\x{65D5}\x{65D6}\x{65D7}'
. '\x{65DA}\x{65DB}\x{65DD}\x{65DE}\x{65DF}\x{65E0}\x{65E1}\x{65E2}\x{65E3}'
. '\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}\x{65EB}\x{65EC}\x{65ED}\x{65EE}'
. '\x{65EF}\x{65F0}\x{65F1}\x{65F2}\x{65F3}\x{65F4}\x{65F5}\x{65F6}\x{65F7}'
. '\x{65F8}\x{65FA}\x{65FB}\x{65FC}\x{65FD}\x{6600}\x{6601}\x{6602}\x{6603}'
. '\x{6604}\x{6605}\x{6606}\x{6607}\x{6608}\x{6609}\x{660A}\x{660B}\x{660C}'
. '\x{660D}\x{660E}\x{660F}\x{6610}\x{6611}\x{6612}\x{6613}\x{6614}\x{6615}'
. '\x{6616}\x{6618}\x{6619}\x{661A}\x{661B}\x{661C}\x{661D}\x{661F}\x{6620}'
. '\x{6621}\x{6622}\x{6623}\x{6624}\x{6625}\x{6626}\x{6627}\x{6628}\x{6629}'
. '\x{662A}\x{662B}\x{662D}\x{662E}\x{662F}\x{6630}\x{6631}\x{6632}\x{6633}'
. '\x{6634}\x{6635}\x{6636}\x{6639}\x{663A}\x{663C}\x{663D}\x{663E}\x{6640}'
. '\x{6641}\x{6642}\x{6643}\x{6644}\x{6645}\x{6646}\x{6647}\x{6649}\x{664A}'
. '\x{664B}\x{664C}\x{664E}\x{664F}\x{6650}\x{6651}\x{6652}\x{6653}\x{6654}'
. '\x{6655}\x{6656}\x{6657}\x{6658}\x{6659}\x{665A}\x{665B}\x{665C}\x{665D}'
. '\x{665E}\x{665F}\x{6661}\x{6662}\x{6664}\x{6665}\x{6666}\x{6668}\x{6669}'
. '\x{666A}\x{666B}\x{666C}\x{666D}\x{666E}\x{666F}\x{6670}\x{6671}\x{6672}'
. '\x{6673}\x{6674}\x{6675}\x{6676}\x{6677}\x{6678}\x{6679}\x{667A}\x{667B}'
. '\x{667C}\x{667D}\x{667E}\x{667F}\x{6680}\x{6681}\x{6682}\x{6683}\x{6684}'
. '\x{6685}\x{6686}\x{6687}\x{6688}\x{6689}\x{668A}\x{668B}\x{668C}\x{668D}'
. '\x{668E}\x{668F}\x{6690}\x{6691}\x{6693}\x{6694}\x{6695}\x{6696}\x{6697}'
. '\x{6698}\x{6699}\x{669A}\x{669B}\x{669D}\x{669F}\x{66A0}\x{66A1}\x{66A2}'
. '\x{66A3}\x{66A4}\x{66A5}\x{66A6}\x{66A7}\x{66A8}\x{66A9}\x{66AA}\x{66AB}'
. '\x{66AE}\x{66AF}\x{66B0}\x{66B1}\x{66B2}\x{66B3}\x{66B4}\x{66B5}\x{66B6}'
. '\x{66B7}\x{66B8}\x{66B9}\x{66BA}\x{66BB}\x{66BC}\x{66BD}\x{66BE}\x{66BF}'
. '\x{66C0}\x{66C1}\x{66C2}\x{66C3}\x{66C4}\x{66C5}\x{66C6}\x{66C7}\x{66C8}'
. '\x{66C9}\x{66CA}\x{66CB}\x{66CC}\x{66CD}\x{66CE}\x{66CF}\x{66D1}\x{66D2}'
. '\x{66D4}\x{66D5}\x{66D6}\x{66D8}\x{66D9}\x{66DA}\x{66DB}\x{66DC}\x{66DD}'
. '\x{66DE}\x{66E0}\x{66E1}\x{66E2}\x{66E3}\x{66E4}\x{66E5}\x{66E6}\x{66E7}'
. '\x{66E8}\x{66E9}\x{66EA}\x{66EB}\x{66EC}\x{66ED}\x{66EE}\x{66F0}\x{66F1}'
. '\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F6}\x{66F7}\x{66F8}\x{66F9}\x{66FA}'
. '\x{66FB}\x{66FC}\x{66FE}\x{66FF}\x{6700}\x{6701}\x{6703}\x{6704}\x{6705}'
. '\x{6706}\x{6708}\x{6709}\x{670A}\x{670B}\x{670C}\x{670D}\x{670E}\x{670F}'
. '\x{6710}\x{6711}\x{6712}\x{6713}\x{6714}\x{6715}\x{6716}\x{6717}\x{6718}'
. '\x{671A}\x{671B}\x{671C}\x{671D}\x{671E}\x{671F}\x{6720}\x{6721}\x{6722}'
. '\x{6723}\x{6725}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}\x{672D}'
. '\x{672E}\x{672F}\x{6730}\x{6731}\x{6732}\x{6733}\x{6734}\x{6735}\x{6736}'
. '\x{6737}\x{6738}\x{6739}\x{673A}\x{673B}\x{673C}\x{673D}\x{673E}\x{673F}'
. '\x{6740}\x{6741}\x{6742}\x{6743}\x{6744}\x{6745}\x{6746}\x{6747}\x{6748}'
. '\x{6749}\x{674A}\x{674B}\x{674C}\x{674D}\x{674E}\x{674F}\x{6750}\x{6751}'
. '\x{6752}\x{6753}\x{6754}\x{6755}\x{6756}\x{6757}\x{6758}\x{6759}\x{675A}'
. '\x{675B}\x{675C}\x{675D}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}'
. '\x{6764}\x{6765}\x{6766}\x{6768}\x{6769}\x{676A}\x{676B}\x{676C}\x{676D}'
. '\x{676E}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}\x{6774}\x{6775}\x{6776}'
. '\x{6777}\x{6778}\x{6779}\x{677A}\x{677B}\x{677C}\x{677D}\x{677E}\x{677F}'
. '\x{6780}\x{6781}\x{6782}\x{6783}\x{6784}\x{6785}\x{6786}\x{6787}\x{6789}'
. '\x{678A}\x{678B}\x{678C}\x{678D}\x{678E}\x{678F}\x{6790}\x{6791}\x{6792}'
. '\x{6793}\x{6794}\x{6795}\x{6797}\x{6798}\x{6799}\x{679A}\x{679B}\x{679C}'
. '\x{679D}\x{679E}\x{679F}\x{67A0}\x{67A1}\x{67A2}\x{67A3}\x{67A4}\x{67A5}'
. '\x{67A6}\x{67A7}\x{67A8}\x{67AA}\x{67AB}\x{67AC}\x{67AD}\x{67AE}\x{67AF}'
. '\x{67B0}\x{67B1}\x{67B2}\x{67B3}\x{67B4}\x{67B5}\x{67B6}\x{67B7}\x{67B8}'
. '\x{67B9}\x{67BA}\x{67BB}\x{67BC}\x{67BE}\x{67C0}\x{67C1}\x{67C2}\x{67C3}'
. '\x{67C4}\x{67C5}\x{67C6}\x{67C7}\x{67C8}\x{67C9}\x{67CA}\x{67CB}\x{67CC}'
. '\x{67CD}\x{67CE}\x{67CF}\x{67D0}\x{67D1}\x{67D2}\x{67D3}\x{67D4}\x{67D6}'
. '\x{67D8}\x{67D9}\x{67DA}\x{67DB}\x{67DC}\x{67DD}\x{67DE}\x{67DF}\x{67E0}'
. '\x{67E1}\x{67E2}\x{67E3}\x{67E4}\x{67E5}\x{67E6}\x{67E7}\x{67E8}\x{67E9}'
. '\x{67EA}\x{67EB}\x{67EC}\x{67ED}\x{67EE}\x{67EF}\x{67F0}\x{67F1}\x{67F2}'
. '\x{67F3}\x{67F4}\x{67F5}\x{67F6}\x{67F7}\x{67F8}\x{67FA}\x{67FB}\x{67FC}'
. '\x{67FD}\x{67FE}\x{67FF}\x{6800}\x{6802}\x{6803}\x{6804}\x{6805}\x{6806}'
. '\x{6807}\x{6808}\x{6809}\x{680A}\x{680B}\x{680C}\x{680D}\x{680E}\x{680F}'
. '\x{6810}\x{6811}\x{6812}\x{6813}\x{6814}\x{6816}\x{6817}\x{6818}\x{6819}'
. '\x{681A}\x{681B}\x{681C}\x{681D}\x{681F}\x{6820}\x{6821}\x{6822}\x{6823}'
. '\x{6824}\x{6825}\x{6826}\x{6828}\x{6829}\x{682A}\x{682B}\x{682C}\x{682D}'
. '\x{682E}\x{682F}\x{6831}\x{6832}\x{6833}\x{6834}\x{6835}\x{6836}\x{6837}'
. '\x{6838}\x{6839}\x{683A}\x{683B}\x{683C}\x{683D}\x{683E}\x{683F}\x{6840}'
. '\x{6841}\x{6842}\x{6843}\x{6844}\x{6845}\x{6846}\x{6847}\x{6848}\x{6849}'
. '\x{684A}\x{684B}\x{684C}\x{684D}\x{684E}\x{684F}\x{6850}\x{6851}\x{6852}'
. '\x{6853}\x{6854}\x{6855}\x{6856}\x{6857}\x{685B}\x{685D}\x{6860}\x{6861}'
. '\x{6862}\x{6863}\x{6864}\x{6865}\x{6866}\x{6867}\x{6868}\x{6869}\x{686A}'
. '\x{686B}\x{686C}\x{686D}\x{686E}\x{686F}\x{6870}\x{6871}\x{6872}\x{6873}'
. '\x{6874}\x{6875}\x{6876}\x{6877}\x{6878}\x{6879}\x{687B}\x{687C}\x{687D}'
. '\x{687E}\x{687F}\x{6880}\x{6881}\x{6882}\x{6883}\x{6884}\x{6885}\x{6886}'
. '\x{6887}\x{6888}\x{6889}\x{688A}\x{688B}\x{688C}\x{688D}\x{688E}\x{688F}'
. '\x{6890}\x{6891}\x{6892}\x{6893}\x{6894}\x{6896}\x{6897}\x{6898}\x{689A}'
. '\x{689B}\x{689C}\x{689D}\x{689E}\x{689F}\x{68A0}\x{68A1}\x{68A2}\x{68A3}'
. '\x{68A4}\x{68A6}\x{68A7}\x{68A8}\x{68A9}\x{68AA}\x{68AB}\x{68AC}\x{68AD}'
. '\x{68AE}\x{68AF}\x{68B0}\x{68B1}\x{68B2}\x{68B3}\x{68B4}\x{68B5}\x{68B6}'
. '\x{68B7}\x{68B9}\x{68BB}\x{68BC}\x{68BD}\x{68BE}\x{68BF}\x{68C0}\x{68C1}'
. '\x{68C2}\x{68C4}\x{68C6}\x{68C7}\x{68C8}\x{68C9}\x{68CA}\x{68CB}\x{68CC}'
. '\x{68CD}\x{68CE}\x{68CF}\x{68D0}\x{68D1}\x{68D2}\x{68D3}\x{68D4}\x{68D5}'
. '\x{68D6}\x{68D7}\x{68D8}\x{68DA}\x{68DB}\x{68DC}\x{68DD}\x{68DE}\x{68DF}'
. '\x{68E0}\x{68E1}\x{68E3}\x{68E4}\x{68E6}\x{68E7}\x{68E8}\x{68E9}\x{68EA}'
. '\x{68EB}\x{68EC}\x{68ED}\x{68EE}\x{68EF}\x{68F0}\x{68F1}\x{68F2}\x{68F3}'
. '\x{68F4}\x{68F5}\x{68F6}\x{68F7}\x{68F8}\x{68F9}\x{68FA}\x{68FB}\x{68FC}'
. '\x{68FD}\x{68FE}\x{68FF}\x{6901}\x{6902}\x{6903}\x{6904}\x{6905}\x{6906}'
. '\x{6907}\x{6908}\x{690A}\x{690B}\x{690C}\x{690D}\x{690E}\x{690F}\x{6910}'
. '\x{6911}\x{6912}\x{6913}\x{6914}\x{6915}\x{6916}\x{6917}\x{6918}\x{6919}'
. '\x{691A}\x{691B}\x{691C}\x{691D}\x{691E}\x{691F}\x{6920}\x{6921}\x{6922}'
. '\x{6923}\x{6924}\x{6925}\x{6926}\x{6927}\x{6928}\x{6929}\x{692A}\x{692B}'
. '\x{692C}\x{692D}\x{692E}\x{692F}\x{6930}\x{6931}\x{6932}\x{6933}\x{6934}'
. '\x{6935}\x{6936}\x{6937}\x{6938}\x{6939}\x{693A}\x{693B}\x{693C}\x{693D}'
. '\x{693F}\x{6940}\x{6941}\x{6942}\x{6943}\x{6944}\x{6945}\x{6946}\x{6947}'
. '\x{6948}\x{6949}\x{694A}\x{694B}\x{694C}\x{694E}\x{694F}\x{6950}\x{6951}'
. '\x{6952}\x{6953}\x{6954}\x{6955}\x{6956}\x{6957}\x{6958}\x{6959}\x{695A}'
. '\x{695B}\x{695C}\x{695D}\x{695E}\x{695F}\x{6960}\x{6961}\x{6962}\x{6963}'
. '\x{6964}\x{6965}\x{6966}\x{6967}\x{6968}\x{6969}\x{696A}\x{696B}\x{696C}'
. '\x{696D}\x{696E}\x{696F}\x{6970}\x{6971}\x{6972}\x{6973}\x{6974}\x{6975}'
. '\x{6976}\x{6977}\x{6978}\x{6979}\x{697A}\x{697B}\x{697C}\x{697D}\x{697E}'
. '\x{697F}\x{6980}\x{6981}\x{6982}\x{6983}\x{6984}\x{6985}\x{6986}\x{6987}'
. '\x{6988}\x{6989}\x{698A}\x{698B}\x{698C}\x{698D}\x{698E}\x{698F}\x{6990}'
. '\x{6991}\x{6992}\x{6993}\x{6994}\x{6995}\x{6996}\x{6997}\x{6998}\x{6999}'
. '\x{699A}\x{699B}\x{699C}\x{699D}\x{699E}\x{69A0}\x{69A1}\x{69A3}\x{69A4}'
. '\x{69A5}\x{69A6}\x{69A7}\x{69A8}\x{69A9}\x{69AA}\x{69AB}\x{69AC}\x{69AD}'
. '\x{69AE}\x{69AF}\x{69B0}\x{69B1}\x{69B2}\x{69B3}\x{69B4}\x{69B5}\x{69B6}'
. '\x{69B7}\x{69B8}\x{69B9}\x{69BA}\x{69BB}\x{69BC}\x{69BD}\x{69BE}\x{69BF}'
. '\x{69C1}\x{69C2}\x{69C3}\x{69C4}\x{69C5}\x{69C6}\x{69C7}\x{69C8}\x{69C9}'
. '\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}\x{69CF}\x{69D0}\x{69D3}\x{69D4}'
. '\x{69D8}\x{69D9}\x{69DA}\x{69DB}\x{69DC}\x{69DD}\x{69DE}\x{69DF}\x{69E0}'
. '\x{69E1}\x{69E2}\x{69E3}\x{69E4}\x{69E5}\x{69E6}\x{69E7}\x{69E8}\x{69E9}'
. '\x{69EA}\x{69EB}\x{69EC}\x{69ED}\x{69EE}\x{69EF}\x{69F0}\x{69F1}\x{69F2}'
. '\x{69F3}\x{69F4}\x{69F5}\x{69F6}\x{69F7}\x{69F8}\x{69FA}\x{69FB}\x{69FC}'
. '\x{69FD}\x{69FE}\x{69FF}\x{6A00}\x{6A01}\x{6A02}\x{6A04}\x{6A05}\x{6A06}'
. '\x{6A07}\x{6A08}\x{6A09}\x{6A0A}\x{6A0B}\x{6A0D}\x{6A0E}\x{6A0F}\x{6A10}'
. '\x{6A11}\x{6A12}\x{6A13}\x{6A14}\x{6A15}\x{6A16}\x{6A17}\x{6A18}\x{6A19}'
. '\x{6A1A}\x{6A1B}\x{6A1D}\x{6A1E}\x{6A1F}\x{6A20}\x{6A21}\x{6A22}\x{6A23}'
. '\x{6A25}\x{6A26}\x{6A27}\x{6A28}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2C}\x{6A2D}'
. '\x{6A2E}\x{6A2F}\x{6A30}\x{6A31}\x{6A32}\x{6A33}\x{6A34}\x{6A35}\x{6A36}'
. '\x{6A38}\x{6A39}\x{6A3A}\x{6A3B}\x{6A3C}\x{6A3D}\x{6A3E}\x{6A3F}\x{6A40}'
. '\x{6A41}\x{6A42}\x{6A43}\x{6A44}\x{6A45}\x{6A46}\x{6A47}\x{6A48}\x{6A49}'
. '\x{6A4B}\x{6A4C}\x{6A4D}\x{6A4E}\x{6A4F}\x{6A50}\x{6A51}\x{6A52}\x{6A54}'
. '\x{6A55}\x{6A56}\x{6A57}\x{6A58}\x{6A59}\x{6A5A}\x{6A5B}\x{6A5D}\x{6A5E}'
. '\x{6A5F}\x{6A60}\x{6A61}\x{6A62}\x{6A63}\x{6A64}\x{6A65}\x{6A66}\x{6A67}'
. '\x{6A68}\x{6A69}\x{6A6A}\x{6A6B}\x{6A6C}\x{6A6D}\x{6A6F}\x{6A71}\x{6A72}'
. '\x{6A73}\x{6A74}\x{6A75}\x{6A76}\x{6A77}\x{6A78}\x{6A79}\x{6A7A}\x{6A7B}'
. '\x{6A7C}\x{6A7D}\x{6A7E}\x{6A7F}\x{6A80}\x{6A81}\x{6A82}\x{6A83}\x{6A84}'
. '\x{6A85}\x{6A87}\x{6A88}\x{6A89}\x{6A8B}\x{6A8C}\x{6A8D}\x{6A8E}\x{6A90}'
. '\x{6A91}\x{6A92}\x{6A93}\x{6A94}\x{6A95}\x{6A96}\x{6A97}\x{6A98}\x{6A9A}'
. '\x{6A9B}\x{6A9C}\x{6A9E}\x{6A9F}\x{6AA0}\x{6AA1}\x{6AA2}\x{6AA3}\x{6AA4}'
. '\x{6AA5}\x{6AA6}\x{6AA7}\x{6AA8}\x{6AA9}\x{6AAB}\x{6AAC}\x{6AAD}\x{6AAE}'
. '\x{6AAF}\x{6AB0}\x{6AB2}\x{6AB3}\x{6AB4}\x{6AB5}\x{6AB6}\x{6AB7}\x{6AB8}'
. '\x{6AB9}\x{6ABA}\x{6ABB}\x{6ABC}\x{6ABD}\x{6ABF}\x{6AC1}\x{6AC2}\x{6AC3}'
. '\x{6AC5}\x{6AC6}\x{6AC7}\x{6ACA}\x{6ACB}\x{6ACC}\x{6ACD}\x{6ACE}\x{6ACF}'
. '\x{6AD0}\x{6AD1}\x{6AD2}\x{6AD3}\x{6AD4}\x{6AD5}\x{6AD6}\x{6AD7}\x{6AD9}'
. '\x{6ADA}\x{6ADB}\x{6ADC}\x{6ADD}\x{6ADE}\x{6ADF}\x{6AE0}\x{6AE1}\x{6AE2}'
. '\x{6AE3}\x{6AE4}\x{6AE5}\x{6AE6}\x{6AE7}\x{6AE8}\x{6AEA}\x{6AEB}\x{6AEC}'
. '\x{6AED}\x{6AEE}\x{6AEF}\x{6AF0}\x{6AF1}\x{6AF2}\x{6AF3}\x{6AF4}\x{6AF5}'
. '\x{6AF6}\x{6AF7}\x{6AF8}\x{6AF9}\x{6AFA}\x{6AFB}\x{6AFC}\x{6AFD}\x{6AFE}'
. '\x{6AFF}\x{6B00}\x{6B01}\x{6B02}\x{6B03}\x{6B04}\x{6B05}\x{6B06}\x{6B07}'
. '\x{6B08}\x{6B09}\x{6B0A}\x{6B0B}\x{6B0C}\x{6B0D}\x{6B0F}\x{6B10}\x{6B11}'
. '\x{6B12}\x{6B13}\x{6B14}\x{6B15}\x{6B16}\x{6B17}\x{6B18}\x{6B19}\x{6B1A}'
. '\x{6B1C}\x{6B1D}\x{6B1E}\x{6B1F}\x{6B20}\x{6B21}\x{6B22}\x{6B23}\x{6B24}'
. '\x{6B25}\x{6B26}\x{6B27}\x{6B28}\x{6B29}\x{6B2A}\x{6B2B}\x{6B2C}\x{6B2D}'
. '\x{6B2F}\x{6B30}\x{6B31}\x{6B32}\x{6B33}\x{6B34}\x{6B36}\x{6B37}\x{6B38}'
. '\x{6B39}\x{6B3A}\x{6B3B}\x{6B3C}\x{6B3D}\x{6B3E}\x{6B3F}\x{6B41}\x{6B42}'
. '\x{6B43}\x{6B44}\x{6B45}\x{6B46}\x{6B47}\x{6B48}\x{6B49}\x{6B4A}\x{6B4B}'
. '\x{6B4C}\x{6B4D}\x{6B4E}\x{6B4F}\x{6B50}\x{6B51}\x{6B52}\x{6B53}\x{6B54}'
. '\x{6B55}\x{6B56}\x{6B59}\x{6B5A}\x{6B5B}\x{6B5C}\x{6B5E}\x{6B5F}\x{6B60}'
. '\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B65}\x{6B66}\x{6B67}\x{6B69}\x{6B6A}'
. '\x{6B6B}\x{6B6D}\x{6B6F}\x{6B70}\x{6B72}\x{6B73}\x{6B74}\x{6B76}\x{6B77}'
. '\x{6B78}\x{6B79}\x{6B7A}\x{6B7B}\x{6B7C}\x{6B7E}\x{6B7F}\x{6B80}\x{6B81}'
. '\x{6B82}\x{6B83}\x{6B84}\x{6B85}\x{6B86}\x{6B87}\x{6B88}\x{6B89}\x{6B8A}'
. '\x{6B8B}\x{6B8C}\x{6B8D}\x{6B8E}\x{6B8F}\x{6B90}\x{6B91}\x{6B92}\x{6B93}'
. '\x{6B94}\x{6B95}\x{6B96}\x{6B97}\x{6B98}\x{6B99}\x{6B9A}\x{6B9B}\x{6B9C}'
. '\x{6B9D}\x{6B9E}\x{6B9F}\x{6BA0}\x{6BA1}\x{6BA2}\x{6BA3}\x{6BA4}\x{6BA5}'
. '\x{6BA6}\x{6BA7}\x{6BA8}\x{6BA9}\x{6BAA}\x{6BAB}\x{6BAC}\x{6BAD}\x{6BAE}'
. '\x{6BAF}\x{6BB0}\x{6BB2}\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB6}\x{6BB7}\x{6BB9}'
. '\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBD}\x{6BBE}\x{6BBF}\x{6BC0}\x{6BC1}\x{6BC2}'
. '\x{6BC3}\x{6BC4}\x{6BC5}\x{6BC6}\x{6BC7}\x{6BC8}\x{6BC9}\x{6BCA}\x{6BCB}'
. '\x{6BCC}\x{6BCD}\x{6BCE}\x{6BCF}\x{6BD0}\x{6BD1}\x{6BD2}\x{6BD3}\x{6BD4}'
. '\x{6BD5}\x{6BD6}\x{6BD7}\x{6BD8}\x{6BD9}\x{6BDA}\x{6BDB}\x{6BDC}\x{6BDD}'
. '\x{6BDE}\x{6BDF}\x{6BE0}\x{6BE1}\x{6BE2}\x{6BE3}\x{6BE4}\x{6BE5}\x{6BE6}'
. '\x{6BE7}\x{6BE8}\x{6BEA}\x{6BEB}\x{6BEC}\x{6BED}\x{6BEE}\x{6BEF}\x{6BF0}'
. '\x{6BF2}\x{6BF3}\x{6BF5}\x{6BF6}\x{6BF7}\x{6BF8}\x{6BF9}\x{6BFB}\x{6BFC}'
. '\x{6BFD}\x{6BFE}\x{6BFF}\x{6C00}\x{6C01}\x{6C02}\x{6C03}\x{6C04}\x{6C05}'
. '\x{6C06}\x{6C07}\x{6C08}\x{6C09}\x{6C0B}\x{6C0C}\x{6C0D}\x{6C0E}\x{6C0F}'
. '\x{6C10}\x{6C11}\x{6C12}\x{6C13}\x{6C14}\x{6C15}\x{6C16}\x{6C18}\x{6C19}'
. '\x{6C1A}\x{6C1B}\x{6C1D}\x{6C1E}\x{6C1F}\x{6C20}\x{6C21}\x{6C22}\x{6C23}'
. '\x{6C24}\x{6C25}\x{6C26}\x{6C27}\x{6C28}\x{6C29}\x{6C2A}\x{6C2B}\x{6C2C}'
. '\x{6C2E}\x{6C2F}\x{6C30}\x{6C31}\x{6C32}\x{6C33}\x{6C34}\x{6C35}\x{6C36}'
. '\x{6C37}\x{6C38}\x{6C3A}\x{6C3B}\x{6C3D}\x{6C3E}\x{6C3F}\x{6C40}\x{6C41}'
. '\x{6C42}\x{6C43}\x{6C44}\x{6C46}\x{6C47}\x{6C48}\x{6C49}\x{6C4A}\x{6C4B}'
. '\x{6C4C}\x{6C4D}\x{6C4E}\x{6C4F}\x{6C50}\x{6C51}\x{6C52}\x{6C53}\x{6C54}'
. '\x{6C55}\x{6C56}\x{6C57}\x{6C58}\x{6C59}\x{6C5A}\x{6C5B}\x{6C5C}\x{6C5D}'
. '\x{6C5E}\x{6C5F}\x{6C60}\x{6C61}\x{6C62}\x{6C63}\x{6C64}\x{6C65}\x{6C66}'
. '\x{6C67}\x{6C68}\x{6C69}\x{6C6A}\x{6C6B}\x{6C6D}\x{6C6F}\x{6C70}\x{6C71}'
. '\x{6C72}\x{6C73}\x{6C74}\x{6C75}\x{6C76}\x{6C77}\x{6C78}\x{6C79}\x{6C7A}'
. '\x{6C7B}\x{6C7C}\x{6C7D}\x{6C7E}\x{6C7F}\x{6C80}\x{6C81}\x{6C82}\x{6C83}'
. '\x{6C84}\x{6C85}\x{6C86}\x{6C87}\x{6C88}\x{6C89}\x{6C8A}\x{6C8B}\x{6C8C}'
. '\x{6C8D}\x{6C8E}\x{6C8F}\x{6C90}\x{6C91}\x{6C92}\x{6C93}\x{6C94}\x{6C95}'
. '\x{6C96}\x{6C97}\x{6C98}\x{6C99}\x{6C9A}\x{6C9B}\x{6C9C}\x{6C9D}\x{6C9E}'
. '\x{6C9F}\x{6CA1}\x{6CA2}\x{6CA3}\x{6CA4}\x{6CA5}\x{6CA6}\x{6CA7}\x{6CA8}'
. '\x{6CA9}\x{6CAA}\x{6CAB}\x{6CAC}\x{6CAD}\x{6CAE}\x{6CAF}\x{6CB0}\x{6CB1}'
. '\x{6CB2}\x{6CB3}\x{6CB4}\x{6CB5}\x{6CB6}\x{6CB7}\x{6CB8}\x{6CB9}\x{6CBA}'
. '\x{6CBB}\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC0}\x{6CC1}\x{6CC2}\x{6CC3}'
. '\x{6CC4}\x{6CC5}\x{6CC6}\x{6CC7}\x{6CC8}\x{6CC9}\x{6CCA}\x{6CCB}\x{6CCC}'
. '\x{6CCD}\x{6CCE}\x{6CCF}\x{6CD0}\x{6CD1}\x{6CD2}\x{6CD3}\x{6CD4}\x{6CD5}'
. '\x{6CD6}\x{6CD7}\x{6CD9}\x{6CDA}\x{6CDB}\x{6CDC}\x{6CDD}\x{6CDE}\x{6CDF}'
. '\x{6CE0}\x{6CE1}\x{6CE2}\x{6CE3}\x{6CE4}\x{6CE5}\x{6CE6}\x{6CE7}\x{6CE8}'
. '\x{6CE9}\x{6CEA}\x{6CEB}\x{6CEC}\x{6CED}\x{6CEE}\x{6CEF}\x{6CF0}\x{6CF1}'
. '\x{6CF2}\x{6CF3}\x{6CF5}\x{6CF6}\x{6CF7}\x{6CF8}\x{6CF9}\x{6CFA}\x{6CFB}'
. '\x{6CFC}\x{6CFD}\x{6CFE}\x{6CFF}\x{6D00}\x{6D01}\x{6D03}\x{6D04}\x{6D05}'
. '\x{6D06}\x{6D07}\x{6D08}\x{6D09}\x{6D0A}\x{6D0B}\x{6D0C}\x{6D0D}\x{6D0E}'
. '\x{6D0F}\x{6D10}\x{6D11}\x{6D12}\x{6D13}\x{6D14}\x{6D15}\x{6D16}\x{6D17}'
. '\x{6D18}\x{6D19}\x{6D1A}\x{6D1B}\x{6D1D}\x{6D1E}\x{6D1F}\x{6D20}\x{6D21}'
. '\x{6D22}\x{6D23}\x{6D25}\x{6D26}\x{6D27}\x{6D28}\x{6D29}\x{6D2A}\x{6D2B}'
. '\x{6D2C}\x{6D2D}\x{6D2E}\x{6D2F}\x{6D30}\x{6D31}\x{6D32}\x{6D33}\x{6D34}'
. '\x{6D35}\x{6D36}\x{6D37}\x{6D38}\x{6D39}\x{6D3A}\x{6D3B}\x{6D3C}\x{6D3D}'
. '\x{6D3E}\x{6D3F}\x{6D40}\x{6D41}\x{6D42}\x{6D43}\x{6D44}\x{6D45}\x{6D46}'
. '\x{6D47}\x{6D48}\x{6D49}\x{6D4A}\x{6D4B}\x{6D4C}\x{6D4D}\x{6D4E}\x{6D4F}'
. '\x{6D50}\x{6D51}\x{6D52}\x{6D53}\x{6D54}\x{6D55}\x{6D56}\x{6D57}\x{6D58}'
. '\x{6D59}\x{6D5A}\x{6D5B}\x{6D5C}\x{6D5D}\x{6D5E}\x{6D5F}\x{6D60}\x{6D61}'
. '\x{6D62}\x{6D63}\x{6D64}\x{6D65}\x{6D66}\x{6D67}\x{6D68}\x{6D69}\x{6D6A}'
. '\x{6D6B}\x{6D6C}\x{6D6D}\x{6D6E}\x{6D6F}\x{6D70}\x{6D72}\x{6D73}\x{6D74}'
. '\x{6D75}\x{6D76}\x{6D77}\x{6D78}\x{6D79}\x{6D7A}\x{6D7B}\x{6D7C}\x{6D7D}'
. '\x{6D7E}\x{6D7F}\x{6D80}\x{6D82}\x{6D83}\x{6D84}\x{6D85}\x{6D86}\x{6D87}'
. '\x{6D88}\x{6D89}\x{6D8A}\x{6D8B}\x{6D8C}\x{6D8D}\x{6D8E}\x{6D8F}\x{6D90}'
. '\x{6D91}\x{6D92}\x{6D93}\x{6D94}\x{6D95}\x{6D97}\x{6D98}\x{6D99}\x{6D9A}'
. '\x{6D9B}\x{6D9D}\x{6D9E}\x{6D9F}\x{6DA0}\x{6DA1}\x{6DA2}\x{6DA3}\x{6DA4}'
. '\x{6DA5}\x{6DA6}\x{6DA7}\x{6DA8}\x{6DA9}\x{6DAA}\x{6DAB}\x{6DAC}\x{6DAD}'
. '\x{6DAE}\x{6DAF}\x{6DB2}\x{6DB3}\x{6DB4}\x{6DB5}\x{6DB7}\x{6DB8}\x{6DB9}'
. '\x{6DBA}\x{6DBB}\x{6DBC}\x{6DBD}\x{6DBE}\x{6DBF}\x{6DC0}\x{6DC1}\x{6DC2}'
. '\x{6DC3}\x{6DC4}\x{6DC5}\x{6DC6}\x{6DC7}\x{6DC8}\x{6DC9}\x{6DCA}\x{6DCB}'
. '\x{6DCC}\x{6DCD}\x{6DCE}\x{6DCF}\x{6DD0}\x{6DD1}\x{6DD2}\x{6DD3}\x{6DD4}'
. '\x{6DD5}\x{6DD6}\x{6DD7}\x{6DD8}\x{6DD9}\x{6DDA}\x{6DDB}\x{6DDC}\x{6DDD}'
. '\x{6DDE}\x{6DDF}\x{6DE0}\x{6DE1}\x{6DE2}\x{6DE3}\x{6DE4}\x{6DE5}\x{6DE6}'
. '\x{6DE7}\x{6DE8}\x{6DE9}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DED}\x{6DEE}\x{6DEF}'
. '\x{6DF0}\x{6DF1}\x{6DF2}\x{6DF3}\x{6DF4}\x{6DF5}\x{6DF6}\x{6DF7}\x{6DF8}'
. '\x{6DF9}\x{6DFA}\x{6DFB}\x{6DFC}\x{6DFD}\x{6E00}\x{6E03}\x{6E04}\x{6E05}'
. '\x{6E07}\x{6E08}\x{6E09}\x{6E0A}\x{6E0B}\x{6E0C}\x{6E0D}\x{6E0E}\x{6E0F}'
. '\x{6E10}\x{6E11}\x{6E14}\x{6E15}\x{6E16}\x{6E17}\x{6E19}\x{6E1A}\x{6E1B}'
. '\x{6E1C}\x{6E1D}\x{6E1E}\x{6E1F}\x{6E20}\x{6E21}\x{6E22}\x{6E23}\x{6E24}'
. '\x{6E25}\x{6E26}\x{6E27}\x{6E28}\x{6E29}\x{6E2B}\x{6E2C}\x{6E2D}\x{6E2E}'
. '\x{6E2F}\x{6E30}\x{6E31}\x{6E32}\x{6E33}\x{6E34}\x{6E35}\x{6E36}\x{6E37}'
. '\x{6E38}\x{6E39}\x{6E3A}\x{6E3B}\x{6E3C}\x{6E3D}\x{6E3E}\x{6E3F}\x{6E40}'
. '\x{6E41}\x{6E42}\x{6E43}\x{6E44}\x{6E45}\x{6E46}\x{6E47}\x{6E48}\x{6E49}'
. '\x{6E4A}\x{6E4B}\x{6E4D}\x{6E4E}\x{6E4F}\x{6E50}\x{6E51}\x{6E52}\x{6E53}'
. '\x{6E54}\x{6E55}\x{6E56}\x{6E57}\x{6E58}\x{6E59}\x{6E5A}\x{6E5B}\x{6E5C}'
. '\x{6E5D}\x{6E5E}\x{6E5F}\x{6E60}\x{6E61}\x{6E62}\x{6E63}\x{6E64}\x{6E65}'
. '\x{6E66}\x{6E67}\x{6E68}\x{6E69}\x{6E6A}\x{6E6B}\x{6E6D}\x{6E6E}\x{6E6F}'
. '\x{6E70}\x{6E71}\x{6E72}\x{6E73}\x{6E74}\x{6E75}\x{6E77}\x{6E78}\x{6E79}'
. '\x{6E7E}\x{6E7F}\x{6E80}\x{6E81}\x{6E82}\x{6E83}\x{6E84}\x{6E85}\x{6E86}'
. '\x{6E87}\x{6E88}\x{6E89}\x{6E8A}\x{6E8D}\x{6E8E}\x{6E8F}\x{6E90}\x{6E91}'
. '\x{6E92}\x{6E93}\x{6E94}\x{6E96}\x{6E97}\x{6E98}\x{6E99}\x{6E9A}\x{6E9B}'
. '\x{6E9C}\x{6E9D}\x{6E9E}\x{6E9F}\x{6EA0}\x{6EA1}\x{6EA2}\x{6EA3}\x{6EA4}'
. '\x{6EA5}\x{6EA6}\x{6EA7}\x{6EA8}\x{6EA9}\x{6EAA}\x{6EAB}\x{6EAC}\x{6EAD}'
. '\x{6EAE}\x{6EAF}\x{6EB0}\x{6EB1}\x{6EB2}\x{6EB3}\x{6EB4}\x{6EB5}\x{6EB6}'
. '\x{6EB7}\x{6EB8}\x{6EB9}\x{6EBA}\x{6EBB}\x{6EBC}\x{6EBD}\x{6EBE}\x{6EBF}'
. '\x{6EC0}\x{6EC1}\x{6EC2}\x{6EC3}\x{6EC4}\x{6EC5}\x{6EC6}\x{6EC7}\x{6EC8}'
. '\x{6EC9}\x{6ECA}\x{6ECB}\x{6ECC}\x{6ECD}\x{6ECE}\x{6ECF}\x{6ED0}\x{6ED1}'
. '\x{6ED2}\x{6ED3}\x{6ED4}\x{6ED5}\x{6ED6}\x{6ED7}\x{6ED8}\x{6ED9}\x{6EDA}'
. '\x{6EDC}\x{6EDE}\x{6EDF}\x{6EE0}\x{6EE1}\x{6EE2}\x{6EE4}\x{6EE5}\x{6EE6}'
. '\x{6EE7}\x{6EE8}\x{6EE9}\x{6EEA}\x{6EEB}\x{6EEC}\x{6EED}\x{6EEE}\x{6EEF}'
. '\x{6EF0}\x{6EF1}\x{6EF2}\x{6EF3}\x{6EF4}\x{6EF5}\x{6EF6}\x{6EF7}\x{6EF8}'
. '\x{6EF9}\x{6EFA}\x{6EFB}\x{6EFC}\x{6EFD}\x{6EFE}\x{6EFF}\x{6F00}\x{6F01}'
. '\x{6F02}\x{6F03}\x{6F05}\x{6F06}\x{6F07}\x{6F08}\x{6F09}\x{6F0A}\x{6F0C}'
. '\x{6F0D}\x{6F0E}\x{6F0F}\x{6F10}\x{6F11}\x{6F12}\x{6F13}\x{6F14}\x{6F15}'
. '\x{6F16}\x{6F17}\x{6F18}\x{6F19}\x{6F1A}\x{6F1B}\x{6F1C}\x{6F1D}\x{6F1E}'
. '\x{6F1F}\x{6F20}\x{6F21}\x{6F22}\x{6F23}\x{6F24}\x{6F25}\x{6F26}\x{6F27}'
. '\x{6F28}\x{6F29}\x{6F2A}\x{6F2B}\x{6F2C}\x{6F2D}\x{6F2E}\x{6F2F}\x{6F30}'
. '\x{6F31}\x{6F32}\x{6F33}\x{6F34}\x{6F35}\x{6F36}\x{6F37}\x{6F38}\x{6F39}'
. '\x{6F3A}\x{6F3B}\x{6F3C}\x{6F3D}\x{6F3E}\x{6F3F}\x{6F40}\x{6F41}\x{6F43}'
. '\x{6F44}\x{6F45}\x{6F46}\x{6F47}\x{6F49}\x{6F4B}\x{6F4C}\x{6F4D}\x{6F4E}'
. '\x{6F4F}\x{6F50}\x{6F51}\x{6F52}\x{6F53}\x{6F54}\x{6F55}\x{6F56}\x{6F57}'
. '\x{6F58}\x{6F59}\x{6F5A}\x{6F5B}\x{6F5C}\x{6F5D}\x{6F5E}\x{6F5F}\x{6F60}'
. '\x{6F61}\x{6F62}\x{6F63}\x{6F64}\x{6F65}\x{6F66}\x{6F67}\x{6F68}\x{6F69}'
. '\x{6F6A}\x{6F6B}\x{6F6C}\x{6F6D}\x{6F6E}\x{6F6F}\x{6F70}\x{6F71}\x{6F72}'
. '\x{6F73}\x{6F74}\x{6F75}\x{6F76}\x{6F77}\x{6F78}\x{6F7A}\x{6F7B}\x{6F7C}'
. '\x{6F7D}\x{6F7E}\x{6F7F}\x{6F80}\x{6F81}\x{6F82}\x{6F83}\x{6F84}\x{6F85}'
. '\x{6F86}\x{6F87}\x{6F88}\x{6F89}\x{6F8A}\x{6F8B}\x{6F8C}\x{6F8D}\x{6F8E}'
. '\x{6F8F}\x{6F90}\x{6F91}\x{6F92}\x{6F93}\x{6F94}\x{6F95}\x{6F96}\x{6F97}'
. '\x{6F99}\x{6F9B}\x{6F9C}\x{6F9D}\x{6F9E}\x{6FA0}\x{6FA1}\x{6FA2}\x{6FA3}'
. '\x{6FA4}\x{6FA5}\x{6FA6}\x{6FA7}\x{6FA8}\x{6FA9}\x{6FAA}\x{6FAB}\x{6FAC}'
. '\x{6FAD}\x{6FAE}\x{6FAF}\x{6FB0}\x{6FB1}\x{6FB2}\x{6FB3}\x{6FB4}\x{6FB5}'
. '\x{6FB6}\x{6FB8}\x{6FB9}\x{6FBA}\x{6FBB}\x{6FBC}\x{6FBD}\x{6FBE}\x{6FBF}'
. '\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC4}\x{6FC6}\x{6FC7}\x{6FC8}\x{6FC9}'
. '\x{6FCA}\x{6FCB}\x{6FCC}\x{6FCD}\x{6FCE}\x{6FCF}\x{6FD1}\x{6FD2}\x{6FD4}'
. '\x{6FD5}\x{6FD6}\x{6FD7}\x{6FD8}\x{6FD9}\x{6FDA}\x{6FDB}\x{6FDC}\x{6FDD}'
. '\x{6FDE}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE2}\x{6FE3}\x{6FE4}\x{6FE5}\x{6FE6}'
. '\x{6FE7}\x{6FE8}\x{6FE9}\x{6FEA}\x{6FEB}\x{6FEC}\x{6FED}\x{6FEE}\x{6FEF}'
. '\x{6FF0}\x{6FF1}\x{6FF2}\x{6FF3}\x{6FF4}\x{6FF6}\x{6FF7}\x{6FF8}\x{6FF9}'
. '\x{6FFA}\x{6FFB}\x{6FFC}\x{6FFE}\x{6FFF}\x{7000}\x{7001}\x{7002}\x{7003}'
. '\x{7004}\x{7005}\x{7006}\x{7007}\x{7008}\x{7009}\x{700A}\x{700B}\x{700C}'
. '\x{700D}\x{700E}\x{700F}\x{7011}\x{7012}\x{7014}\x{7015}\x{7016}\x{7017}'
. '\x{7018}\x{7019}\x{701A}\x{701B}\x{701C}\x{701D}\x{701F}\x{7020}\x{7021}'
. '\x{7022}\x{7023}\x{7024}\x{7025}\x{7026}\x{7027}\x{7028}\x{7029}\x{702A}'
. '\x{702B}\x{702C}\x{702D}\x{702E}\x{702F}\x{7030}\x{7031}\x{7032}\x{7033}'
. '\x{7034}\x{7035}\x{7036}\x{7037}\x{7038}\x{7039}\x{703A}\x{703B}\x{703C}'
. '\x{703D}\x{703E}\x{703F}\x{7040}\x{7041}\x{7042}\x{7043}\x{7044}\x{7045}'
. '\x{7046}\x{7048}\x{7049}\x{704A}\x{704C}\x{704D}\x{704F}\x{7050}\x{7051}'
. '\x{7052}\x{7053}\x{7054}\x{7055}\x{7056}\x{7057}\x{7058}\x{7059}\x{705A}'
. '\x{705B}\x{705C}\x{705D}\x{705E}\x{705F}\x{7060}\x{7061}\x{7062}\x{7063}'
. '\x{7064}\x{7065}\x{7066}\x{7067}\x{7068}\x{7069}\x{706A}\x{706B}\x{706C}'
. '\x{706D}\x{706E}\x{706F}\x{7070}\x{7071}\x{7074}\x{7075}\x{7076}\x{7077}'
. '\x{7078}\x{7079}\x{707A}\x{707C}\x{707D}\x{707E}\x{707F}\x{7080}\x{7082}'
. '\x{7083}\x{7084}\x{7085}\x{7086}\x{7087}\x{7088}\x{7089}\x{708A}\x{708B}'
. '\x{708C}\x{708E}\x{708F}\x{7090}\x{7091}\x{7092}\x{7093}\x{7094}\x{7095}'
. '\x{7096}\x{7098}\x{7099}\x{709A}\x{709C}\x{709D}\x{709E}\x{709F}\x{70A0}'
. '\x{70A1}\x{70A2}\x{70A3}\x{70A4}\x{70A5}\x{70A6}\x{70A7}\x{70A8}\x{70A9}'
. '\x{70AB}\x{70AC}\x{70AD}\x{70AE}\x{70AF}\x{70B0}\x{70B1}\x{70B3}\x{70B4}'
. '\x{70B5}\x{70B7}\x{70B8}\x{70B9}\x{70BA}\x{70BB}\x{70BC}\x{70BD}\x{70BE}'
. '\x{70BF}\x{70C0}\x{70C1}\x{70C2}\x{70C3}\x{70C4}\x{70C5}\x{70C6}\x{70C7}'
. '\x{70C8}\x{70C9}\x{70CA}\x{70CB}\x{70CC}\x{70CD}\x{70CE}\x{70CF}\x{70D0}'
. '\x{70D1}\x{70D2}\x{70D3}\x{70D4}\x{70D6}\x{70D7}\x{70D8}\x{70D9}\x{70DA}'
. '\x{70DB}\x{70DC}\x{70DD}\x{70DE}\x{70DF}\x{70E0}\x{70E1}\x{70E2}\x{70E3}'
. '\x{70E4}\x{70E5}\x{70E6}\x{70E7}\x{70E8}\x{70E9}\x{70EA}\x{70EB}\x{70EC}'
. '\x{70ED}\x{70EE}\x{70EF}\x{70F0}\x{70F1}\x{70F2}\x{70F3}\x{70F4}\x{70F5}'
. '\x{70F6}\x{70F7}\x{70F8}\x{70F9}\x{70FA}\x{70FB}\x{70FC}\x{70FD}\x{70FF}'
. '\x{7100}\x{7101}\x{7102}\x{7103}\x{7104}\x{7105}\x{7106}\x{7107}\x{7109}'
. '\x{710A}\x{710B}\x{710C}\x{710D}\x{710E}\x{710F}\x{7110}\x{7111}\x{7112}'
. '\x{7113}\x{7115}\x{7116}\x{7117}\x{7118}\x{7119}\x{711A}\x{711B}\x{711C}'
. '\x{711D}\x{711E}\x{711F}\x{7120}\x{7121}\x{7122}\x{7123}\x{7125}\x{7126}'
. '\x{7127}\x{7128}\x{7129}\x{712A}\x{712B}\x{712C}\x{712D}\x{712E}\x{712F}'
. '\x{7130}\x{7131}\x{7132}\x{7135}\x{7136}\x{7137}\x{7138}\x{7139}\x{713A}'
. '\x{713B}\x{713D}\x{713E}\x{713F}\x{7140}\x{7141}\x{7142}\x{7143}\x{7144}'
. '\x{7145}\x{7146}\x{7147}\x{7148}\x{7149}\x{714A}\x{714B}\x{714C}\x{714D}'
. '\x{714E}\x{714F}\x{7150}\x{7151}\x{7152}\x{7153}\x{7154}\x{7156}\x{7158}'
. '\x{7159}\x{715A}\x{715B}\x{715C}\x{715D}\x{715E}\x{715F}\x{7160}\x{7161}'
. '\x{7162}\x{7163}\x{7164}\x{7165}\x{7166}\x{7167}\x{7168}\x{7169}\x{716A}'
. '\x{716C}\x{716E}\x{716F}\x{7170}\x{7171}\x{7172}\x{7173}\x{7174}\x{7175}'
. '\x{7176}\x{7177}\x{7178}\x{7179}\x{717A}\x{717B}\x{717C}\x{717D}\x{717E}'
. '\x{717F}\x{7180}\x{7181}\x{7182}\x{7183}\x{7184}\x{7185}\x{7186}\x{7187}'
. '\x{7188}\x{7189}\x{718A}\x{718B}\x{718C}\x{718E}\x{718F}\x{7190}\x{7191}'
. '\x{7192}\x{7193}\x{7194}\x{7195}\x{7197}\x{7198}\x{7199}\x{719A}\x{719B}'
. '\x{719C}\x{719D}\x{719E}\x{719F}\x{71A0}\x{71A1}\x{71A2}\x{71A3}\x{71A4}'
. '\x{71A5}\x{71A7}\x{71A8}\x{71A9}\x{71AA}\x{71AC}\x{71AD}\x{71AE}\x{71AF}'
. '\x{71B0}\x{71B1}\x{71B2}\x{71B3}\x{71B4}\x{71B5}\x{71B7}\x{71B8}\x{71B9}'
. '\x{71BA}\x{71BB}\x{71BC}\x{71BD}\x{71BE}\x{71BF}\x{71C0}\x{71C1}\x{71C2}'
. '\x{71C3}\x{71C4}\x{71C5}\x{71C6}\x{71C7}\x{71C8}\x{71C9}\x{71CA}\x{71CB}'
. '\x{71CD}\x{71CE}\x{71CF}\x{71D0}\x{71D1}\x{71D2}\x{71D4}\x{71D5}\x{71D6}'
. '\x{71D7}\x{71D8}\x{71D9}\x{71DA}\x{71DB}\x{71DC}\x{71DD}\x{71DE}\x{71DF}'
. '\x{71E0}\x{71E1}\x{71E2}\x{71E3}\x{71E4}\x{71E5}\x{71E6}\x{71E7}\x{71E8}'
. '\x{71E9}\x{71EA}\x{71EB}\x{71EC}\x{71ED}\x{71EE}\x{71EF}\x{71F0}\x{71F1}'
. '\x{71F2}\x{71F4}\x{71F5}\x{71F6}\x{71F7}\x{71F8}\x{71F9}\x{71FB}\x{71FC}'
. '\x{71FD}\x{71FE}\x{71FF}\x{7201}\x{7202}\x{7203}\x{7204}\x{7205}\x{7206}'
. '\x{7207}\x{7208}\x{7209}\x{720A}\x{720C}\x{720D}\x{720E}\x{720F}\x{7210}'
. '\x{7212}\x{7213}\x{7214}\x{7216}\x{7218}\x{7219}\x{721A}\x{721B}\x{721C}'
. '\x{721D}\x{721E}\x{721F}\x{7221}\x{7222}\x{7223}\x{7226}\x{7227}\x{7228}'
. '\x{7229}\x{722A}\x{722B}\x{722C}\x{722D}\x{722E}\x{7230}\x{7231}\x{7232}'
. '\x{7233}\x{7235}\x{7236}\x{7237}\x{7238}\x{7239}\x{723A}\x{723B}\x{723C}'
. '\x{723D}\x{723E}\x{723F}\x{7240}\x{7241}\x{7242}\x{7243}\x{7244}\x{7246}'
. '\x{7247}\x{7248}\x{7249}\x{724A}\x{724B}\x{724C}\x{724D}\x{724F}\x{7251}'
. '\x{7252}\x{7253}\x{7254}\x{7256}\x{7257}\x{7258}\x{7259}\x{725A}\x{725B}'
. '\x{725C}\x{725D}\x{725E}\x{725F}\x{7260}\x{7261}\x{7262}\x{7263}\x{7264}'
. '\x{7265}\x{7266}\x{7267}\x{7268}\x{7269}\x{726A}\x{726B}\x{726C}\x{726D}'
. '\x{726E}\x{726F}\x{7270}\x{7271}\x{7272}\x{7273}\x{7274}\x{7275}\x{7276}'
. '\x{7277}\x{7278}\x{7279}\x{727A}\x{727B}\x{727C}\x{727D}\x{727E}\x{727F}'
. '\x{7280}\x{7281}\x{7282}\x{7283}\x{7284}\x{7285}\x{7286}\x{7287}\x{7288}'
. '\x{7289}\x{728A}\x{728B}\x{728C}\x{728D}\x{728E}\x{728F}\x{7290}\x{7291}'
. '\x{7292}\x{7293}\x{7294}\x{7295}\x{7296}\x{7297}\x{7298}\x{7299}\x{729A}'
. '\x{729B}\x{729C}\x{729D}\x{729E}\x{729F}\x{72A1}\x{72A2}\x{72A3}\x{72A4}'
. '\x{72A5}\x{72A6}\x{72A7}\x{72A8}\x{72A9}\x{72AA}\x{72AC}\x{72AD}\x{72AE}'
. '\x{72AF}\x{72B0}\x{72B1}\x{72B2}\x{72B3}\x{72B4}\x{72B5}\x{72B6}\x{72B7}'
. '\x{72B8}\x{72B9}\x{72BA}\x{72BB}\x{72BC}\x{72BD}\x{72BF}\x{72C0}\x{72C1}'
. '\x{72C2}\x{72C3}\x{72C4}\x{72C5}\x{72C6}\x{72C7}\x{72C8}\x{72C9}\x{72CA}'
. '\x{72CB}\x{72CC}\x{72CD}\x{72CE}\x{72CF}\x{72D0}\x{72D1}\x{72D2}\x{72D3}'
. '\x{72D4}\x{72D5}\x{72D6}\x{72D7}\x{72D8}\x{72D9}\x{72DA}\x{72DB}\x{72DC}'
. '\x{72DD}\x{72DE}\x{72DF}\x{72E0}\x{72E1}\x{72E2}\x{72E3}\x{72E4}\x{72E5}'
. '\x{72E6}\x{72E7}\x{72E8}\x{72E9}\x{72EA}\x{72EB}\x{72EC}\x{72ED}\x{72EE}'
. '\x{72EF}\x{72F0}\x{72F1}\x{72F2}\x{72F3}\x{72F4}\x{72F5}\x{72F6}\x{72F7}'
. '\x{72F8}\x{72F9}\x{72FA}\x{72FB}\x{72FC}\x{72FD}\x{72FE}\x{72FF}\x{7300}'
. '\x{7301}\x{7303}\x{7304}\x{7305}\x{7306}\x{7307}\x{7308}\x{7309}\x{730A}'
. '\x{730B}\x{730C}\x{730D}\x{730E}\x{730F}\x{7311}\x{7312}\x{7313}\x{7314}'
. '\x{7315}\x{7316}\x{7317}\x{7318}\x{7319}\x{731A}\x{731B}\x{731C}\x{731D}'
. '\x{731E}\x{7320}\x{7321}\x{7322}\x{7323}\x{7324}\x{7325}\x{7326}\x{7327}'
. '\x{7329}\x{732A}\x{732B}\x{732C}\x{732D}\x{732E}\x{7330}\x{7331}\x{7332}'
. '\x{7333}\x{7334}\x{7335}\x{7336}\x{7337}\x{7338}\x{7339}\x{733A}\x{733B}'
. '\x{733C}\x{733D}\x{733E}\x{733F}\x{7340}\x{7341}\x{7342}\x{7343}\x{7344}'
. '\x{7345}\x{7346}\x{7347}\x{7348}\x{7349}\x{734A}\x{734B}\x{734C}\x{734D}'
. '\x{734E}\x{7350}\x{7351}\x{7352}\x{7354}\x{7355}\x{7356}\x{7357}\x{7358}'
. '\x{7359}\x{735A}\x{735B}\x{735C}\x{735D}\x{735E}\x{735F}\x{7360}\x{7361}'
. '\x{7362}\x{7364}\x{7365}\x{7366}\x{7367}\x{7368}\x{7369}\x{736A}\x{736B}'
. '\x{736C}\x{736D}\x{736E}\x{736F}\x{7370}\x{7371}\x{7372}\x{7373}\x{7374}'
. '\x{7375}\x{7376}\x{7377}\x{7378}\x{7379}\x{737A}\x{737B}\x{737C}\x{737D}'
. '\x{737E}\x{737F}\x{7380}\x{7381}\x{7382}\x{7383}\x{7384}\x{7385}\x{7386}'
. '\x{7387}\x{7388}\x{7389}\x{738A}\x{738B}\x{738C}\x{738D}\x{738E}\x{738F}'
. '\x{7390}\x{7391}\x{7392}\x{7393}\x{7394}\x{7395}\x{7396}\x{7397}\x{7398}'
. '\x{7399}\x{739A}\x{739B}\x{739D}\x{739E}\x{739F}\x{73A0}\x{73A1}\x{73A2}'
. '\x{73A3}\x{73A4}\x{73A5}\x{73A6}\x{73A7}\x{73A8}\x{73A9}\x{73AA}\x{73AB}'
. '\x{73AC}\x{73AD}\x{73AE}\x{73AF}\x{73B0}\x{73B1}\x{73B2}\x{73B3}\x{73B4}'
. '\x{73B5}\x{73B6}\x{73B7}\x{73B8}\x{73B9}\x{73BA}\x{73BB}\x{73BC}\x{73BD}'
. '\x{73BE}\x{73BF}\x{73C0}\x{73C2}\x{73C3}\x{73C4}\x{73C5}\x{73C6}\x{73C7}'
. '\x{73C8}\x{73C9}\x{73CA}\x{73CB}\x{73CC}\x{73CD}\x{73CE}\x{73CF}\x{73D0}'
. '\x{73D1}\x{73D2}\x{73D3}\x{73D4}\x{73D5}\x{73D6}\x{73D7}\x{73D8}\x{73D9}'
. '\x{73DA}\x{73DB}\x{73DC}\x{73DD}\x{73DE}\x{73DF}\x{73E0}\x{73E2}\x{73E3}'
. '\x{73E5}\x{73E6}\x{73E7}\x{73E8}\x{73E9}\x{73EA}\x{73EB}\x{73EC}\x{73ED}'
. '\x{73EE}\x{73EF}\x{73F0}\x{73F1}\x{73F2}\x{73F4}\x{73F5}\x{73F6}\x{73F7}'
. '\x{73F8}\x{73F9}\x{73FA}\x{73FC}\x{73FD}\x{73FE}\x{73FF}\x{7400}\x{7401}'
. '\x{7402}\x{7403}\x{7404}\x{7405}\x{7406}\x{7407}\x{7408}\x{7409}\x{740A}'
. '\x{740B}\x{740C}\x{740D}\x{740E}\x{740F}\x{7410}\x{7411}\x{7412}\x{7413}'
. '\x{7414}\x{7415}\x{7416}\x{7417}\x{7419}\x{741A}\x{741B}\x{741C}\x{741D}'
. '\x{741E}\x{741F}\x{7420}\x{7421}\x{7422}\x{7423}\x{7424}\x{7425}\x{7426}'
. '\x{7427}\x{7428}\x{7429}\x{742A}\x{742B}\x{742C}\x{742D}\x{742E}\x{742F}'
. '\x{7430}\x{7431}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{7437}\x{7438}'
. '\x{743A}\x{743B}\x{743C}\x{743D}\x{743F}\x{7440}\x{7441}\x{7442}\x{7443}'
. '\x{7444}\x{7445}\x{7446}\x{7448}\x{744A}\x{744B}\x{744C}\x{744D}\x{744E}'
. '\x{744F}\x{7450}\x{7451}\x{7452}\x{7453}\x{7454}\x{7455}\x{7456}\x{7457}'
. '\x{7459}\x{745A}\x{745B}\x{745C}\x{745D}\x{745E}\x{745F}\x{7461}\x{7462}'
. '\x{7463}\x{7464}\x{7465}\x{7466}\x{7467}\x{7468}\x{7469}\x{746A}\x{746B}'
. '\x{746C}\x{746D}\x{746E}\x{746F}\x{7470}\x{7471}\x{7472}\x{7473}\x{7474}'
. '\x{7475}\x{7476}\x{7477}\x{7478}\x{7479}\x{747A}\x{747C}\x{747D}\x{747E}'
. '\x{747F}\x{7480}\x{7481}\x{7482}\x{7483}\x{7485}\x{7486}\x{7487}\x{7488}'
. '\x{7489}\x{748A}\x{748B}\x{748C}\x{748D}\x{748E}\x{748F}\x{7490}\x{7491}'
. '\x{7492}\x{7493}\x{7494}\x{7495}\x{7497}\x{7498}\x{7499}\x{749A}\x{749B}'
. '\x{749C}\x{749E}\x{749F}\x{74A0}\x{74A1}\x{74A3}\x{74A4}\x{74A5}\x{74A6}'
. '\x{74A7}\x{74A8}\x{74A9}\x{74AA}\x{74AB}\x{74AC}\x{74AD}\x{74AE}\x{74AF}'
. '\x{74B0}\x{74B1}\x{74B2}\x{74B3}\x{74B4}\x{74B5}\x{74B6}\x{74B7}\x{74B8}'
. '\x{74B9}\x{74BA}\x{74BB}\x{74BC}\x{74BD}\x{74BE}\x{74BF}\x{74C0}\x{74C1}'
. '\x{74C2}\x{74C3}\x{74C4}\x{74C5}\x{74C6}\x{74CA}\x{74CB}\x{74CD}\x{74CE}'
. '\x{74CF}\x{74D0}\x{74D1}\x{74D2}\x{74D3}\x{74D4}\x{74D5}\x{74D6}\x{74D7}'
. '\x{74D8}\x{74D9}\x{74DA}\x{74DB}\x{74DC}\x{74DD}\x{74DE}\x{74DF}\x{74E0}'
. '\x{74E1}\x{74E2}\x{74E3}\x{74E4}\x{74E5}\x{74E6}\x{74E7}\x{74E8}\x{74E9}'
. '\x{74EA}\x{74EC}\x{74ED}\x{74EE}\x{74EF}\x{74F0}\x{74F1}\x{74F2}\x{74F3}'
. '\x{74F4}\x{74F5}\x{74F6}\x{74F7}\x{74F8}\x{74F9}\x{74FA}\x{74FB}\x{74FC}'
. '\x{74FD}\x{74FE}\x{74FF}\x{7500}\x{7501}\x{7502}\x{7503}\x{7504}\x{7505}'
. '\x{7506}\x{7507}\x{7508}\x{7509}\x{750A}\x{750B}\x{750C}\x{750D}\x{750F}'
. '\x{7510}\x{7511}\x{7512}\x{7513}\x{7514}\x{7515}\x{7516}\x{7517}\x{7518}'
. '\x{7519}\x{751A}\x{751B}\x{751C}\x{751D}\x{751E}\x{751F}\x{7521}\x{7522}'
. '\x{7523}\x{7524}\x{7525}\x{7526}\x{7527}\x{7528}\x{7529}\x{752A}\x{752B}'
. '\x{752C}\x{752D}\x{752E}\x{752F}\x{7530}\x{7531}\x{7532}\x{7533}\x{7535}'
. '\x{7536}\x{7537}\x{7538}\x{7539}\x{753A}\x{753B}\x{753C}\x{753D}\x{753E}'
. '\x{753F}\x{7540}\x{7542}\x{7543}\x{7544}\x{7545}\x{7546}\x{7547}\x{7548}'
. '\x{7549}\x{754B}\x{754C}\x{754D}\x{754E}\x{754F}\x{7550}\x{7551}\x{7553}'
. '\x{7554}\x{7556}\x{7557}\x{7558}\x{7559}\x{755A}\x{755B}\x{755C}\x{755D}'
. '\x{755F}\x{7560}\x{7562}\x{7563}\x{7564}\x{7565}\x{7566}\x{7567}\x{7568}'
. '\x{7569}\x{756A}\x{756B}\x{756C}\x{756D}\x{756E}\x{756F}\x{7570}\x{7572}'
. '\x{7574}\x{7575}\x{7576}\x{7577}\x{7578}\x{7579}\x{757C}\x{757D}\x{757E}'
. '\x{757F}\x{7580}\x{7581}\x{7582}\x{7583}\x{7584}\x{7586}\x{7587}\x{7588}'
. '\x{7589}\x{758A}\x{758B}\x{758C}\x{758D}\x{758F}\x{7590}\x{7591}\x{7592}'
. '\x{7593}\x{7594}\x{7595}\x{7596}\x{7597}\x{7598}\x{7599}\x{759A}\x{759B}'
. '\x{759C}\x{759D}\x{759E}\x{759F}\x{75A0}\x{75A1}\x{75A2}\x{75A3}\x{75A4}'
. '\x{75A5}\x{75A6}\x{75A7}\x{75A8}\x{75AA}\x{75AB}\x{75AC}\x{75AD}\x{75AE}'
. '\x{75AF}\x{75B0}\x{75B1}\x{75B2}\x{75B3}\x{75B4}\x{75B5}\x{75B6}\x{75B8}'
. '\x{75B9}\x{75BA}\x{75BB}\x{75BC}\x{75BD}\x{75BE}\x{75BF}\x{75C0}\x{75C1}'
. '\x{75C2}\x{75C3}\x{75C4}\x{75C5}\x{75C6}\x{75C7}\x{75C8}\x{75C9}\x{75CA}'
. '\x{75CB}\x{75CC}\x{75CD}\x{75CE}\x{75CF}\x{75D0}\x{75D1}\x{75D2}\x{75D3}'
. '\x{75D4}\x{75D5}\x{75D6}\x{75D7}\x{75D8}\x{75D9}\x{75DA}\x{75DB}\x{75DD}'
. '\x{75DE}\x{75DF}\x{75E0}\x{75E1}\x{75E2}\x{75E3}\x{75E4}\x{75E5}\x{75E6}'
. '\x{75E7}\x{75E8}\x{75EA}\x{75EB}\x{75EC}\x{75ED}\x{75EF}\x{75F0}\x{75F1}'
. '\x{75F2}\x{75F3}\x{75F4}\x{75F5}\x{75F6}\x{75F7}\x{75F8}\x{75F9}\x{75FA}'
. '\x{75FB}\x{75FC}\x{75FD}\x{75FE}\x{75FF}\x{7600}\x{7601}\x{7602}\x{7603}'
. '\x{7604}\x{7605}\x{7606}\x{7607}\x{7608}\x{7609}\x{760A}\x{760B}\x{760C}'
. '\x{760D}\x{760E}\x{760F}\x{7610}\x{7611}\x{7612}\x{7613}\x{7614}\x{7615}'
. '\x{7616}\x{7617}\x{7618}\x{7619}\x{761A}\x{761B}\x{761C}\x{761D}\x{761E}'
. '\x{761F}\x{7620}\x{7621}\x{7622}\x{7623}\x{7624}\x{7625}\x{7626}\x{7627}'
. '\x{7628}\x{7629}\x{762A}\x{762B}\x{762D}\x{762E}\x{762F}\x{7630}\x{7631}'
. '\x{7632}\x{7633}\x{7634}\x{7635}\x{7636}\x{7637}\x{7638}\x{7639}\x{763A}'
. '\x{763B}\x{763C}\x{763D}\x{763E}\x{763F}\x{7640}\x{7641}\x{7642}\x{7643}'
. '\x{7646}\x{7647}\x{7648}\x{7649}\x{764A}\x{764B}\x{764C}\x{764D}\x{764F}'
. '\x{7650}\x{7652}\x{7653}\x{7654}\x{7656}\x{7657}\x{7658}\x{7659}\x{765A}'
. '\x{765B}\x{765C}\x{765D}\x{765E}\x{765F}\x{7660}\x{7661}\x{7662}\x{7663}'
. '\x{7664}\x{7665}\x{7666}\x{7667}\x{7668}\x{7669}\x{766A}\x{766B}\x{766C}'
. '\x{766D}\x{766E}\x{766F}\x{7670}\x{7671}\x{7672}\x{7674}\x{7675}\x{7676}'
. '\x{7677}\x{7678}\x{7679}\x{767B}\x{767C}\x{767D}\x{767E}\x{767F}\x{7680}'
. '\x{7681}\x{7682}\x{7683}\x{7684}\x{7685}\x{7686}\x{7687}\x{7688}\x{7689}'
. '\x{768A}\x{768B}\x{768C}\x{768E}\x{768F}\x{7690}\x{7691}\x{7692}\x{7693}'
. '\x{7694}\x{7695}\x{7696}\x{7697}\x{7698}\x{7699}\x{769A}\x{769B}\x{769C}'
. '\x{769D}\x{769E}\x{769F}\x{76A0}\x{76A3}\x{76A4}\x{76A6}\x{76A7}\x{76A9}'
. '\x{76AA}\x{76AB}\x{76AC}\x{76AD}\x{76AE}\x{76AF}\x{76B0}\x{76B1}\x{76B2}'
. '\x{76B4}\x{76B5}\x{76B7}\x{76B8}\x{76BA}\x{76BB}\x{76BC}\x{76BD}\x{76BE}'
. '\x{76BF}\x{76C0}\x{76C2}\x{76C3}\x{76C4}\x{76C5}\x{76C6}\x{76C7}\x{76C8}'
. '\x{76C9}\x{76CA}\x{76CD}\x{76CE}\x{76CF}\x{76D0}\x{76D1}\x{76D2}\x{76D3}'
. '\x{76D4}\x{76D5}\x{76D6}\x{76D7}\x{76D8}\x{76DA}\x{76DB}\x{76DC}\x{76DD}'
. '\x{76DE}\x{76DF}\x{76E0}\x{76E1}\x{76E2}\x{76E3}\x{76E4}\x{76E5}\x{76E6}'
. '\x{76E7}\x{76E8}\x{76E9}\x{76EA}\x{76EC}\x{76ED}\x{76EE}\x{76EF}\x{76F0}'
. '\x{76F1}\x{76F2}\x{76F3}\x{76F4}\x{76F5}\x{76F6}\x{76F7}\x{76F8}\x{76F9}'
. '\x{76FA}\x{76FB}\x{76FC}\x{76FD}\x{76FE}\x{76FF}\x{7701}\x{7703}\x{7704}'
. '\x{7705}\x{7706}\x{7707}\x{7708}\x{7709}\x{770A}\x{770B}\x{770C}\x{770D}'
. '\x{770F}\x{7710}\x{7711}\x{7712}\x{7713}\x{7714}\x{7715}\x{7716}\x{7717}'
. '\x{7718}\x{7719}\x{771A}\x{771B}\x{771C}\x{771D}\x{771E}\x{771F}\x{7720}'
. '\x{7722}\x{7723}\x{7725}\x{7726}\x{7727}\x{7728}\x{7729}\x{772A}\x{772C}'
. '\x{772D}\x{772E}\x{772F}\x{7730}\x{7731}\x{7732}\x{7733}\x{7734}\x{7735}'
. '\x{7736}\x{7737}\x{7738}\x{7739}\x{773A}\x{773B}\x{773C}\x{773D}\x{773E}'
. '\x{7740}\x{7741}\x{7743}\x{7744}\x{7745}\x{7746}\x{7747}\x{7748}\x{7749}'
. '\x{774A}\x{774B}\x{774C}\x{774D}\x{774E}\x{774F}\x{7750}\x{7751}\x{7752}'
. '\x{7753}\x{7754}\x{7755}\x{7756}\x{7757}\x{7758}\x{7759}\x{775A}\x{775B}'
. '\x{775C}\x{775D}\x{775E}\x{775F}\x{7760}\x{7761}\x{7762}\x{7763}\x{7765}'
. '\x{7766}\x{7767}\x{7768}\x{7769}\x{776A}\x{776B}\x{776C}\x{776D}\x{776E}'
. '\x{776F}\x{7770}\x{7771}\x{7772}\x{7773}\x{7774}\x{7775}\x{7776}\x{7777}'
. '\x{7778}\x{7779}\x{777A}\x{777B}\x{777C}\x{777D}\x{777E}\x{777F}\x{7780}'
. '\x{7781}\x{7782}\x{7783}\x{7784}\x{7785}\x{7786}\x{7787}\x{7788}\x{7789}'
. '\x{778A}\x{778B}\x{778C}\x{778D}\x{778E}\x{778F}\x{7790}\x{7791}\x{7792}'
. '\x{7793}\x{7794}\x{7795}\x{7797}\x{7798}\x{7799}\x{779A}\x{779B}\x{779C}'
. '\x{779D}\x{779E}\x{779F}\x{77A0}\x{77A1}\x{77A2}\x{77A3}\x{77A5}\x{77A6}'
. '\x{77A7}\x{77A8}\x{77A9}\x{77AA}\x{77AB}\x{77AC}\x{77AD}\x{77AE}\x{77AF}'
. '\x{77B0}\x{77B1}\x{77B2}\x{77B3}\x{77B4}\x{77B5}\x{77B6}\x{77B7}\x{77B8}'
. '\x{77B9}\x{77BA}\x{77BB}\x{77BC}\x{77BD}\x{77BF}\x{77C0}\x{77C2}\x{77C3}'
. '\x{77C4}\x{77C5}\x{77C6}\x{77C7}\x{77C8}\x{77C9}\x{77CA}\x{77CB}\x{77CC}'
. '\x{77CD}\x{77CE}\x{77CF}\x{77D0}\x{77D1}\x{77D3}\x{77D4}\x{77D5}\x{77D6}'
. '\x{77D7}\x{77D8}\x{77D9}\x{77DA}\x{77DB}\x{77DC}\x{77DE}\x{77DF}\x{77E0}'
. '\x{77E1}\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E8}\x{77E9}\x{77EA}\x{77EB}'
. '\x{77EC}\x{77ED}\x{77EE}\x{77EF}\x{77F0}\x{77F1}\x{77F2}\x{77F3}\x{77F6}'
. '\x{77F7}\x{77F8}\x{77F9}\x{77FA}\x{77FB}\x{77FC}\x{77FD}\x{77FE}\x{77FF}'
. '\x{7800}\x{7801}\x{7802}\x{7803}\x{7804}\x{7805}\x{7806}\x{7808}\x{7809}'
. '\x{780A}\x{780B}\x{780C}\x{780D}\x{780E}\x{780F}\x{7810}\x{7811}\x{7812}'
. '\x{7813}\x{7814}\x{7815}\x{7816}\x{7817}\x{7818}\x{7819}\x{781A}\x{781B}'
. '\x{781C}\x{781D}\x{781E}\x{781F}\x{7820}\x{7821}\x{7822}\x{7823}\x{7825}'
. '\x{7826}\x{7827}\x{7828}\x{7829}\x{782A}\x{782B}\x{782C}\x{782D}\x{782E}'
. '\x{782F}\x{7830}\x{7831}\x{7832}\x{7833}\x{7834}\x{7835}\x{7837}\x{7838}'
. '\x{7839}\x{783A}\x{783B}\x{783C}\x{783D}\x{783E}\x{7840}\x{7841}\x{7843}'
. '\x{7844}\x{7845}\x{7847}\x{7848}\x{7849}\x{784A}\x{784C}\x{784D}\x{784E}'
. '\x{7850}\x{7851}\x{7852}\x{7853}\x{7854}\x{7855}\x{7856}\x{7857}\x{7858}'
. '\x{7859}\x{785A}\x{785B}\x{785C}\x{785D}\x{785E}\x{785F}\x{7860}\x{7861}'
. '\x{7862}\x{7863}\x{7864}\x{7865}\x{7866}\x{7867}\x{7868}\x{7869}\x{786A}'
. '\x{786B}\x{786C}\x{786D}\x{786E}\x{786F}\x{7870}\x{7871}\x{7872}\x{7873}'
. '\x{7874}\x{7875}\x{7877}\x{7878}\x{7879}\x{787A}\x{787B}\x{787C}\x{787D}'
. '\x{787E}\x{787F}\x{7880}\x{7881}\x{7882}\x{7883}\x{7884}\x{7885}\x{7886}'
. '\x{7887}\x{7889}\x{788A}\x{788B}\x{788C}\x{788D}\x{788E}\x{788F}\x{7890}'
. '\x{7891}\x{7892}\x{7893}\x{7894}\x{7895}\x{7896}\x{7897}\x{7898}\x{7899}'
. '\x{789A}\x{789B}\x{789C}\x{789D}\x{789E}\x{789F}\x{78A0}\x{78A1}\x{78A2}'
. '\x{78A3}\x{78A4}\x{78A5}\x{78A6}\x{78A7}\x{78A8}\x{78A9}\x{78AA}\x{78AB}'
. '\x{78AC}\x{78AD}\x{78AE}\x{78AF}\x{78B0}\x{78B1}\x{78B2}\x{78B3}\x{78B4}'
. '\x{78B5}\x{78B6}\x{78B7}\x{78B8}\x{78B9}\x{78BA}\x{78BB}\x{78BC}\x{78BD}'
. '\x{78BE}\x{78BF}\x{78C0}\x{78C1}\x{78C3}\x{78C4}\x{78C5}\x{78C6}\x{78C8}'
. '\x{78C9}\x{78CA}\x{78CB}\x{78CC}\x{78CD}\x{78CE}\x{78CF}\x{78D0}\x{78D1}'
. '\x{78D3}\x{78D4}\x{78D5}\x{78D6}\x{78D7}\x{78D8}\x{78D9}\x{78DA}\x{78DB}'
. '\x{78DC}\x{78DD}\x{78DE}\x{78DF}\x{78E0}\x{78E1}\x{78E2}\x{78E3}\x{78E4}'
. '\x{78E5}\x{78E6}\x{78E7}\x{78E8}\x{78E9}\x{78EA}\x{78EB}\x{78EC}\x{78ED}'
. '\x{78EE}\x{78EF}\x{78F1}\x{78F2}\x{78F3}\x{78F4}\x{78F5}\x{78F6}\x{78F7}'
. '\x{78F9}\x{78FA}\x{78FB}\x{78FC}\x{78FD}\x{78FE}\x{78FF}\x{7901}\x{7902}'
. '\x{7903}\x{7904}\x{7905}\x{7906}\x{7907}\x{7909}\x{790A}\x{790B}\x{790C}'
. '\x{790E}\x{790F}\x{7910}\x{7911}\x{7912}\x{7913}\x{7914}\x{7916}\x{7917}'
. '\x{7918}\x{7919}\x{791A}\x{791B}\x{791C}\x{791D}\x{791E}\x{7921}\x{7922}'
. '\x{7923}\x{7924}\x{7925}\x{7926}\x{7927}\x{7928}\x{7929}\x{792A}\x{792B}'
. '\x{792C}\x{792D}\x{792E}\x{792F}\x{7930}\x{7931}\x{7933}\x{7934}\x{7935}'
. '\x{7937}\x{7938}\x{7939}\x{793A}\x{793B}\x{793C}\x{793D}\x{793E}\x{793F}'
. '\x{7940}\x{7941}\x{7942}\x{7943}\x{7944}\x{7945}\x{7946}\x{7947}\x{7948}'
. '\x{7949}\x{794A}\x{794B}\x{794C}\x{794D}\x{794E}\x{794F}\x{7950}\x{7951}'
. '\x{7952}\x{7953}\x{7954}\x{7955}\x{7956}\x{7957}\x{7958}\x{795A}\x{795B}'
. '\x{795C}\x{795D}\x{795E}\x{795F}\x{7960}\x{7961}\x{7962}\x{7963}\x{7964}'
. '\x{7965}\x{7966}\x{7967}\x{7968}\x{7969}\x{796A}\x{796B}\x{796D}\x{796F}'
. '\x{7970}\x{7971}\x{7972}\x{7973}\x{7974}\x{7977}\x{7978}\x{7979}\x{797A}'
. '\x{797B}\x{797C}\x{797D}\x{797E}\x{797F}\x{7980}\x{7981}\x{7982}\x{7983}'
. '\x{7984}\x{7985}\x{7988}\x{7989}\x{798A}\x{798B}\x{798C}\x{798D}\x{798E}'
. '\x{798F}\x{7990}\x{7991}\x{7992}\x{7993}\x{7994}\x{7995}\x{7996}\x{7997}'
. '\x{7998}\x{7999}\x{799A}\x{799B}\x{799C}\x{799F}\x{79A0}\x{79A1}\x{79A2}'
. '\x{79A3}\x{79A4}\x{79A5}\x{79A6}\x{79A7}\x{79A8}\x{79AA}\x{79AB}\x{79AC}'
. '\x{79AD}\x{79AE}\x{79AF}\x{79B0}\x{79B1}\x{79B2}\x{79B3}\x{79B4}\x{79B5}'
. '\x{79B6}\x{79B7}\x{79B8}\x{79B9}\x{79BA}\x{79BB}\x{79BD}\x{79BE}\x{79BF}'
. '\x{79C0}\x{79C1}\x{79C2}\x{79C3}\x{79C5}\x{79C6}\x{79C8}\x{79C9}\x{79CA}'
. '\x{79CB}\x{79CD}\x{79CE}\x{79CF}\x{79D0}\x{79D1}\x{79D2}\x{79D3}\x{79D5}'
. '\x{79D6}\x{79D8}\x{79D9}\x{79DA}\x{79DB}\x{79DC}\x{79DD}\x{79DE}\x{79DF}'
. '\x{79E0}\x{79E1}\x{79E2}\x{79E3}\x{79E4}\x{79E5}\x{79E6}\x{79E7}\x{79E8}'
. '\x{79E9}\x{79EA}\x{79EB}\x{79EC}\x{79ED}\x{79EE}\x{79EF}\x{79F0}\x{79F1}'
. '\x{79F2}\x{79F3}\x{79F4}\x{79F5}\x{79F6}\x{79F7}\x{79F8}\x{79F9}\x{79FA}'
. '\x{79FB}\x{79FC}\x{79FD}\x{79FE}\x{79FF}\x{7A00}\x{7A02}\x{7A03}\x{7A04}'
. '\x{7A05}\x{7A06}\x{7A08}\x{7A0A}\x{7A0B}\x{7A0C}\x{7A0D}\x{7A0E}\x{7A0F}'
. '\x{7A10}\x{7A11}\x{7A12}\x{7A13}\x{7A14}\x{7A15}\x{7A16}\x{7A17}\x{7A18}'
. '\x{7A19}\x{7A1A}\x{7A1B}\x{7A1C}\x{7A1D}\x{7A1E}\x{7A1F}\x{7A20}\x{7A21}'
. '\x{7A22}\x{7A23}\x{7A24}\x{7A25}\x{7A26}\x{7A27}\x{7A28}\x{7A29}\x{7A2A}'
. '\x{7A2B}\x{7A2D}\x{7A2E}\x{7A2F}\x{7A30}\x{7A31}\x{7A32}\x{7A33}\x{7A34}'
. '\x{7A35}\x{7A37}\x{7A39}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}'
. '\x{7A41}\x{7A42}\x{7A43}\x{7A44}\x{7A45}\x{7A46}\x{7A47}\x{7A48}\x{7A49}'
. '\x{7A4A}\x{7A4B}\x{7A4C}\x{7A4D}\x{7A4E}\x{7A50}\x{7A51}\x{7A52}\x{7A53}'
. '\x{7A54}\x{7A55}\x{7A56}\x{7A57}\x{7A58}\x{7A59}\x{7A5A}\x{7A5B}\x{7A5C}'
. '\x{7A5D}\x{7A5E}\x{7A5F}\x{7A60}\x{7A61}\x{7A62}\x{7A65}\x{7A66}\x{7A67}'
. '\x{7A68}\x{7A69}\x{7A6B}\x{7A6C}\x{7A6D}\x{7A6E}\x{7A70}\x{7A71}\x{7A72}'
. '\x{7A73}\x{7A74}\x{7A75}\x{7A76}\x{7A77}\x{7A78}\x{7A79}\x{7A7A}\x{7A7B}'
. '\x{7A7C}\x{7A7D}\x{7A7E}\x{7A7F}\x{7A80}\x{7A81}\x{7A83}\x{7A84}\x{7A85}'
. '\x{7A86}\x{7A87}\x{7A88}\x{7A89}\x{7A8A}\x{7A8B}\x{7A8C}\x{7A8D}\x{7A8E}'
. '\x{7A8F}\x{7A90}\x{7A91}\x{7A92}\x{7A93}\x{7A94}\x{7A95}\x{7A96}\x{7A97}'
. '\x{7A98}\x{7A99}\x{7A9C}\x{7A9D}\x{7A9E}\x{7A9F}\x{7AA0}\x{7AA1}\x{7AA2}'
. '\x{7AA3}\x{7AA4}\x{7AA5}\x{7AA6}\x{7AA7}\x{7AA8}\x{7AA9}\x{7AAA}\x{7AAB}'
. '\x{7AAC}\x{7AAD}\x{7AAE}\x{7AAF}\x{7AB0}\x{7AB1}\x{7AB2}\x{7AB3}\x{7AB4}'
. '\x{7AB5}\x{7AB6}\x{7AB7}\x{7AB8}\x{7ABA}\x{7ABE}\x{7ABF}\x{7AC0}\x{7AC1}'
. '\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}\x{7AC9}\x{7ACA}\x{7ACB}\x{7ACC}\x{7ACD}'
. '\x{7ACE}\x{7ACF}\x{7AD0}\x{7AD1}\x{7AD2}\x{7AD3}\x{7AD4}\x{7AD5}\x{7AD6}'
. '\x{7AD8}\x{7AD9}\x{7ADB}\x{7ADC}\x{7ADD}\x{7ADE}\x{7ADF}\x{7AE0}\x{7AE1}'
. '\x{7AE2}\x{7AE3}\x{7AE4}\x{7AE5}\x{7AE6}\x{7AE7}\x{7AE8}\x{7AEA}\x{7AEB}'
. '\x{7AEC}\x{7AED}\x{7AEE}\x{7AEF}\x{7AF0}\x{7AF1}\x{7AF2}\x{7AF3}\x{7AF4}'
. '\x{7AF6}\x{7AF7}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFB}\x{7AFD}\x{7AFE}\x{7AFF}'
. '\x{7B00}\x{7B01}\x{7B02}\x{7B03}\x{7B04}\x{7B05}\x{7B06}\x{7B08}\x{7B09}'
. '\x{7B0A}\x{7B0B}\x{7B0C}\x{7B0D}\x{7B0E}\x{7B0F}\x{7B10}\x{7B11}\x{7B12}'
. '\x{7B13}\x{7B14}\x{7B15}\x{7B16}\x{7B17}\x{7B18}\x{7B19}\x{7B1A}\x{7B1B}'
. '\x{7B1C}\x{7B1D}\x{7B1E}\x{7B20}\x{7B21}\x{7B22}\x{7B23}\x{7B24}\x{7B25}'
. '\x{7B26}\x{7B28}\x{7B2A}\x{7B2B}\x{7B2C}\x{7B2D}\x{7B2E}\x{7B2F}\x{7B30}'
. '\x{7B31}\x{7B32}\x{7B33}\x{7B34}\x{7B35}\x{7B36}\x{7B37}\x{7B38}\x{7B39}'
. '\x{7B3A}\x{7B3B}\x{7B3C}\x{7B3D}\x{7B3E}\x{7B3F}\x{7B40}\x{7B41}\x{7B43}'
. '\x{7B44}\x{7B45}\x{7B46}\x{7B47}\x{7B48}\x{7B49}\x{7B4A}\x{7B4B}\x{7B4C}'
. '\x{7B4D}\x{7B4E}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B55}\x{7B56}'
. '\x{7B57}\x{7B58}\x{7B59}\x{7B5A}\x{7B5B}\x{7B5C}\x{7B5D}\x{7B5E}\x{7B5F}'
. '\x{7B60}\x{7B61}\x{7B62}\x{7B63}\x{7B64}\x{7B65}\x{7B66}\x{7B67}\x{7B68}'
. '\x{7B69}\x{7B6A}\x{7B6B}\x{7B6C}\x{7B6D}\x{7B6E}\x{7B70}\x{7B71}\x{7B72}'
. '\x{7B73}\x{7B74}\x{7B75}\x{7B76}\x{7B77}\x{7B78}\x{7B79}\x{7B7B}\x{7B7C}'
. '\x{7B7D}\x{7B7E}\x{7B7F}\x{7B80}\x{7B81}\x{7B82}\x{7B83}\x{7B84}\x{7B85}'
. '\x{7B87}\x{7B88}\x{7B89}\x{7B8A}\x{7B8B}\x{7B8C}\x{7B8D}\x{7B8E}\x{7B8F}'
. '\x{7B90}\x{7B91}\x{7B93}\x{7B94}\x{7B95}\x{7B96}\x{7B97}\x{7B98}\x{7B99}'
. '\x{7B9A}\x{7B9B}\x{7B9C}\x{7B9D}\x{7B9E}\x{7B9F}\x{7BA0}\x{7BA1}\x{7BA2}'
. '\x{7BA4}\x{7BA6}\x{7BA7}\x{7BA8}\x{7BA9}\x{7BAA}\x{7BAB}\x{7BAC}\x{7BAD}'
. '\x{7BAE}\x{7BAF}\x{7BB1}\x{7BB3}\x{7BB4}\x{7BB5}\x{7BB6}\x{7BB7}\x{7BB8}'
. '\x{7BB9}\x{7BBA}\x{7BBB}\x{7BBC}\x{7BBD}\x{7BBE}\x{7BBF}\x{7BC0}\x{7BC1}'
. '\x{7BC2}\x{7BC3}\x{7BC4}\x{7BC5}\x{7BC6}\x{7BC7}\x{7BC8}\x{7BC9}\x{7BCA}'
. '\x{7BCB}\x{7BCC}\x{7BCD}\x{7BCE}\x{7BD0}\x{7BD1}\x{7BD2}\x{7BD3}\x{7BD4}'
. '\x{7BD5}\x{7BD6}\x{7BD7}\x{7BD8}\x{7BD9}\x{7BDA}\x{7BDB}\x{7BDC}\x{7BDD}'
. '\x{7BDE}\x{7BDF}\x{7BE0}\x{7BE1}\x{7BE2}\x{7BE3}\x{7BE4}\x{7BE5}\x{7BE6}'
. '\x{7BE7}\x{7BE8}\x{7BE9}\x{7BEA}\x{7BEB}\x{7BEC}\x{7BED}\x{7BEE}\x{7BEF}'
. '\x{7BF0}\x{7BF1}\x{7BF2}\x{7BF3}\x{7BF4}\x{7BF5}\x{7BF6}\x{7BF7}\x{7BF8}'
. '\x{7BF9}\x{7BFB}\x{7BFC}\x{7BFD}\x{7BFE}\x{7BFF}\x{7C00}\x{7C01}\x{7C02}'
. '\x{7C03}\x{7C04}\x{7C05}\x{7C06}\x{7C07}\x{7C08}\x{7C09}\x{7C0A}\x{7C0B}'
. '\x{7C0C}\x{7C0D}\x{7C0E}\x{7C0F}\x{7C10}\x{7C11}\x{7C12}\x{7C13}\x{7C15}'
. '\x{7C16}\x{7C17}\x{7C18}\x{7C19}\x{7C1A}\x{7C1C}\x{7C1D}\x{7C1E}\x{7C1F}'
. '\x{7C20}\x{7C21}\x{7C22}\x{7C23}\x{7C24}\x{7C25}\x{7C26}\x{7C27}\x{7C28}'
. '\x{7C29}\x{7C2A}\x{7C2B}\x{7C2C}\x{7C2D}\x{7C30}\x{7C31}\x{7C32}\x{7C33}'
. '\x{7C34}\x{7C35}\x{7C36}\x{7C37}\x{7C38}\x{7C39}\x{7C3A}\x{7C3B}\x{7C3C}'
. '\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C41}\x{7C42}\x{7C43}\x{7C44}\x{7C45}'
. '\x{7C46}\x{7C47}\x{7C48}\x{7C49}\x{7C4A}\x{7C4B}\x{7C4C}\x{7C4D}\x{7C4E}'
. '\x{7C50}\x{7C51}\x{7C53}\x{7C54}\x{7C56}\x{7C57}\x{7C58}\x{7C59}\x{7C5A}'
. '\x{7C5B}\x{7C5C}\x{7C5E}\x{7C5F}\x{7C60}\x{7C61}\x{7C62}\x{7C63}\x{7C64}'
. '\x{7C65}\x{7C66}\x{7C67}\x{7C68}\x{7C69}\x{7C6A}\x{7C6B}\x{7C6C}\x{7C6D}'
. '\x{7C6E}\x{7C6F}\x{7C70}\x{7C71}\x{7C72}\x{7C73}\x{7C74}\x{7C75}\x{7C77}'
. '\x{7C78}\x{7C79}\x{7C7A}\x{7C7B}\x{7C7C}\x{7C7D}\x{7C7E}\x{7C7F}\x{7C80}'
. '\x{7C81}\x{7C82}\x{7C84}\x{7C85}\x{7C86}\x{7C88}\x{7C89}\x{7C8A}\x{7C8B}'
. '\x{7C8C}\x{7C8D}\x{7C8E}\x{7C8F}\x{7C90}\x{7C91}\x{7C92}\x{7C94}\x{7C95}'
. '\x{7C96}\x{7C97}\x{7C98}\x{7C99}\x{7C9B}\x{7C9C}\x{7C9D}\x{7C9E}\x{7C9F}'
. '\x{7CA0}\x{7CA1}\x{7CA2}\x{7CA3}\x{7CA4}\x{7CA5}\x{7CA6}\x{7CA7}\x{7CA8}'
. '\x{7CA9}\x{7CAA}\x{7CAD}\x{7CAE}\x{7CAF}\x{7CB0}\x{7CB1}\x{7CB2}\x{7CB3}'
. '\x{7CB4}\x{7CB5}\x{7CB6}\x{7CB7}\x{7CB8}\x{7CB9}\x{7CBA}\x{7CBB}\x{7CBC}'
. '\x{7CBD}\x{7CBE}\x{7CBF}\x{7CC0}\x{7CC1}\x{7CC2}\x{7CC3}\x{7CC4}\x{7CC5}'
. '\x{7CC6}\x{7CC7}\x{7CC8}\x{7CC9}\x{7CCA}\x{7CCB}\x{7CCC}\x{7CCD}\x{7CCE}'
. '\x{7CCF}\x{7CD0}\x{7CD1}\x{7CD2}\x{7CD4}\x{7CD5}\x{7CD6}\x{7CD7}\x{7CD8}'
. '\x{7CD9}\x{7CDC}\x{7CDD}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE4}\x{7CE7}'
. '\x{7CE8}\x{7CE9}\x{7CEA}\x{7CEB}\x{7CEC}\x{7CED}\x{7CEE}\x{7CEF}\x{7CF0}'
. '\x{7CF1}\x{7CF2}\x{7CF3}\x{7CF4}\x{7CF5}\x{7CF6}\x{7CF7}\x{7CF8}\x{7CF9}'
. '\x{7CFA}\x{7CFB}\x{7CFD}\x{7CFE}\x{7D00}\x{7D01}\x{7D02}\x{7D03}\x{7D04}'
. '\x{7D05}\x{7D06}\x{7D07}\x{7D08}\x{7D09}\x{7D0A}\x{7D0B}\x{7D0C}\x{7D0D}'
. '\x{7D0E}\x{7D0F}\x{7D10}\x{7D11}\x{7D12}\x{7D13}\x{7D14}\x{7D15}\x{7D16}'
. '\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D1D}\x{7D1E}\x{7D1F}'
. '\x{7D20}\x{7D21}\x{7D22}\x{7D24}\x{7D25}\x{7D26}\x{7D27}\x{7D28}\x{7D29}'
. '\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D31}\x{7D32}\x{7D33}\x{7D34}'
. '\x{7D35}\x{7D36}\x{7D37}\x{7D38}\x{7D39}\x{7D3A}\x{7D3B}\x{7D3C}\x{7D3D}'
. '\x{7D3E}\x{7D3F}\x{7D40}\x{7D41}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}'
. '\x{7D47}\x{7D49}\x{7D4A}\x{7D4B}\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D51}'
. '\x{7D52}\x{7D53}\x{7D54}\x{7D55}\x{7D56}\x{7D57}\x{7D58}\x{7D59}\x{7D5B}'
. '\x{7D5C}\x{7D5D}\x{7D5E}\x{7D5F}\x{7D60}\x{7D61}\x{7D62}\x{7D63}\x{7D65}'
. '\x{7D66}\x{7D67}\x{7D68}\x{7D69}\x{7D6A}\x{7D6B}\x{7D6C}\x{7D6D}\x{7D6E}'
. '\x{7D6F}\x{7D70}\x{7D71}\x{7D72}\x{7D73}\x{7D74}\x{7D75}\x{7D76}\x{7D77}'
. '\x{7D79}\x{7D7A}\x{7D7B}\x{7D7C}\x{7D7D}\x{7D7E}\x{7D7F}\x{7D80}\x{7D81}'
. '\x{7D83}\x{7D84}\x{7D85}\x{7D86}\x{7D87}\x{7D88}\x{7D89}\x{7D8A}\x{7D8B}'
. '\x{7D8C}\x{7D8D}\x{7D8E}\x{7D8F}\x{7D90}\x{7D91}\x{7D92}\x{7D93}\x{7D94}'
. '\x{7D96}\x{7D97}\x{7D99}\x{7D9B}\x{7D9C}\x{7D9D}\x{7D9E}\x{7D9F}\x{7DA0}'
. '\x{7DA1}\x{7DA2}\x{7DA3}\x{7DA5}\x{7DA6}\x{7DA7}\x{7DA9}\x{7DAA}\x{7DAB}'
. '\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}\x{7DB1}\x{7DB2}\x{7DB3}\x{7DB4}'
. '\x{7DB5}\x{7DB6}\x{7DB7}\x{7DB8}\x{7DB9}\x{7DBA}\x{7DBB}\x{7DBC}\x{7DBD}'
. '\x{7DBE}\x{7DBF}\x{7DC0}\x{7DC1}\x{7DC2}\x{7DC3}\x{7DC4}\x{7DC5}\x{7DC6}'
. '\x{7DC7}\x{7DC8}\x{7DC9}\x{7DCA}\x{7DCB}\x{7DCC}\x{7DCE}\x{7DCF}\x{7DD0}'
. '\x{7DD1}\x{7DD2}\x{7DD4}\x{7DD5}\x{7DD6}\x{7DD7}\x{7DD8}\x{7DD9}\x{7DDA}'
. '\x{7DDB}\x{7DDD}\x{7DDE}\x{7DDF}\x{7DE0}\x{7DE1}\x{7DE2}\x{7DE3}\x{7DE6}'
. '\x{7DE7}\x{7DE8}\x{7DE9}\x{7DEA}\x{7DEC}\x{7DED}\x{7DEE}\x{7DEF}\x{7DF0}'
. '\x{7DF1}\x{7DF2}\x{7DF3}\x{7DF4}\x{7DF5}\x{7DF6}\x{7DF7}\x{7DF8}\x{7DF9}'
. '\x{7DFA}\x{7DFB}\x{7DFC}\x{7E00}\x{7E01}\x{7E02}\x{7E03}\x{7E04}\x{7E05}'
. '\x{7E06}\x{7E07}\x{7E08}\x{7E09}\x{7E0A}\x{7E0B}\x{7E0C}\x{7E0D}\x{7E0E}'
. '\x{7E0F}\x{7E10}\x{7E11}\x{7E12}\x{7E13}\x{7E14}\x{7E15}\x{7E16}\x{7E17}'
. '\x{7E19}\x{7E1A}\x{7E1B}\x{7E1C}\x{7E1D}\x{7E1E}\x{7E1F}\x{7E20}\x{7E21}'
. '\x{7E22}\x{7E23}\x{7E24}\x{7E25}\x{7E26}\x{7E27}\x{7E28}\x{7E29}\x{7E2A}'
. '\x{7E2B}\x{7E2C}\x{7E2D}\x{7E2E}\x{7E2F}\x{7E30}\x{7E31}\x{7E32}\x{7E33}'
. '\x{7E34}\x{7E35}\x{7E36}\x{7E37}\x{7E38}\x{7E39}\x{7E3A}\x{7E3B}\x{7E3C}'
. '\x{7E3D}\x{7E3E}\x{7E3F}\x{7E40}\x{7E41}\x{7E42}\x{7E43}\x{7E44}\x{7E45}'
. '\x{7E46}\x{7E47}\x{7E48}\x{7E49}\x{7E4C}\x{7E4D}\x{7E4E}\x{7E4F}\x{7E50}'
. '\x{7E51}\x{7E52}\x{7E53}\x{7E54}\x{7E55}\x{7E56}\x{7E57}\x{7E58}\x{7E59}'
. '\x{7E5A}\x{7E5C}\x{7E5D}\x{7E5E}\x{7E5F}\x{7E60}\x{7E61}\x{7E62}\x{7E63}'
. '\x{7E65}\x{7E66}\x{7E67}\x{7E68}\x{7E69}\x{7E6A}\x{7E6B}\x{7E6C}\x{7E6D}'
. '\x{7E6E}\x{7E6F}\x{7E70}\x{7E71}\x{7E72}\x{7E73}\x{7E74}\x{7E75}\x{7E76}'
. '\x{7E77}\x{7E78}\x{7E79}\x{7E7A}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7E}\x{7E7F}'
. '\x{7E80}\x{7E81}\x{7E82}\x{7E83}\x{7E84}\x{7E85}\x{7E86}\x{7E87}\x{7E88}'
. '\x{7E89}\x{7E8A}\x{7E8B}\x{7E8C}\x{7E8D}\x{7E8E}\x{7E8F}\x{7E90}\x{7E91}'
. '\x{7E92}\x{7E93}\x{7E94}\x{7E95}\x{7E96}\x{7E97}\x{7E98}\x{7E99}\x{7E9A}'
. '\x{7E9B}\x{7E9C}\x{7E9E}\x{7E9F}\x{7EA0}\x{7EA1}\x{7EA2}\x{7EA3}\x{7EA4}'
. '\x{7EA5}\x{7EA6}\x{7EA7}\x{7EA8}\x{7EA9}\x{7EAA}\x{7EAB}\x{7EAC}\x{7EAD}'
. '\x{7EAE}\x{7EAF}\x{7EB0}\x{7EB1}\x{7EB2}\x{7EB3}\x{7EB4}\x{7EB5}\x{7EB6}'
. '\x{7EB7}\x{7EB8}\x{7EB9}\x{7EBA}\x{7EBB}\x{7EBC}\x{7EBD}\x{7EBE}\x{7EBF}'
. '\x{7EC0}\x{7EC1}\x{7EC2}\x{7EC3}\x{7EC4}\x{7EC5}\x{7EC6}\x{7EC7}\x{7EC8}'
. '\x{7EC9}\x{7ECA}\x{7ECB}\x{7ECC}\x{7ECD}\x{7ECE}\x{7ECF}\x{7ED0}\x{7ED1}'
. '\x{7ED2}\x{7ED3}\x{7ED4}\x{7ED5}\x{7ED6}\x{7ED7}\x{7ED8}\x{7ED9}\x{7EDA}'
. '\x{7EDB}\x{7EDC}\x{7EDD}\x{7EDE}\x{7EDF}\x{7EE0}\x{7EE1}\x{7EE2}\x{7EE3}'
. '\x{7EE4}\x{7EE5}\x{7EE6}\x{7EE7}\x{7EE8}\x{7EE9}\x{7EEA}\x{7EEB}\x{7EEC}'
. '\x{7EED}\x{7EEE}\x{7EEF}\x{7EF0}\x{7EF1}\x{7EF2}\x{7EF3}\x{7EF4}\x{7EF5}'
. '\x{7EF6}\x{7EF7}\x{7EF8}\x{7EF9}\x{7EFA}\x{7EFB}\x{7EFC}\x{7EFD}\x{7EFE}'
. '\x{7EFF}\x{7F00}\x{7F01}\x{7F02}\x{7F03}\x{7F04}\x{7F05}\x{7F06}\x{7F07}'
. '\x{7F08}\x{7F09}\x{7F0A}\x{7F0B}\x{7F0C}\x{7F0D}\x{7F0E}\x{7F0F}\x{7F10}'
. '\x{7F11}\x{7F12}\x{7F13}\x{7F14}\x{7F15}\x{7F16}\x{7F17}\x{7F18}\x{7F19}'
. '\x{7F1A}\x{7F1B}\x{7F1C}\x{7F1D}\x{7F1E}\x{7F1F}\x{7F20}\x{7F21}\x{7F22}'
. '\x{7F23}\x{7F24}\x{7F25}\x{7F26}\x{7F27}\x{7F28}\x{7F29}\x{7F2A}\x{7F2B}'
. '\x{7F2C}\x{7F2D}\x{7F2E}\x{7F2F}\x{7F30}\x{7F31}\x{7F32}\x{7F33}\x{7F34}'
. '\x{7F35}\x{7F36}\x{7F37}\x{7F38}\x{7F39}\x{7F3A}\x{7F3D}\x{7F3E}\x{7F3F}'
. '\x{7F40}\x{7F42}\x{7F43}\x{7F44}\x{7F45}\x{7F47}\x{7F48}\x{7F49}\x{7F4A}'
. '\x{7F4B}\x{7F4C}\x{7F4D}\x{7F4E}\x{7F4F}\x{7F50}\x{7F51}\x{7F52}\x{7F53}'
. '\x{7F54}\x{7F55}\x{7F56}\x{7F57}\x{7F58}\x{7F5A}\x{7F5B}\x{7F5C}\x{7F5D}'
. '\x{7F5E}\x{7F5F}\x{7F60}\x{7F61}\x{7F62}\x{7F63}\x{7F64}\x{7F65}\x{7F66}'
. '\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6C}\x{7F6D}\x{7F6E}\x{7F6F}'
. '\x{7F70}\x{7F71}\x{7F72}\x{7F73}\x{7F74}\x{7F75}\x{7F76}\x{7F77}\x{7F78}'
. '\x{7F79}\x{7F7A}\x{7F7B}\x{7F7C}\x{7F7D}\x{7F7E}\x{7F7F}\x{7F80}\x{7F81}'
. '\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}\x{7F88}\x{7F89}\x{7F8A}\x{7F8B}'
. '\x{7F8C}\x{7F8D}\x{7F8E}\x{7F8F}\x{7F91}\x{7F92}\x{7F93}\x{7F94}\x{7F95}'
. '\x{7F96}\x{7F98}\x{7F9A}\x{7F9B}\x{7F9C}\x{7F9D}\x{7F9E}\x{7F9F}\x{7FA0}'
. '\x{7FA1}\x{7FA2}\x{7FA3}\x{7FA4}\x{7FA5}\x{7FA6}\x{7FA7}\x{7FA8}\x{7FA9}'
. '\x{7FAA}\x{7FAB}\x{7FAC}\x{7FAD}\x{7FAE}\x{7FAF}\x{7FB0}\x{7FB1}\x{7FB2}'
. '\x{7FB3}\x{7FB5}\x{7FB6}\x{7FB7}\x{7FB8}\x{7FB9}\x{7FBA}\x{7FBB}\x{7FBC}'
. '\x{7FBD}\x{7FBE}\x{7FBF}\x{7FC0}\x{7FC1}\x{7FC2}\x{7FC3}\x{7FC4}\x{7FC5}'
. '\x{7FC6}\x{7FC7}\x{7FC8}\x{7FC9}\x{7FCA}\x{7FCB}\x{7FCC}\x{7FCD}\x{7FCE}'
. '\x{7FCF}\x{7FD0}\x{7FD1}\x{7FD2}\x{7FD3}\x{7FD4}\x{7FD5}\x{7FD7}\x{7FD8}'
. '\x{7FD9}\x{7FDA}\x{7FDB}\x{7FDC}\x{7FDE}\x{7FDF}\x{7FE0}\x{7FE1}\x{7FE2}'
. '\x{7FE3}\x{7FE5}\x{7FE6}\x{7FE7}\x{7FE8}\x{7FE9}\x{7FEA}\x{7FEB}\x{7FEC}'
. '\x{7FED}\x{7FEE}\x{7FEF}\x{7FF0}\x{7FF1}\x{7FF2}\x{7FF3}\x{7FF4}\x{7FF5}'
. '\x{7FF6}\x{7FF7}\x{7FF8}\x{7FF9}\x{7FFA}\x{7FFB}\x{7FFC}\x{7FFD}\x{7FFE}'
. '\x{7FFF}\x{8000}\x{8001}\x{8002}\x{8003}\x{8004}\x{8005}\x{8006}\x{8007}'
. '\x{8008}\x{8009}\x{800B}\x{800C}\x{800D}\x{800E}\x{800F}\x{8010}\x{8011}'
. '\x{8012}\x{8013}\x{8014}\x{8015}\x{8016}\x{8017}\x{8018}\x{8019}\x{801A}'
. '\x{801B}\x{801C}\x{801D}\x{801E}\x{801F}\x{8020}\x{8021}\x{8022}\x{8023}'
. '\x{8024}\x{8025}\x{8026}\x{8027}\x{8028}\x{8029}\x{802A}\x{802B}\x{802C}'
. '\x{802D}\x{802E}\x{8030}\x{8031}\x{8032}\x{8033}\x{8034}\x{8035}\x{8036}'
. '\x{8037}\x{8038}\x{8039}\x{803A}\x{803B}\x{803D}\x{803E}\x{803F}\x{8041}'
. '\x{8042}\x{8043}\x{8044}\x{8045}\x{8046}\x{8047}\x{8048}\x{8049}\x{804A}'
. '\x{804B}\x{804C}\x{804D}\x{804E}\x{804F}\x{8050}\x{8051}\x{8052}\x{8053}'
. '\x{8054}\x{8055}\x{8056}\x{8057}\x{8058}\x{8059}\x{805A}\x{805B}\x{805C}'
. '\x{805D}\x{805E}\x{805F}\x{8060}\x{8061}\x{8062}\x{8063}\x{8064}\x{8065}'
. '\x{8067}\x{8068}\x{8069}\x{806A}\x{806B}\x{806C}\x{806D}\x{806E}\x{806F}'
. '\x{8070}\x{8071}\x{8072}\x{8073}\x{8074}\x{8075}\x{8076}\x{8077}\x{8078}'
. '\x{8079}\x{807A}\x{807B}\x{807C}\x{807D}\x{807E}\x{807F}\x{8080}\x{8081}'
. '\x{8082}\x{8083}\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808A}\x{808B}'
. '\x{808C}\x{808D}\x{808F}\x{8090}\x{8091}\x{8092}\x{8093}\x{8095}\x{8096}'
. '\x{8097}\x{8098}\x{8099}\x{809A}\x{809B}\x{809C}\x{809D}\x{809E}\x{809F}'
. '\x{80A0}\x{80A1}\x{80A2}\x{80A3}\x{80A4}\x{80A5}\x{80A9}\x{80AA}\x{80AB}'
. '\x{80AD}\x{80AE}\x{80AF}\x{80B0}\x{80B1}\x{80B2}\x{80B4}\x{80B5}\x{80B6}'
. '\x{80B7}\x{80B8}\x{80BA}\x{80BB}\x{80BC}\x{80BD}\x{80BE}\x{80BF}\x{80C0}'
. '\x{80C1}\x{80C2}\x{80C3}\x{80C4}\x{80C5}\x{80C6}\x{80C7}\x{80C8}\x{80C9}'
. '\x{80CA}\x{80CB}\x{80CC}\x{80CD}\x{80CE}\x{80CF}\x{80D0}\x{80D1}\x{80D2}'
. '\x{80D3}\x{80D4}\x{80D5}\x{80D6}\x{80D7}\x{80D8}\x{80D9}\x{80DA}\x{80DB}'
. '\x{80DC}\x{80DD}\x{80DE}\x{80E0}\x{80E1}\x{80E2}\x{80E3}\x{80E4}\x{80E5}'
. '\x{80E6}\x{80E7}\x{80E8}\x{80E9}\x{80EA}\x{80EB}\x{80EC}\x{80ED}\x{80EE}'
. '\x{80EF}\x{80F0}\x{80F1}\x{80F2}\x{80F3}\x{80F4}\x{80F5}\x{80F6}\x{80F7}'
. '\x{80F8}\x{80F9}\x{80FA}\x{80FB}\x{80FC}\x{80FD}\x{80FE}\x{80FF}\x{8100}'
. '\x{8101}\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{810B}'
. '\x{810C}\x{810D}\x{810E}\x{810F}\x{8110}\x{8111}\x{8112}\x{8113}\x{8114}'
. '\x{8115}\x{8116}\x{8118}\x{8119}\x{811A}\x{811B}\x{811C}\x{811D}\x{811E}'
. '\x{811F}\x{8120}\x{8121}\x{8122}\x{8123}\x{8124}\x{8125}\x{8126}\x{8127}'
. '\x{8128}\x{8129}\x{812A}\x{812B}\x{812C}\x{812D}\x{812E}\x{812F}\x{8130}'
. '\x{8131}\x{8132}\x{8136}\x{8137}\x{8138}\x{8139}\x{813A}\x{813B}\x{813C}'
. '\x{813D}\x{813E}\x{813F}\x{8140}\x{8141}\x{8142}\x{8143}\x{8144}\x{8145}'
. '\x{8146}\x{8147}\x{8148}\x{8149}\x{814A}\x{814B}\x{814C}\x{814D}\x{814E}'
. '\x{814F}\x{8150}\x{8151}\x{8152}\x{8153}\x{8154}\x{8155}\x{8156}\x{8157}'
. '\x{8158}\x{8159}\x{815A}\x{815B}\x{815C}\x{815D}\x{815E}\x{8160}\x{8161}'
. '\x{8162}\x{8163}\x{8164}\x{8165}\x{8166}\x{8167}\x{8168}\x{8169}\x{816A}'
. '\x{816B}\x{816C}\x{816D}\x{816E}\x{816F}\x{8170}\x{8171}\x{8172}\x{8173}'
. '\x{8174}\x{8175}\x{8176}\x{8177}\x{8178}\x{8179}\x{817A}\x{817B}\x{817C}'
. '\x{817D}\x{817E}\x{817F}\x{8180}\x{8181}\x{8182}\x{8183}\x{8185}\x{8186}'
. '\x{8187}\x{8188}\x{8189}\x{818A}\x{818B}\x{818C}\x{818D}\x{818E}\x{818F}'
. '\x{8191}\x{8192}\x{8193}\x{8194}\x{8195}\x{8197}\x{8198}\x{8199}\x{819A}'
. '\x{819B}\x{819C}\x{819D}\x{819E}\x{819F}\x{81A0}\x{81A1}\x{81A2}\x{81A3}'
. '\x{81A4}\x{81A5}\x{81A6}\x{81A7}\x{81A8}\x{81A9}\x{81AA}\x{81AB}\x{81AC}'
. '\x{81AD}\x{81AE}\x{81AF}\x{81B0}\x{81B1}\x{81B2}\x{81B3}\x{81B4}\x{81B5}'
. '\x{81B6}\x{81B7}\x{81B8}\x{81B9}\x{81BA}\x{81BB}\x{81BC}\x{81BD}\x{81BE}'
. '\x{81BF}\x{81C0}\x{81C1}\x{81C2}\x{81C3}\x{81C4}\x{81C5}\x{81C6}\x{81C7}'
. '\x{81C8}\x{81C9}\x{81CA}\x{81CC}\x{81CD}\x{81CE}\x{81CF}\x{81D0}\x{81D1}'
. '\x{81D2}\x{81D4}\x{81D5}\x{81D6}\x{81D7}\x{81D8}\x{81D9}\x{81DA}\x{81DB}'
. '\x{81DC}\x{81DD}\x{81DE}\x{81DF}\x{81E0}\x{81E1}\x{81E2}\x{81E3}\x{81E5}'
. '\x{81E6}\x{81E7}\x{81E8}\x{81E9}\x{81EA}\x{81EB}\x{81EC}\x{81ED}\x{81EE}'
. '\x{81F1}\x{81F2}\x{81F3}\x{81F4}\x{81F5}\x{81F6}\x{81F7}\x{81F8}\x{81F9}'
. '\x{81FA}\x{81FB}\x{81FC}\x{81FD}\x{81FE}\x{81FF}\x{8200}\x{8201}\x{8202}'
. '\x{8203}\x{8204}\x{8205}\x{8206}\x{8207}\x{8208}\x{8209}\x{820A}\x{820B}'
. '\x{820C}\x{820D}\x{820E}\x{820F}\x{8210}\x{8211}\x{8212}\x{8214}\x{8215}'
. '\x{8216}\x{8218}\x{8219}\x{821A}\x{821B}\x{821C}\x{821D}\x{821E}\x{821F}'
. '\x{8220}\x{8221}\x{8222}\x{8223}\x{8225}\x{8226}\x{8227}\x{8228}\x{8229}'
. '\x{822A}\x{822B}\x{822C}\x{822D}\x{822F}\x{8230}\x{8231}\x{8232}\x{8233}'
. '\x{8234}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{823A}\x{823B}\x{823C}'
. '\x{823D}\x{823E}\x{823F}\x{8240}\x{8242}\x{8243}\x{8244}\x{8245}\x{8246}'
. '\x{8247}\x{8248}\x{8249}\x{824A}\x{824B}\x{824C}\x{824D}\x{824E}\x{824F}'
. '\x{8250}\x{8251}\x{8252}\x{8253}\x{8254}\x{8255}\x{8256}\x{8257}\x{8258}'
. '\x{8259}\x{825A}\x{825B}\x{825C}\x{825D}\x{825E}\x{825F}\x{8260}\x{8261}'
. '\x{8263}\x{8264}\x{8266}\x{8267}\x{8268}\x{8269}\x{826A}\x{826B}\x{826C}'
. '\x{826D}\x{826E}\x{826F}\x{8270}\x{8271}\x{8272}\x{8273}\x{8274}\x{8275}'
. '\x{8276}\x{8277}\x{8278}\x{8279}\x{827A}\x{827B}\x{827C}\x{827D}\x{827E}'
. '\x{827F}\x{8280}\x{8281}\x{8282}\x{8283}\x{8284}\x{8285}\x{8286}\x{8287}'
. '\x{8288}\x{8289}\x{828A}\x{828B}\x{828D}\x{828E}\x{828F}\x{8290}\x{8291}'
. '\x{8292}\x{8293}\x{8294}\x{8295}\x{8296}\x{8297}\x{8298}\x{8299}\x{829A}'
. '\x{829B}\x{829C}\x{829D}\x{829E}\x{829F}\x{82A0}\x{82A1}\x{82A2}\x{82A3}'
. '\x{82A4}\x{82A5}\x{82A6}\x{82A7}\x{82A8}\x{82A9}\x{82AA}\x{82AB}\x{82AC}'
. '\x{82AD}\x{82AE}\x{82AF}\x{82B0}\x{82B1}\x{82B3}\x{82B4}\x{82B5}\x{82B6}'
. '\x{82B7}\x{82B8}\x{82B9}\x{82BA}\x{82BB}\x{82BC}\x{82BD}\x{82BE}\x{82BF}'
. '\x{82C0}\x{82C1}\x{82C2}\x{82C3}\x{82C4}\x{82C5}\x{82C6}\x{82C7}\x{82C8}'
. '\x{82C9}\x{82CA}\x{82CB}\x{82CC}\x{82CD}\x{82CE}\x{82CF}\x{82D0}\x{82D1}'
. '\x{82D2}\x{82D3}\x{82D4}\x{82D5}\x{82D6}\x{82D7}\x{82D8}\x{82D9}\x{82DA}'
. '\x{82DB}\x{82DC}\x{82DD}\x{82DE}\x{82DF}\x{82E0}\x{82E1}\x{82E3}\x{82E4}'
. '\x{82E5}\x{82E6}\x{82E7}\x{82E8}\x{82E9}\x{82EA}\x{82EB}\x{82EC}\x{82ED}'
. '\x{82EE}\x{82EF}\x{82F0}\x{82F1}\x{82F2}\x{82F3}\x{82F4}\x{82F5}\x{82F6}'
. '\x{82F7}\x{82F8}\x{82F9}\x{82FA}\x{82FB}\x{82FD}\x{82FE}\x{82FF}\x{8300}'
. '\x{8301}\x{8302}\x{8303}\x{8304}\x{8305}\x{8306}\x{8307}\x{8308}\x{8309}'
. '\x{830B}\x{830C}\x{830D}\x{830E}\x{830F}\x{8311}\x{8312}\x{8313}\x{8314}'
. '\x{8315}\x{8316}\x{8317}\x{8318}\x{8319}\x{831A}\x{831B}\x{831C}\x{831D}'
. '\x{831E}\x{831F}\x{8320}\x{8321}\x{8322}\x{8323}\x{8324}\x{8325}\x{8326}'
. '\x{8327}\x{8328}\x{8329}\x{832A}\x{832B}\x{832C}\x{832D}\x{832E}\x{832F}'
. '\x{8331}\x{8332}\x{8333}\x{8334}\x{8335}\x{8336}\x{8337}\x{8338}\x{8339}'
. '\x{833A}\x{833B}\x{833C}\x{833D}\x{833E}\x{833F}\x{8340}\x{8341}\x{8342}'
. '\x{8343}\x{8344}\x{8345}\x{8346}\x{8347}\x{8348}\x{8349}\x{834A}\x{834B}'
. '\x{834C}\x{834D}\x{834E}\x{834F}\x{8350}\x{8351}\x{8352}\x{8353}\x{8354}'
. '\x{8356}\x{8357}\x{8358}\x{8359}\x{835A}\x{835B}\x{835C}\x{835D}\x{835E}'
. '\x{835F}\x{8360}\x{8361}\x{8362}\x{8363}\x{8364}\x{8365}\x{8366}\x{8367}'
. '\x{8368}\x{8369}\x{836A}\x{836B}\x{836C}\x{836D}\x{836E}\x{836F}\x{8370}'
. '\x{8371}\x{8372}\x{8373}\x{8374}\x{8375}\x{8376}\x{8377}\x{8378}\x{8379}'
. '\x{837A}\x{837B}\x{837C}\x{837D}\x{837E}\x{837F}\x{8380}\x{8381}\x{8382}'
. '\x{8383}\x{8384}\x{8385}\x{8386}\x{8387}\x{8388}\x{8389}\x{838A}\x{838B}'
. '\x{838C}\x{838D}\x{838E}\x{838F}\x{8390}\x{8391}\x{8392}\x{8393}\x{8394}'
. '\x{8395}\x{8396}\x{8397}\x{8398}\x{8399}\x{839A}\x{839B}\x{839C}\x{839D}'
. '\x{839E}\x{83A0}\x{83A1}\x{83A2}\x{83A3}\x{83A4}\x{83A5}\x{83A6}\x{83A7}'
. '\x{83A8}\x{83A9}\x{83AA}\x{83AB}\x{83AC}\x{83AD}\x{83AE}\x{83AF}\x{83B0}'
. '\x{83B1}\x{83B2}\x{83B3}\x{83B4}\x{83B6}\x{83B7}\x{83B8}\x{83B9}\x{83BA}'
. '\x{83BB}\x{83BC}\x{83BD}\x{83BF}\x{83C0}\x{83C1}\x{83C2}\x{83C3}\x{83C4}'
. '\x{83C5}\x{83C6}\x{83C7}\x{83C8}\x{83C9}\x{83CA}\x{83CB}\x{83CC}\x{83CD}'
. '\x{83CE}\x{83CF}\x{83D0}\x{83D1}\x{83D2}\x{83D3}\x{83D4}\x{83D5}\x{83D6}'
. '\x{83D7}\x{83D8}\x{83D9}\x{83DA}\x{83DB}\x{83DC}\x{83DD}\x{83DE}\x{83DF}'
. '\x{83E0}\x{83E1}\x{83E2}\x{83E3}\x{83E4}\x{83E5}\x{83E7}\x{83E8}\x{83E9}'
. '\x{83EA}\x{83EB}\x{83EC}\x{83EE}\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F3}'
. '\x{83F4}\x{83F5}\x{83F6}\x{83F7}\x{83F8}\x{83F9}\x{83FA}\x{83FB}\x{83FC}'
. '\x{83FD}\x{83FE}\x{83FF}\x{8400}\x{8401}\x{8402}\x{8403}\x{8404}\x{8405}'
. '\x{8406}\x{8407}\x{8408}\x{8409}\x{840A}\x{840B}\x{840C}\x{840D}\x{840E}'
. '\x{840F}\x{8410}\x{8411}\x{8412}\x{8413}\x{8415}\x{8418}\x{8419}\x{841A}'
. '\x{841B}\x{841C}\x{841D}\x{841E}\x{8421}\x{8422}\x{8423}\x{8424}\x{8425}'
. '\x{8426}\x{8427}\x{8428}\x{8429}\x{842A}\x{842B}\x{842C}\x{842D}\x{842E}'
. '\x{842F}\x{8430}\x{8431}\x{8432}\x{8433}\x{8434}\x{8435}\x{8436}\x{8437}'
. '\x{8438}\x{8439}\x{843A}\x{843B}\x{843C}\x{843D}\x{843E}\x{843F}\x{8440}'
. '\x{8441}\x{8442}\x{8443}\x{8444}\x{8445}\x{8446}\x{8447}\x{8448}\x{8449}'
. '\x{844A}\x{844B}\x{844C}\x{844D}\x{844E}\x{844F}\x{8450}\x{8451}\x{8452}'
. '\x{8453}\x{8454}\x{8455}\x{8456}\x{8457}\x{8459}\x{845A}\x{845B}\x{845C}'
. '\x{845D}\x{845E}\x{845F}\x{8460}\x{8461}\x{8462}\x{8463}\x{8464}\x{8465}'
. '\x{8466}\x{8467}\x{8468}\x{8469}\x{846A}\x{846B}\x{846C}\x{846D}\x{846E}'
. '\x{846F}\x{8470}\x{8471}\x{8472}\x{8473}\x{8474}\x{8475}\x{8476}\x{8477}'
. '\x{8478}\x{8479}\x{847A}\x{847B}\x{847C}\x{847D}\x{847E}\x{847F}\x{8480}'
. '\x{8481}\x{8482}\x{8484}\x{8485}\x{8486}\x{8487}\x{8488}\x{8489}\x{848A}'
. '\x{848B}\x{848C}\x{848D}\x{848E}\x{848F}\x{8490}\x{8491}\x{8492}\x{8493}'
. '\x{8494}\x{8496}\x{8497}\x{8498}\x{8499}\x{849A}\x{849B}\x{849C}\x{849D}'
. '\x{849E}\x{849F}\x{84A0}\x{84A1}\x{84A2}\x{84A3}\x{84A4}\x{84A5}\x{84A6}'
. '\x{84A7}\x{84A8}\x{84A9}\x{84AA}\x{84AB}\x{84AC}\x{84AE}\x{84AF}\x{84B0}'
. '\x{84B1}\x{84B2}\x{84B3}\x{84B4}\x{84B5}\x{84B6}\x{84B8}\x{84B9}\x{84BA}'
. '\x{84BB}\x{84BC}\x{84BD}\x{84BE}\x{84BF}\x{84C0}\x{84C1}\x{84C2}\x{84C4}'
. '\x{84C5}\x{84C6}\x{84C7}\x{84C8}\x{84C9}\x{84CA}\x{84CB}\x{84CC}\x{84CD}'
. '\x{84CE}\x{84CF}\x{84D0}\x{84D1}\x{84D2}\x{84D3}\x{84D4}\x{84D5}\x{84D6}'
. '\x{84D7}\x{84D8}\x{84D9}\x{84DB}\x{84DC}\x{84DD}\x{84DE}\x{84DF}\x{84E0}'
. '\x{84E1}\x{84E2}\x{84E3}\x{84E4}\x{84E5}\x{84E6}\x{84E7}\x{84E8}\x{84E9}'
. '\x{84EA}\x{84EB}\x{84EC}\x{84EE}\x{84EF}\x{84F0}\x{84F1}\x{84F2}\x{84F3}'
. '\x{84F4}\x{84F5}\x{84F6}\x{84F7}\x{84F8}\x{84F9}\x{84FA}\x{84FB}\x{84FC}'
. '\x{84FD}\x{84FE}\x{84FF}\x{8500}\x{8501}\x{8502}\x{8503}\x{8504}\x{8506}'
. '\x{8507}\x{8508}\x{8509}\x{850A}\x{850B}\x{850C}\x{850D}\x{850E}\x{850F}'
. '\x{8511}\x{8512}\x{8513}\x{8514}\x{8515}\x{8516}\x{8517}\x{8518}\x{8519}'
. '\x{851A}\x{851B}\x{851C}\x{851D}\x{851E}\x{851F}\x{8520}\x{8521}\x{8522}'
. '\x{8523}\x{8524}\x{8525}\x{8526}\x{8527}\x{8528}\x{8529}\x{852A}\x{852B}'
. '\x{852C}\x{852D}\x{852E}\x{852F}\x{8530}\x{8531}\x{8534}\x{8535}\x{8536}'
. '\x{8537}\x{8538}\x{8539}\x{853A}\x{853B}\x{853C}\x{853D}\x{853E}\x{853F}'
. '\x{8540}\x{8541}\x{8542}\x{8543}\x{8544}\x{8545}\x{8546}\x{8547}\x{8548}'
. '\x{8549}\x{854A}\x{854B}\x{854D}\x{854E}\x{854F}\x{8551}\x{8552}\x{8553}'
. '\x{8554}\x{8555}\x{8556}\x{8557}\x{8558}\x{8559}\x{855A}\x{855B}\x{855C}'
. '\x{855D}\x{855E}\x{855F}\x{8560}\x{8561}\x{8562}\x{8563}\x{8564}\x{8565}'
. '\x{8566}\x{8567}\x{8568}\x{8569}\x{856A}\x{856B}\x{856C}\x{856D}\x{856E}'
. '\x{856F}\x{8570}\x{8571}\x{8572}\x{8573}\x{8574}\x{8575}\x{8576}\x{8577}'
. '\x{8578}\x{8579}\x{857A}\x{857B}\x{857C}\x{857D}\x{857E}\x{8580}\x{8581}'
. '\x{8582}\x{8583}\x{8584}\x{8585}\x{8586}\x{8587}\x{8588}\x{8589}\x{858A}'
. '\x{858B}\x{858C}\x{858D}\x{858E}\x{858F}\x{8590}\x{8591}\x{8592}\x{8594}'
. '\x{8595}\x{8596}\x{8598}\x{8599}\x{859A}\x{859B}\x{859C}\x{859D}\x{859E}'
. '\x{859F}\x{85A0}\x{85A1}\x{85A2}\x{85A3}\x{85A4}\x{85A5}\x{85A6}\x{85A7}'
. '\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AD}\x{85AE}\x{85AF}\x{85B0}'
. '\x{85B1}\x{85B3}\x{85B4}\x{85B5}\x{85B6}\x{85B7}\x{85B8}\x{85B9}\x{85BA}'
. '\x{85BC}\x{85BD}\x{85BE}\x{85BF}\x{85C0}\x{85C1}\x{85C2}\x{85C3}\x{85C4}'
. '\x{85C5}\x{85C6}\x{85C7}\x{85C8}\x{85C9}\x{85CA}\x{85CB}\x{85CD}\x{85CE}'
. '\x{85CF}\x{85D0}\x{85D1}\x{85D2}\x{85D3}\x{85D4}\x{85D5}\x{85D6}\x{85D7}'
. '\x{85D8}\x{85D9}\x{85DA}\x{85DB}\x{85DC}\x{85DD}\x{85DE}\x{85DF}\x{85E0}'
. '\x{85E1}\x{85E2}\x{85E3}\x{85E4}\x{85E5}\x{85E6}\x{85E7}\x{85E8}\x{85E9}'
. '\x{85EA}\x{85EB}\x{85EC}\x{85ED}\x{85EF}\x{85F0}\x{85F1}\x{85F2}\x{85F4}'
. '\x{85F5}\x{85F6}\x{85F7}\x{85F8}\x{85F9}\x{85FA}\x{85FB}\x{85FD}\x{85FE}'
. '\x{85FF}\x{8600}\x{8601}\x{8602}\x{8604}\x{8605}\x{8606}\x{8607}\x{8608}'
. '\x{8609}\x{860A}\x{860B}\x{860C}\x{860F}\x{8611}\x{8612}\x{8613}\x{8614}'
. '\x{8616}\x{8617}\x{8618}\x{8619}\x{861A}\x{861B}\x{861C}\x{861E}\x{861F}'
. '\x{8620}\x{8621}\x{8622}\x{8623}\x{8624}\x{8625}\x{8626}\x{8627}\x{8628}'
. '\x{8629}\x{862A}\x{862B}\x{862C}\x{862D}\x{862E}\x{862F}\x{8630}\x{8631}'
. '\x{8632}\x{8633}\x{8634}\x{8635}\x{8636}\x{8638}\x{8639}\x{863A}\x{863B}'
. '\x{863C}\x{863D}\x{863E}\x{863F}\x{8640}\x{8641}\x{8642}\x{8643}\x{8644}'
. '\x{8645}\x{8646}\x{8647}\x{8648}\x{8649}\x{864A}\x{864B}\x{864C}\x{864D}'
. '\x{864E}\x{864F}\x{8650}\x{8651}\x{8652}\x{8653}\x{8654}\x{8655}\x{8656}'
. '\x{8658}\x{8659}\x{865A}\x{865B}\x{865C}\x{865D}\x{865E}\x{865F}\x{8660}'
. '\x{8661}\x{8662}\x{8663}\x{8664}\x{8665}\x{8666}\x{8667}\x{8668}\x{8669}'
. '\x{866A}\x{866B}\x{866C}\x{866D}\x{866E}\x{866F}\x{8670}\x{8671}\x{8672}'
. '\x{8673}\x{8674}\x{8676}\x{8677}\x{8678}\x{8679}\x{867A}\x{867B}\x{867C}'
. '\x{867D}\x{867E}\x{867F}\x{8680}\x{8681}\x{8682}\x{8683}\x{8684}\x{8685}'
. '\x{8686}\x{8687}\x{8688}\x{868A}\x{868B}\x{868C}\x{868D}\x{868E}\x{868F}'
. '\x{8690}\x{8691}\x{8693}\x{8694}\x{8695}\x{8696}\x{8697}\x{8698}\x{8699}'
. '\x{869A}\x{869B}\x{869C}\x{869D}\x{869E}\x{869F}\x{86A1}\x{86A2}\x{86A3}'
. '\x{86A4}\x{86A5}\x{86A7}\x{86A8}\x{86A9}\x{86AA}\x{86AB}\x{86AC}\x{86AD}'
. '\x{86AE}\x{86AF}\x{86B0}\x{86B1}\x{86B2}\x{86B3}\x{86B4}\x{86B5}\x{86B6}'
. '\x{86B7}\x{86B8}\x{86B9}\x{86BA}\x{86BB}\x{86BC}\x{86BD}\x{86BE}\x{86BF}'
. '\x{86C0}\x{86C1}\x{86C2}\x{86C3}\x{86C4}\x{86C5}\x{86C6}\x{86C7}\x{86C8}'
. '\x{86C9}\x{86CA}\x{86CB}\x{86CC}\x{86CE}\x{86CF}\x{86D0}\x{86D1}\x{86D2}'
. '\x{86D3}\x{86D4}\x{86D6}\x{86D7}\x{86D8}\x{86D9}\x{86DA}\x{86DB}\x{86DC}'
. '\x{86DD}\x{86DE}\x{86DF}\x{86E1}\x{86E2}\x{86E3}\x{86E4}\x{86E5}\x{86E6}'
. '\x{86E8}\x{86E9}\x{86EA}\x{86EB}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F0}'
. '\x{86F1}\x{86F2}\x{86F3}\x{86F4}\x{86F5}\x{86F6}\x{86F7}\x{86F8}\x{86F9}'
. '\x{86FA}\x{86FB}\x{86FC}\x{86FE}\x{86FF}\x{8700}\x{8701}\x{8702}\x{8703}'
. '\x{8704}\x{8705}\x{8706}\x{8707}\x{8708}\x{8709}\x{870A}\x{870B}\x{870C}'
. '\x{870D}\x{870E}\x{870F}\x{8710}\x{8711}\x{8712}\x{8713}\x{8714}\x{8715}'
. '\x{8716}\x{8717}\x{8718}\x{8719}\x{871A}\x{871B}\x{871C}\x{871E}\x{871F}'
. '\x{8720}\x{8721}\x{8722}\x{8723}\x{8724}\x{8725}\x{8726}\x{8727}\x{8728}'
. '\x{8729}\x{872A}\x{872B}\x{872C}\x{872D}\x{872E}\x{8730}\x{8731}\x{8732}'
. '\x{8733}\x{8734}\x{8735}\x{8736}\x{8737}\x{8738}\x{8739}\x{873A}\x{873B}'
. '\x{873C}\x{873E}\x{873F}\x{8740}\x{8741}\x{8742}\x{8743}\x{8744}\x{8746}'
. '\x{8747}\x{8748}\x{8749}\x{874A}\x{874C}\x{874D}\x{874E}\x{874F}\x{8750}'
. '\x{8751}\x{8752}\x{8753}\x{8754}\x{8755}\x{8756}\x{8757}\x{8758}\x{8759}'
. '\x{875A}\x{875B}\x{875C}\x{875D}\x{875E}\x{875F}\x{8760}\x{8761}\x{8762}'
. '\x{8763}\x{8764}\x{8765}\x{8766}\x{8767}\x{8768}\x{8769}\x{876A}\x{876B}'
. '\x{876C}\x{876D}\x{876E}\x{876F}\x{8770}\x{8772}\x{8773}\x{8774}\x{8775}'
. '\x{8776}\x{8777}\x{8778}\x{8779}\x{877A}\x{877B}\x{877C}\x{877D}\x{877E}'
. '\x{8780}\x{8781}\x{8782}\x{8783}\x{8784}\x{8785}\x{8786}\x{8787}\x{8788}'
. '\x{8789}\x{878A}\x{878B}\x{878C}\x{878D}\x{878F}\x{8790}\x{8791}\x{8792}'
. '\x{8793}\x{8794}\x{8795}\x{8796}\x{8797}\x{8798}\x{879A}\x{879B}\x{879C}'
. '\x{879D}\x{879E}\x{879F}\x{87A0}\x{87A1}\x{87A2}\x{87A3}\x{87A4}\x{87A5}'
. '\x{87A6}\x{87A7}\x{87A8}\x{87A9}\x{87AA}\x{87AB}\x{87AC}\x{87AD}\x{87AE}'
. '\x{87AF}\x{87B0}\x{87B1}\x{87B2}\x{87B3}\x{87B4}\x{87B5}\x{87B6}\x{87B7}'
. '\x{87B8}\x{87B9}\x{87BA}\x{87BB}\x{87BC}\x{87BD}\x{87BE}\x{87BF}\x{87C0}'
. '\x{87C1}\x{87C2}\x{87C3}\x{87C4}\x{87C5}\x{87C6}\x{87C7}\x{87C8}\x{87C9}'
. '\x{87CA}\x{87CB}\x{87CC}\x{87CD}\x{87CE}\x{87CF}\x{87D0}\x{87D1}\x{87D2}'
. '\x{87D3}\x{87D4}\x{87D5}\x{87D6}\x{87D7}\x{87D8}\x{87D9}\x{87DB}\x{87DC}'
. '\x{87DD}\x{87DE}\x{87DF}\x{87E0}\x{87E1}\x{87E2}\x{87E3}\x{87E4}\x{87E5}'
. '\x{87E6}\x{87E7}\x{87E8}\x{87E9}\x{87EA}\x{87EB}\x{87EC}\x{87ED}\x{87EE}'
. '\x{87EF}\x{87F1}\x{87F2}\x{87F3}\x{87F4}\x{87F5}\x{87F6}\x{87F7}\x{87F8}'
. '\x{87F9}\x{87FA}\x{87FB}\x{87FC}\x{87FD}\x{87FE}\x{87FF}\x{8800}\x{8801}'
. '\x{8802}\x{8803}\x{8804}\x{8805}\x{8806}\x{8808}\x{8809}\x{880A}\x{880B}'
. '\x{880C}\x{880D}\x{880E}\x{880F}\x{8810}\x{8811}\x{8813}\x{8814}\x{8815}'
. '\x{8816}\x{8817}\x{8818}\x{8819}\x{881A}\x{881B}\x{881C}\x{881D}\x{881E}'
. '\x{881F}\x{8820}\x{8821}\x{8822}\x{8823}\x{8824}\x{8825}\x{8826}\x{8827}'
. '\x{8828}\x{8829}\x{882A}\x{882B}\x{882C}\x{882E}\x{882F}\x{8830}\x{8831}'
. '\x{8832}\x{8833}\x{8834}\x{8835}\x{8836}\x{8837}\x{8838}\x{8839}\x{883B}'
. '\x{883C}\x{883D}\x{883E}\x{883F}\x{8840}\x{8841}\x{8842}\x{8843}\x{8844}'
. '\x{8845}\x{8846}\x{8848}\x{8849}\x{884A}\x{884B}\x{884C}\x{884D}\x{884E}'
. '\x{884F}\x{8850}\x{8851}\x{8852}\x{8853}\x{8854}\x{8855}\x{8856}\x{8857}'
. '\x{8859}\x{885A}\x{885B}\x{885D}\x{885E}\x{8860}\x{8861}\x{8862}\x{8863}'
. '\x{8864}\x{8865}\x{8866}\x{8867}\x{8868}\x{8869}\x{886A}\x{886B}\x{886C}'
. '\x{886D}\x{886E}\x{886F}\x{8870}\x{8871}\x{8872}\x{8873}\x{8874}\x{8875}'
. '\x{8876}\x{8877}\x{8878}\x{8879}\x{887B}\x{887C}\x{887D}\x{887E}\x{887F}'
. '\x{8880}\x{8881}\x{8882}\x{8883}\x{8884}\x{8885}\x{8886}\x{8887}\x{8888}'
. '\x{8889}\x{888A}\x{888B}\x{888C}\x{888D}\x{888E}\x{888F}\x{8890}\x{8891}'
. '\x{8892}\x{8893}\x{8894}\x{8895}\x{8896}\x{8897}\x{8898}\x{8899}\x{889A}'
. '\x{889B}\x{889C}\x{889D}\x{889E}\x{889F}\x{88A0}\x{88A1}\x{88A2}\x{88A3}'
. '\x{88A4}\x{88A5}\x{88A6}\x{88A7}\x{88A8}\x{88A9}\x{88AA}\x{88AB}\x{88AC}'
. '\x{88AD}\x{88AE}\x{88AF}\x{88B0}\x{88B1}\x{88B2}\x{88B3}\x{88B4}\x{88B6}'
. '\x{88B7}\x{88B8}\x{88B9}\x{88BA}\x{88BB}\x{88BC}\x{88BD}\x{88BE}\x{88BF}'
. '\x{88C0}\x{88C1}\x{88C2}\x{88C3}\x{88C4}\x{88C5}\x{88C6}\x{88C7}\x{88C8}'
. '\x{88C9}\x{88CA}\x{88CB}\x{88CC}\x{88CD}\x{88CE}\x{88CF}\x{88D0}\x{88D1}'
. '\x{88D2}\x{88D3}\x{88D4}\x{88D5}\x{88D6}\x{88D7}\x{88D8}\x{88D9}\x{88DA}'
. '\x{88DB}\x{88DC}\x{88DD}\x{88DE}\x{88DF}\x{88E0}\x{88E1}\x{88E2}\x{88E3}'
. '\x{88E4}\x{88E5}\x{88E7}\x{88E8}\x{88EA}\x{88EB}\x{88EC}\x{88EE}\x{88EF}'
. '\x{88F0}\x{88F1}\x{88F2}\x{88F3}\x{88F4}\x{88F5}\x{88F6}\x{88F7}\x{88F8}'
. '\x{88F9}\x{88FA}\x{88FB}\x{88FC}\x{88FD}\x{88FE}\x{88FF}\x{8900}\x{8901}'
. '\x{8902}\x{8904}\x{8905}\x{8906}\x{8907}\x{8908}\x{8909}\x{890A}\x{890B}'
. '\x{890C}\x{890D}\x{890E}\x{8910}\x{8911}\x{8912}\x{8913}\x{8914}\x{8915}'
. '\x{8916}\x{8917}\x{8918}\x{8919}\x{891A}\x{891B}\x{891C}\x{891D}\x{891E}'
. '\x{891F}\x{8920}\x{8921}\x{8922}\x{8923}\x{8925}\x{8926}\x{8927}\x{8928}'
. '\x{8929}\x{892A}\x{892B}\x{892C}\x{892D}\x{892E}\x{892F}\x{8930}\x{8931}'
. '\x{8932}\x{8933}\x{8934}\x{8935}\x{8936}\x{8937}\x{8938}\x{8939}\x{893A}'
. '\x{893B}\x{893C}\x{893D}\x{893E}\x{893F}\x{8940}\x{8941}\x{8942}\x{8943}'
. '\x{8944}\x{8945}\x{8946}\x{8947}\x{8948}\x{8949}\x{894A}\x{894B}\x{894C}'
. '\x{894E}\x{894F}\x{8950}\x{8951}\x{8952}\x{8953}\x{8954}\x{8955}\x{8956}'
. '\x{8957}\x{8958}\x{8959}\x{895A}\x{895B}\x{895C}\x{895D}\x{895E}\x{895F}'
. '\x{8960}\x{8961}\x{8962}\x{8963}\x{8964}\x{8966}\x{8967}\x{8968}\x{8969}'
. '\x{896A}\x{896B}\x{896C}\x{896D}\x{896E}\x{896F}\x{8970}\x{8971}\x{8972}'
. '\x{8973}\x{8974}\x{8976}\x{8977}\x{8978}\x{8979}\x{897A}\x{897B}\x{897C}'
. '\x{897E}\x{897F}\x{8980}\x{8981}\x{8982}\x{8983}\x{8984}\x{8985}\x{8986}'
. '\x{8987}\x{8988}\x{8989}\x{898A}\x{898B}\x{898C}\x{898E}\x{898F}\x{8991}'
. '\x{8992}\x{8993}\x{8995}\x{8996}\x{8997}\x{8998}\x{899A}\x{899B}\x{899C}'
. '\x{899D}\x{899E}\x{899F}\x{89A0}\x{89A1}\x{89A2}\x{89A3}\x{89A4}\x{89A5}'
. '\x{89A6}\x{89A7}\x{89A8}\x{89AA}\x{89AB}\x{89AC}\x{89AD}\x{89AE}\x{89AF}'
. '\x{89B1}\x{89B2}\x{89B3}\x{89B5}\x{89B6}\x{89B7}\x{89B8}\x{89B9}\x{89BA}'
. '\x{89BD}\x{89BE}\x{89BF}\x{89C0}\x{89C1}\x{89C2}\x{89C3}\x{89C4}\x{89C5}'
. '\x{89C6}\x{89C7}\x{89C8}\x{89C9}\x{89CA}\x{89CB}\x{89CC}\x{89CD}\x{89CE}'
. '\x{89CF}\x{89D0}\x{89D1}\x{89D2}\x{89D3}\x{89D4}\x{89D5}\x{89D6}\x{89D7}'
. '\x{89D8}\x{89D9}\x{89DA}\x{89DB}\x{89DC}\x{89DD}\x{89DE}\x{89DF}\x{89E0}'
. '\x{89E1}\x{89E2}\x{89E3}\x{89E4}\x{89E5}\x{89E6}\x{89E7}\x{89E8}\x{89E9}'
. '\x{89EA}\x{89EB}\x{89EC}\x{89ED}\x{89EF}\x{89F0}\x{89F1}\x{89F2}\x{89F3}'
. '\x{89F4}\x{89F6}\x{89F7}\x{89F8}\x{89FA}\x{89FB}\x{89FC}\x{89FE}\x{89FF}'
. '\x{8A00}\x{8A01}\x{8A02}\x{8A03}\x{8A04}\x{8A07}\x{8A08}\x{8A09}\x{8A0A}'
. '\x{8A0B}\x{8A0C}\x{8A0D}\x{8A0E}\x{8A0F}\x{8A10}\x{8A11}\x{8A12}\x{8A13}'
. '\x{8A15}\x{8A16}\x{8A17}\x{8A18}\x{8A1A}\x{8A1B}\x{8A1C}\x{8A1D}\x{8A1E}'
. '\x{8A1F}\x{8A22}\x{8A23}\x{8A24}\x{8A25}\x{8A26}\x{8A27}\x{8A28}\x{8A29}'
. '\x{8A2A}\x{8A2C}\x{8A2D}\x{8A2E}\x{8A2F}\x{8A30}\x{8A31}\x{8A32}\x{8A34}'
. '\x{8A35}\x{8A36}\x{8A37}\x{8A38}\x{8A39}\x{8A3A}\x{8A3B}\x{8A3C}\x{8A3E}'
. '\x{8A3F}\x{8A40}\x{8A41}\x{8A42}\x{8A43}\x{8A44}\x{8A45}\x{8A46}\x{8A47}'
. '\x{8A48}\x{8A49}\x{8A4A}\x{8A4C}\x{8A4D}\x{8A4E}\x{8A4F}\x{8A50}\x{8A51}'
. '\x{8A52}\x{8A53}\x{8A54}\x{8A55}\x{8A56}\x{8A57}\x{8A58}\x{8A59}\x{8A5A}'
. '\x{8A5B}\x{8A5C}\x{8A5D}\x{8A5E}\x{8A5F}\x{8A60}\x{8A61}\x{8A62}\x{8A63}'
. '\x{8A65}\x{8A66}\x{8A67}\x{8A68}\x{8A69}\x{8A6A}\x{8A6B}\x{8A6C}\x{8A6D}'
. '\x{8A6E}\x{8A6F}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A74}\x{8A75}\x{8A76}'
. '\x{8A77}\x{8A79}\x{8A7A}\x{8A7B}\x{8A7C}\x{8A7E}\x{8A7F}\x{8A80}\x{8A81}'
. '\x{8A82}\x{8A83}\x{8A84}\x{8A85}\x{8A86}\x{8A87}\x{8A89}\x{8A8A}\x{8A8B}'
. '\x{8A8C}\x{8A8D}\x{8A8E}\x{8A8F}\x{8A90}\x{8A91}\x{8A92}\x{8A93}\x{8A94}'
. '\x{8A95}\x{8A96}\x{8A97}\x{8A98}\x{8A99}\x{8A9A}\x{8A9B}\x{8A9C}\x{8A9D}'
. '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA2}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA7}'
. '\x{8AA8}\x{8AA9}\x{8AAA}\x{8AAB}\x{8AAC}\x{8AAE}\x{8AB0}\x{8AB1}\x{8AB2}'
. '\x{8AB3}\x{8AB4}\x{8AB5}\x{8AB6}\x{8AB8}\x{8AB9}\x{8ABA}\x{8ABB}\x{8ABC}'
. '\x{8ABD}\x{8ABE}\x{8ABF}\x{8AC0}\x{8AC1}\x{8AC2}\x{8AC3}\x{8AC4}\x{8AC5}'
. '\x{8AC6}\x{8AC7}\x{8AC8}\x{8AC9}\x{8ACA}\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACE}'
. '\x{8ACF}\x{8AD1}\x{8AD2}\x{8AD3}\x{8AD4}\x{8AD5}\x{8AD6}\x{8AD7}\x{8AD8}'
. '\x{8AD9}\x{8ADA}\x{8ADB}\x{8ADC}\x{8ADD}\x{8ADE}\x{8ADF}\x{8AE0}\x{8AE1}'
. '\x{8AE2}\x{8AE3}\x{8AE4}\x{8AE5}\x{8AE6}\x{8AE7}\x{8AE8}\x{8AE9}\x{8AEA}'
. '\x{8AEB}\x{8AED}\x{8AEE}\x{8AEF}\x{8AF0}\x{8AF1}\x{8AF2}\x{8AF3}\x{8AF4}'
. '\x{8AF5}\x{8AF6}\x{8AF7}\x{8AF8}\x{8AF9}\x{8AFA}\x{8AFB}\x{8AFC}\x{8AFD}'
. '\x{8AFE}\x{8AFF}\x{8B00}\x{8B01}\x{8B02}\x{8B03}\x{8B04}\x{8B05}\x{8B06}'
. '\x{8B07}\x{8B08}\x{8B09}\x{8B0A}\x{8B0B}\x{8B0D}\x{8B0E}\x{8B0F}\x{8B10}'
. '\x{8B11}\x{8B12}\x{8B13}\x{8B14}\x{8B15}\x{8B16}\x{8B17}\x{8B18}\x{8B19}'
. '\x{8B1A}\x{8B1B}\x{8B1C}\x{8B1D}\x{8B1E}\x{8B1F}\x{8B20}\x{8B21}\x{8B22}'
. '\x{8B23}\x{8B24}\x{8B25}\x{8B26}\x{8B27}\x{8B28}\x{8B2A}\x{8B2B}\x{8B2C}'
. '\x{8B2D}\x{8B2E}\x{8B2F}\x{8B30}\x{8B31}\x{8B33}\x{8B34}\x{8B35}\x{8B36}'
. '\x{8B37}\x{8B39}\x{8B3A}\x{8B3B}\x{8B3C}\x{8B3D}\x{8B3E}\x{8B40}\x{8B41}'
. '\x{8B42}\x{8B43}\x{8B44}\x{8B45}\x{8B46}\x{8B47}\x{8B48}\x{8B49}\x{8B4A}'
. '\x{8B4B}\x{8B4C}\x{8B4D}\x{8B4E}\x{8B4F}\x{8B50}\x{8B51}\x{8B52}\x{8B53}'
. '\x{8B54}\x{8B55}\x{8B56}\x{8B57}\x{8B58}\x{8B59}\x{8B5A}\x{8B5B}\x{8B5C}'
. '\x{8B5D}\x{8B5E}\x{8B5F}\x{8B60}\x{8B63}\x{8B64}\x{8B65}\x{8B66}\x{8B67}'
. '\x{8B68}\x{8B6A}\x{8B6B}\x{8B6C}\x{8B6D}\x{8B6E}\x{8B6F}\x{8B70}\x{8B71}'
. '\x{8B73}\x{8B74}\x{8B76}\x{8B77}\x{8B78}\x{8B79}\x{8B7A}\x{8B7B}\x{8B7D}'
. '\x{8B7E}\x{8B7F}\x{8B80}\x{8B82}\x{8B83}\x{8B84}\x{8B85}\x{8B86}\x{8B88}'
. '\x{8B89}\x{8B8A}\x{8B8B}\x{8B8C}\x{8B8E}\x{8B90}\x{8B91}\x{8B92}\x{8B93}'
. '\x{8B94}\x{8B95}\x{8B96}\x{8B97}\x{8B98}\x{8B99}\x{8B9A}\x{8B9C}\x{8B9D}'
. '\x{8B9E}\x{8B9F}\x{8BA0}\x{8BA1}\x{8BA2}\x{8BA3}\x{8BA4}\x{8BA5}\x{8BA6}'
. '\x{8BA7}\x{8BA8}\x{8BA9}\x{8BAA}\x{8BAB}\x{8BAC}\x{8BAD}\x{8BAE}\x{8BAF}'
. '\x{8BB0}\x{8BB1}\x{8BB2}\x{8BB3}\x{8BB4}\x{8BB5}\x{8BB6}\x{8BB7}\x{8BB8}'
. '\x{8BB9}\x{8BBA}\x{8BBB}\x{8BBC}\x{8BBD}\x{8BBE}\x{8BBF}\x{8BC0}\x{8BC1}'
. '\x{8BC2}\x{8BC3}\x{8BC4}\x{8BC5}\x{8BC6}\x{8BC7}\x{8BC8}\x{8BC9}\x{8BCA}'
. '\x{8BCB}\x{8BCC}\x{8BCD}\x{8BCE}\x{8BCF}\x{8BD0}\x{8BD1}\x{8BD2}\x{8BD3}'
. '\x{8BD4}\x{8BD5}\x{8BD6}\x{8BD7}\x{8BD8}\x{8BD9}\x{8BDA}\x{8BDB}\x{8BDC}'
. '\x{8BDD}\x{8BDE}\x{8BDF}\x{8BE0}\x{8BE1}\x{8BE2}\x{8BE3}\x{8BE4}\x{8BE5}'
. '\x{8BE6}\x{8BE7}\x{8BE8}\x{8BE9}\x{8BEA}\x{8BEB}\x{8BEC}\x{8BED}\x{8BEE}'
. '\x{8BEF}\x{8BF0}\x{8BF1}\x{8BF2}\x{8BF3}\x{8BF4}\x{8BF5}\x{8BF6}\x{8BF7}'
. '\x{8BF8}\x{8BF9}\x{8BFA}\x{8BFB}\x{8BFC}\x{8BFD}\x{8BFE}\x{8BFF}\x{8C00}'
. '\x{8C01}\x{8C02}\x{8C03}\x{8C04}\x{8C05}\x{8C06}\x{8C07}\x{8C08}\x{8C09}'
. '\x{8C0A}\x{8C0B}\x{8C0C}\x{8C0D}\x{8C0E}\x{8C0F}\x{8C10}\x{8C11}\x{8C12}'
. '\x{8C13}\x{8C14}\x{8C15}\x{8C16}\x{8C17}\x{8C18}\x{8C19}\x{8C1A}\x{8C1B}'
. '\x{8C1C}\x{8C1D}\x{8C1E}\x{8C1F}\x{8C20}\x{8C21}\x{8C22}\x{8C23}\x{8C24}'
. '\x{8C25}\x{8C26}\x{8C27}\x{8C28}\x{8C29}\x{8C2A}\x{8C2B}\x{8C2C}\x{8C2D}'
. '\x{8C2E}\x{8C2F}\x{8C30}\x{8C31}\x{8C32}\x{8C33}\x{8C34}\x{8C35}\x{8C36}'
. '\x{8C37}\x{8C39}\x{8C3A}\x{8C3B}\x{8C3C}\x{8C3D}\x{8C3E}\x{8C3F}\x{8C41}'
. '\x{8C42}\x{8C43}\x{8C45}\x{8C46}\x{8C47}\x{8C48}\x{8C49}\x{8C4A}\x{8C4B}'
. '\x{8C4C}\x{8C4D}\x{8C4E}\x{8C4F}\x{8C50}\x{8C54}\x{8C55}\x{8C56}\x{8C57}'
. '\x{8C59}\x{8C5A}\x{8C5B}\x{8C5C}\x{8C5D}\x{8C5E}\x{8C5F}\x{8C60}\x{8C61}'
. '\x{8C62}\x{8C63}\x{8C64}\x{8C65}\x{8C66}\x{8C67}\x{8C68}\x{8C69}\x{8C6A}'
. '\x{8C6B}\x{8C6C}\x{8C6D}\x{8C6E}\x{8C6F}\x{8C70}\x{8C71}\x{8C72}\x{8C73}'
. '\x{8C75}\x{8C76}\x{8C77}\x{8C78}\x{8C79}\x{8C7A}\x{8C7B}\x{8C7D}\x{8C7E}'
. '\x{8C80}\x{8C81}\x{8C82}\x{8C84}\x{8C85}\x{8C86}\x{8C88}\x{8C89}\x{8C8A}'
. '\x{8C8C}\x{8C8D}\x{8C8F}\x{8C90}\x{8C91}\x{8C92}\x{8C93}\x{8C94}\x{8C95}'
. '\x{8C96}\x{8C97}\x{8C98}\x{8C99}\x{8C9A}\x{8C9C}\x{8C9D}\x{8C9E}\x{8C9F}'
. '\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA3}\x{8CA4}\x{8CA5}\x{8CA7}\x{8CA8}\x{8CA9}'
. '\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}\x{8CB1}\x{8CB2}'
. '\x{8CB3}\x{8CB4}\x{8CB5}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CB9}\x{8CBA}\x{8CBB}'
. '\x{8CBC}\x{8CBD}\x{8CBE}\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}'
. '\x{8CC5}\x{8CC6}\x{8CC7}\x{8CC8}\x{8CC9}\x{8CCA}\x{8CCC}\x{8CCE}\x{8CCF}'
. '\x{8CD0}\x{8CD1}\x{8CD2}\x{8CD3}\x{8CD4}\x{8CD5}\x{8CD7}\x{8CD9}\x{8CDA}'
. '\x{8CDB}\x{8CDC}\x{8CDD}\x{8CDE}\x{8CDF}\x{8CE0}\x{8CE1}\x{8CE2}\x{8CE3}'
. '\x{8CE4}\x{8CE5}\x{8CE6}\x{8CE7}\x{8CE8}\x{8CEA}\x{8CEB}\x{8CEC}\x{8CED}'
. '\x{8CEE}\x{8CEF}\x{8CF0}\x{8CF1}\x{8CF2}\x{8CF3}\x{8CF4}\x{8CF5}\x{8CF6}'
. '\x{8CF8}\x{8CF9}\x{8CFA}\x{8CFB}\x{8CFC}\x{8CFD}\x{8CFE}\x{8CFF}\x{8D00}'
. '\x{8D02}\x{8D03}\x{8D04}\x{8D05}\x{8D06}\x{8D07}\x{8D08}\x{8D09}\x{8D0A}'
. '\x{8D0B}\x{8D0C}\x{8D0D}\x{8D0E}\x{8D0F}\x{8D10}\x{8D13}\x{8D14}\x{8D15}'
. '\x{8D16}\x{8D17}\x{8D18}\x{8D19}\x{8D1A}\x{8D1B}\x{8D1C}\x{8D1D}\x{8D1E}'
. '\x{8D1F}\x{8D20}\x{8D21}\x{8D22}\x{8D23}\x{8D24}\x{8D25}\x{8D26}\x{8D27}'
. '\x{8D28}\x{8D29}\x{8D2A}\x{8D2B}\x{8D2C}\x{8D2D}\x{8D2E}\x{8D2F}\x{8D30}'
. '\x{8D31}\x{8D32}\x{8D33}\x{8D34}\x{8D35}\x{8D36}\x{8D37}\x{8D38}\x{8D39}'
. '\x{8D3A}\x{8D3B}\x{8D3C}\x{8D3D}\x{8D3E}\x{8D3F}\x{8D40}\x{8D41}\x{8D42}'
. '\x{8D43}\x{8D44}\x{8D45}\x{8D46}\x{8D47}\x{8D48}\x{8D49}\x{8D4A}\x{8D4B}'
. '\x{8D4C}\x{8D4D}\x{8D4E}\x{8D4F}\x{8D50}\x{8D51}\x{8D52}\x{8D53}\x{8D54}'
. '\x{8D55}\x{8D56}\x{8D57}\x{8D58}\x{8D59}\x{8D5A}\x{8D5B}\x{8D5C}\x{8D5D}'
. '\x{8D5E}\x{8D5F}\x{8D60}\x{8D61}\x{8D62}\x{8D63}\x{8D64}\x{8D65}\x{8D66}'
. '\x{8D67}\x{8D68}\x{8D69}\x{8D6A}\x{8D6B}\x{8D6C}\x{8D6D}\x{8D6E}\x{8D6F}'
. '\x{8D70}\x{8D71}\x{8D72}\x{8D73}\x{8D74}\x{8D75}\x{8D76}\x{8D77}\x{8D78}'
. '\x{8D79}\x{8D7A}\x{8D7B}\x{8D7D}\x{8D7E}\x{8D7F}\x{8D80}\x{8D81}\x{8D82}'
. '\x{8D83}\x{8D84}\x{8D85}\x{8D86}\x{8D87}\x{8D88}\x{8D89}\x{8D8A}\x{8D8B}'
. '\x{8D8C}\x{8D8D}\x{8D8E}\x{8D8F}\x{8D90}\x{8D91}\x{8D92}\x{8D93}\x{8D94}'
. '\x{8D95}\x{8D96}\x{8D97}\x{8D98}\x{8D99}\x{8D9A}\x{8D9B}\x{8D9C}\x{8D9D}'
. '\x{8D9E}\x{8D9F}\x{8DA0}\x{8DA1}\x{8DA2}\x{8DA3}\x{8DA4}\x{8DA5}\x{8DA7}'
. '\x{8DA8}\x{8DA9}\x{8DAA}\x{8DAB}\x{8DAC}\x{8DAD}\x{8DAE}\x{8DAF}\x{8DB0}'
. '\x{8DB1}\x{8DB2}\x{8DB3}\x{8DB4}\x{8DB5}\x{8DB6}\x{8DB7}\x{8DB8}\x{8DB9}'
. '\x{8DBA}\x{8DBB}\x{8DBC}\x{8DBD}\x{8DBE}\x{8DBF}\x{8DC1}\x{8DC2}\x{8DC3}'
. '\x{8DC4}\x{8DC5}\x{8DC6}\x{8DC7}\x{8DC8}\x{8DC9}\x{8DCA}\x{8DCB}\x{8DCC}'
. '\x{8DCD}\x{8DCE}\x{8DCF}\x{8DD0}\x{8DD1}\x{8DD2}\x{8DD3}\x{8DD4}\x{8DD5}'
. '\x{8DD6}\x{8DD7}\x{8DD8}\x{8DD9}\x{8DDA}\x{8DDB}\x{8DDC}\x{8DDD}\x{8DDE}'
. '\x{8DDF}\x{8DE0}\x{8DE1}\x{8DE2}\x{8DE3}\x{8DE4}\x{8DE6}\x{8DE7}\x{8DE8}'
. '\x{8DE9}\x{8DEA}\x{8DEB}\x{8DEC}\x{8DED}\x{8DEE}\x{8DEF}\x{8DF0}\x{8DF1}'
. '\x{8DF2}\x{8DF3}\x{8DF4}\x{8DF5}\x{8DF6}\x{8DF7}\x{8DF8}\x{8DF9}\x{8DFA}'
. '\x{8DFB}\x{8DFC}\x{8DFD}\x{8DFE}\x{8DFF}\x{8E00}\x{8E02}\x{8E03}\x{8E04}'
. '\x{8E05}\x{8E06}\x{8E07}\x{8E08}\x{8E09}\x{8E0A}\x{8E0C}\x{8E0D}\x{8E0E}'
. '\x{8E0F}\x{8E10}\x{8E11}\x{8E12}\x{8E13}\x{8E14}\x{8E15}\x{8E16}\x{8E17}'
. '\x{8E18}\x{8E19}\x{8E1A}\x{8E1B}\x{8E1C}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E20}'
. '\x{8E21}\x{8E22}\x{8E23}\x{8E24}\x{8E25}\x{8E26}\x{8E27}\x{8E28}\x{8E29}'
. '\x{8E2A}\x{8E2B}\x{8E2C}\x{8E2D}\x{8E2E}\x{8E2F}\x{8E30}\x{8E31}\x{8E33}'
. '\x{8E34}\x{8E35}\x{8E36}\x{8E37}\x{8E38}\x{8E39}\x{8E3A}\x{8E3B}\x{8E3C}'
. '\x{8E3D}\x{8E3E}\x{8E3F}\x{8E40}\x{8E41}\x{8E42}\x{8E43}\x{8E44}\x{8E45}'
. '\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4B}\x{8E4C}\x{8E4D}\x{8E4E}\x{8E50}'
. '\x{8E51}\x{8E52}\x{8E53}\x{8E54}\x{8E55}\x{8E56}\x{8E57}\x{8E58}\x{8E59}'
. '\x{8E5A}\x{8E5B}\x{8E5C}\x{8E5D}\x{8E5E}\x{8E5F}\x{8E60}\x{8E61}\x{8E62}'
. '\x{8E63}\x{8E64}\x{8E65}\x{8E66}\x{8E67}\x{8E68}\x{8E69}\x{8E6A}\x{8E6B}'
. '\x{8E6C}\x{8E6D}\x{8E6F}\x{8E70}\x{8E71}\x{8E72}\x{8E73}\x{8E74}\x{8E76}'
. '\x{8E78}\x{8E7A}\x{8E7B}\x{8E7C}\x{8E7D}\x{8E7E}\x{8E7F}\x{8E80}\x{8E81}'
. '\x{8E82}\x{8E83}\x{8E84}\x{8E85}\x{8E86}\x{8E87}\x{8E88}\x{8E89}\x{8E8A}'
. '\x{8E8B}\x{8E8C}\x{8E8D}\x{8E8E}\x{8E8F}\x{8E90}\x{8E91}\x{8E92}\x{8E93}'
. '\x{8E94}\x{8E95}\x{8E96}\x{8E97}\x{8E98}\x{8E9A}\x{8E9C}\x{8E9D}\x{8E9E}'
. '\x{8E9F}\x{8EA0}\x{8EA1}\x{8EA3}\x{8EA4}\x{8EA5}\x{8EA6}\x{8EA7}\x{8EA8}'
. '\x{8EA9}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAD}\x{8EAE}\x{8EAF}\x{8EB0}\x{8EB1}'
. '\x{8EB2}\x{8EB4}\x{8EB5}\x{8EB8}\x{8EB9}\x{8EBA}\x{8EBB}\x{8EBC}\x{8EBD}'
. '\x{8EBE}\x{8EBF}\x{8EC0}\x{8EC2}\x{8EC3}\x{8EC5}\x{8EC6}\x{8EC7}\x{8EC8}'
. '\x{8EC9}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ECE}\x{8ECF}\x{8ED0}\x{8ED1}'
. '\x{8ED2}\x{8ED3}\x{8ED4}\x{8ED5}\x{8ED6}\x{8ED7}\x{8ED8}\x{8EDA}\x{8EDB}'
. '\x{8EDC}\x{8EDD}\x{8EDE}\x{8EDF}\x{8EE0}\x{8EE1}\x{8EE4}\x{8EE5}\x{8EE6}'
. '\x{8EE7}\x{8EE8}\x{8EE9}\x{8EEA}\x{8EEB}\x{8EEC}\x{8EED}\x{8EEE}\x{8EEF}'
. '\x{8EF1}\x{8EF2}\x{8EF3}\x{8EF4}\x{8EF5}\x{8EF6}\x{8EF7}\x{8EF8}\x{8EF9}'
. '\x{8EFA}\x{8EFB}\x{8EFC}\x{8EFD}\x{8EFE}\x{8EFF}\x{8F00}\x{8F01}\x{8F02}'
. '\x{8F03}\x{8F04}\x{8F05}\x{8F06}\x{8F07}\x{8F08}\x{8F09}\x{8F0A}\x{8F0B}'
. '\x{8F0D}\x{8F0E}\x{8F10}\x{8F11}\x{8F12}\x{8F13}\x{8F14}\x{8F15}\x{8F16}'
. '\x{8F17}\x{8F18}\x{8F1A}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1E}\x{8F1F}\x{8F20}'
. '\x{8F21}\x{8F22}\x{8F23}\x{8F24}\x{8F25}\x{8F26}\x{8F27}\x{8F28}\x{8F29}'
. '\x{8F2A}\x{8F2B}\x{8F2C}\x{8F2E}\x{8F2F}\x{8F30}\x{8F31}\x{8F32}\x{8F33}'
. '\x{8F34}\x{8F35}\x{8F36}\x{8F37}\x{8F38}\x{8F39}\x{8F3B}\x{8F3C}\x{8F3D}'
. '\x{8F3E}\x{8F3F}\x{8F40}\x{8F42}\x{8F43}\x{8F44}\x{8F45}\x{8F46}\x{8F47}'
. '\x{8F48}\x{8F49}\x{8F4A}\x{8F4B}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F4F}\x{8F50}'
. '\x{8F51}\x{8F52}\x{8F53}\x{8F54}\x{8F55}\x{8F56}\x{8F57}\x{8F58}\x{8F59}'
. '\x{8F5A}\x{8F5B}\x{8F5D}\x{8F5E}\x{8F5F}\x{8F60}\x{8F61}\x{8F62}\x{8F63}'
. '\x{8F64}\x{8F65}\x{8F66}\x{8F67}\x{8F68}\x{8F69}\x{8F6A}\x{8F6B}\x{8F6C}'
. '\x{8F6D}\x{8F6E}\x{8F6F}\x{8F70}\x{8F71}\x{8F72}\x{8F73}\x{8F74}\x{8F75}'
. '\x{8F76}\x{8F77}\x{8F78}\x{8F79}\x{8F7A}\x{8F7B}\x{8F7C}\x{8F7D}\x{8F7E}'
. '\x{8F7F}\x{8F80}\x{8F81}\x{8F82}\x{8F83}\x{8F84}\x{8F85}\x{8F86}\x{8F87}'
. '\x{8F88}\x{8F89}\x{8F8A}\x{8F8B}\x{8F8C}\x{8F8D}\x{8F8E}\x{8F8F}\x{8F90}'
. '\x{8F91}\x{8F92}\x{8F93}\x{8F94}\x{8F95}\x{8F96}\x{8F97}\x{8F98}\x{8F99}'
. '\x{8F9A}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA0}\x{8FA1}\x{8FA2}\x{8FA3}'
. '\x{8FA5}\x{8FA6}\x{8FA7}\x{8FA8}\x{8FA9}\x{8FAA}\x{8FAB}\x{8FAC}\x{8FAD}'
. '\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB4}\x{8FB5}\x{8FB6}\x{8FB7}'
. '\x{8FB8}\x{8FB9}\x{8FBB}\x{8FBC}\x{8FBD}\x{8FBE}\x{8FBF}\x{8FC0}\x{8FC1}'
. '\x{8FC2}\x{8FC4}\x{8FC5}\x{8FC6}\x{8FC7}\x{8FC8}\x{8FC9}\x{8FCB}\x{8FCC}'
. '\x{8FCD}\x{8FCE}\x{8FCF}\x{8FD0}\x{8FD1}\x{8FD2}\x{8FD3}\x{8FD4}\x{8FD5}'
. '\x{8FD6}\x{8FD7}\x{8FD8}\x{8FD9}\x{8FDA}\x{8FDB}\x{8FDC}\x{8FDD}\x{8FDE}'
. '\x{8FDF}\x{8FE0}\x{8FE1}\x{8FE2}\x{8FE3}\x{8FE4}\x{8FE5}\x{8FE6}\x{8FE8}'
. '\x{8FE9}\x{8FEA}\x{8FEB}\x{8FEC}\x{8FED}\x{8FEE}\x{8FEF}\x{8FF0}\x{8FF1}'
. '\x{8FF2}\x{8FF3}\x{8FF4}\x{8FF5}\x{8FF6}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}'
. '\x{8FFB}\x{8FFC}\x{8FFD}\x{8FFE}\x{8FFF}\x{9000}\x{9001}\x{9002}\x{9003}'
. '\x{9004}\x{9005}\x{9006}\x{9007}\x{9008}\x{9009}\x{900A}\x{900B}\x{900C}'
. '\x{900D}\x{900F}\x{9010}\x{9011}\x{9012}\x{9013}\x{9014}\x{9015}\x{9016}'
. '\x{9017}\x{9018}\x{9019}\x{901A}\x{901B}\x{901C}\x{901D}\x{901E}\x{901F}'
. '\x{9020}\x{9021}\x{9022}\x{9023}\x{9024}\x{9025}\x{9026}\x{9027}\x{9028}'
. '\x{9029}\x{902B}\x{902D}\x{902E}\x{902F}\x{9030}\x{9031}\x{9032}\x{9033}'
. '\x{9034}\x{9035}\x{9036}\x{9038}\x{903A}\x{903B}\x{903C}\x{903D}\x{903E}'
. '\x{903F}\x{9041}\x{9042}\x{9043}\x{9044}\x{9045}\x{9047}\x{9048}\x{9049}'
. '\x{904A}\x{904B}\x{904C}\x{904D}\x{904E}\x{904F}\x{9050}\x{9051}\x{9052}'
. '\x{9053}\x{9054}\x{9055}\x{9056}\x{9057}\x{9058}\x{9059}\x{905A}\x{905B}'
. '\x{905C}\x{905D}\x{905E}\x{905F}\x{9060}\x{9061}\x{9062}\x{9063}\x{9064}'
. '\x{9065}\x{9066}\x{9067}\x{9068}\x{9069}\x{906A}\x{906B}\x{906C}\x{906D}'
. '\x{906E}\x{906F}\x{9070}\x{9071}\x{9072}\x{9073}\x{9074}\x{9075}\x{9076}'
. '\x{9077}\x{9078}\x{9079}\x{907A}\x{907B}\x{907C}\x{907D}\x{907E}\x{907F}'
. '\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9085}\x{9086}\x{9087}\x{9088}'
. '\x{9089}\x{908A}\x{908B}\x{908C}\x{908D}\x{908E}\x{908F}\x{9090}\x{9091}'
. '\x{9092}\x{9093}\x{9094}\x{9095}\x{9096}\x{9097}\x{9098}\x{9099}\x{909A}'
. '\x{909B}\x{909C}\x{909D}\x{909E}\x{909F}\x{90A0}\x{90A1}\x{90A2}\x{90A3}'
. '\x{90A4}\x{90A5}\x{90A6}\x{90A7}\x{90A8}\x{90A9}\x{90AA}\x{90AC}\x{90AD}'
. '\x{90AE}\x{90AF}\x{90B0}\x{90B1}\x{90B2}\x{90B3}\x{90B4}\x{90B5}\x{90B6}'
. '\x{90B7}\x{90B8}\x{90B9}\x{90BA}\x{90BB}\x{90BC}\x{90BD}\x{90BE}\x{90BF}'
. '\x{90C0}\x{90C1}\x{90C2}\x{90C3}\x{90C4}\x{90C5}\x{90C6}\x{90C7}\x{90C8}'
. '\x{90C9}\x{90CA}\x{90CB}\x{90CE}\x{90CF}\x{90D0}\x{90D1}\x{90D3}\x{90D4}'
. '\x{90D5}\x{90D6}\x{90D7}\x{90D8}\x{90D9}\x{90DA}\x{90DB}\x{90DC}\x{90DD}'
. '\x{90DE}\x{90DF}\x{90E0}\x{90E1}\x{90E2}\x{90E3}\x{90E4}\x{90E5}\x{90E6}'
. '\x{90E7}\x{90E8}\x{90E9}\x{90EA}\x{90EB}\x{90EC}\x{90ED}\x{90EE}\x{90EF}'
. '\x{90F0}\x{90F1}\x{90F2}\x{90F3}\x{90F4}\x{90F5}\x{90F7}\x{90F8}\x{90F9}'
. '\x{90FA}\x{90FB}\x{90FC}\x{90FD}\x{90FE}\x{90FF}\x{9100}\x{9101}\x{9102}'
. '\x{9103}\x{9104}\x{9105}\x{9106}\x{9107}\x{9108}\x{9109}\x{910B}\x{910C}'
. '\x{910D}\x{910E}\x{910F}\x{9110}\x{9111}\x{9112}\x{9113}\x{9114}\x{9115}'
. '\x{9116}\x{9117}\x{9118}\x{9119}\x{911A}\x{911B}\x{911C}\x{911D}\x{911E}'
. '\x{911F}\x{9120}\x{9121}\x{9122}\x{9123}\x{9124}\x{9125}\x{9126}\x{9127}'
. '\x{9128}\x{9129}\x{912A}\x{912B}\x{912C}\x{912D}\x{912E}\x{912F}\x{9130}'
. '\x{9131}\x{9132}\x{9133}\x{9134}\x{9135}\x{9136}\x{9137}\x{9138}\x{9139}'
. '\x{913A}\x{913B}\x{913E}\x{913F}\x{9140}\x{9141}\x{9142}\x{9143}\x{9144}'
. '\x{9145}\x{9146}\x{9147}\x{9148}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}'
. '\x{914E}\x{914F}\x{9150}\x{9151}\x{9152}\x{9153}\x{9154}\x{9155}\x{9156}'
. '\x{9157}\x{9158}\x{915A}\x{915B}\x{915C}\x{915D}\x{915E}\x{915F}\x{9160}'
. '\x{9161}\x{9162}\x{9163}\x{9164}\x{9165}\x{9166}\x{9167}\x{9168}\x{9169}'
. '\x{916A}\x{916B}\x{916C}\x{916D}\x{916E}\x{916F}\x{9170}\x{9171}\x{9172}'
. '\x{9173}\x{9174}\x{9175}\x{9176}\x{9177}\x{9178}\x{9179}\x{917A}\x{917C}'
. '\x{917D}\x{917E}\x{917F}\x{9180}\x{9181}\x{9182}\x{9183}\x{9184}\x{9185}'
. '\x{9186}\x{9187}\x{9188}\x{9189}\x{918A}\x{918B}\x{918C}\x{918D}\x{918E}'
. '\x{918F}\x{9190}\x{9191}\x{9192}\x{9193}\x{9194}\x{9196}\x{9199}\x{919A}'
. '\x{919B}\x{919C}\x{919D}\x{919E}\x{919F}\x{91A0}\x{91A1}\x{91A2}\x{91A3}'
. '\x{91A5}\x{91A6}\x{91A7}\x{91A8}\x{91AA}\x{91AB}\x{91AC}\x{91AD}\x{91AE}'
. '\x{91AF}\x{91B0}\x{91B1}\x{91B2}\x{91B3}\x{91B4}\x{91B5}\x{91B6}\x{91B7}'
. '\x{91B9}\x{91BA}\x{91BB}\x{91BC}\x{91BD}\x{91BE}\x{91C0}\x{91C1}\x{91C2}'
. '\x{91C3}\x{91C5}\x{91C6}\x{91C7}\x{91C9}\x{91CA}\x{91CB}\x{91CC}\x{91CD}'
. '\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D2}\x{91D3}\x{91D4}\x{91D5}\x{91D7}'
. '\x{91D8}\x{91D9}\x{91DA}\x{91DB}\x{91DC}\x{91DD}\x{91DE}\x{91DF}\x{91E2}'
. '\x{91E3}\x{91E4}\x{91E5}\x{91E6}\x{91E7}\x{91E8}\x{91E9}\x{91EA}\x{91EB}'
. '\x{91EC}\x{91ED}\x{91EE}\x{91F0}\x{91F1}\x{91F2}\x{91F3}\x{91F4}\x{91F5}'
. '\x{91F7}\x{91F8}\x{91F9}\x{91FA}\x{91FB}\x{91FD}\x{91FE}\x{91FF}\x{9200}'
. '\x{9201}\x{9202}\x{9203}\x{9204}\x{9205}\x{9206}\x{9207}\x{9208}\x{9209}'
. '\x{920A}\x{920B}\x{920C}\x{920D}\x{920E}\x{920F}\x{9210}\x{9211}\x{9212}'
. '\x{9214}\x{9215}\x{9216}\x{9217}\x{9218}\x{9219}\x{921A}\x{921B}\x{921C}'
. '\x{921D}\x{921E}\x{9220}\x{9221}\x{9223}\x{9224}\x{9225}\x{9226}\x{9227}'
. '\x{9228}\x{9229}\x{922A}\x{922B}\x{922D}\x{922E}\x{922F}\x{9230}\x{9231}'
. '\x{9232}\x{9233}\x{9234}\x{9235}\x{9236}\x{9237}\x{9238}\x{9239}\x{923A}'
. '\x{923B}\x{923C}\x{923D}\x{923E}\x{923F}\x{9240}\x{9241}\x{9242}\x{9245}'
. '\x{9246}\x{9247}\x{9248}\x{9249}\x{924A}\x{924B}\x{924C}\x{924D}\x{924E}'
. '\x{924F}\x{9250}\x{9251}\x{9252}\x{9253}\x{9254}\x{9255}\x{9256}\x{9257}'
. '\x{9258}\x{9259}\x{925A}\x{925B}\x{925C}\x{925D}\x{925E}\x{925F}\x{9260}'
. '\x{9261}\x{9262}\x{9263}\x{9264}\x{9265}\x{9266}\x{9267}\x{9268}\x{926B}'
. '\x{926C}\x{926D}\x{926E}\x{926F}\x{9270}\x{9272}\x{9273}\x{9274}\x{9275}'
. '\x{9276}\x{9277}\x{9278}\x{9279}\x{927A}\x{927B}\x{927C}\x{927D}\x{927E}'
. '\x{927F}\x{9280}\x{9282}\x{9283}\x{9285}\x{9286}\x{9287}\x{9288}\x{9289}'
. '\x{928A}\x{928B}\x{928C}\x{928D}\x{928E}\x{928F}\x{9290}\x{9291}\x{9292}'
. '\x{9293}\x{9294}\x{9295}\x{9296}\x{9297}\x{9298}\x{9299}\x{929A}\x{929B}'
. '\x{929C}\x{929D}\x{929F}\x{92A0}\x{92A1}\x{92A2}\x{92A3}\x{92A4}\x{92A5}'
. '\x{92A6}\x{92A7}\x{92A8}\x{92A9}\x{92AA}\x{92AB}\x{92AC}\x{92AD}\x{92AE}'
. '\x{92AF}\x{92B0}\x{92B1}\x{92B2}\x{92B3}\x{92B4}\x{92B5}\x{92B6}\x{92B7}'
. '\x{92B8}\x{92B9}\x{92BA}\x{92BB}\x{92BC}\x{92BE}\x{92BF}\x{92C0}\x{92C1}'
. '\x{92C2}\x{92C3}\x{92C4}\x{92C5}\x{92C6}\x{92C7}\x{92C8}\x{92C9}\x{92CA}'
. '\x{92CB}\x{92CC}\x{92CD}\x{92CE}\x{92CF}\x{92D0}\x{92D1}\x{92D2}\x{92D3}'
. '\x{92D5}\x{92D6}\x{92D7}\x{92D8}\x{92D9}\x{92DA}\x{92DC}\x{92DD}\x{92DE}'
. '\x{92DF}\x{92E0}\x{92E1}\x{92E3}\x{92E4}\x{92E5}\x{92E6}\x{92E7}\x{92E8}'
. '\x{92E9}\x{92EA}\x{92EB}\x{92EC}\x{92ED}\x{92EE}\x{92EF}\x{92F0}\x{92F1}'
. '\x{92F2}\x{92F3}\x{92F4}\x{92F5}\x{92F6}\x{92F7}\x{92F8}\x{92F9}\x{92FA}'
. '\x{92FB}\x{92FC}\x{92FD}\x{92FE}\x{92FF}\x{9300}\x{9301}\x{9302}\x{9303}'
. '\x{9304}\x{9305}\x{9306}\x{9307}\x{9308}\x{9309}\x{930A}\x{930B}\x{930C}'
. '\x{930D}\x{930E}\x{930F}\x{9310}\x{9311}\x{9312}\x{9313}\x{9314}\x{9315}'
. '\x{9316}\x{9317}\x{9318}\x{9319}\x{931A}\x{931B}\x{931D}\x{931E}\x{931F}'
. '\x{9320}\x{9321}\x{9322}\x{9323}\x{9324}\x{9325}\x{9326}\x{9327}\x{9328}'
. '\x{9329}\x{932A}\x{932B}\x{932D}\x{932E}\x{932F}\x{9332}\x{9333}\x{9334}'
. '\x{9335}\x{9336}\x{9337}\x{9338}\x{9339}\x{933A}\x{933B}\x{933C}\x{933D}'
. '\x{933E}\x{933F}\x{9340}\x{9341}\x{9342}\x{9343}\x{9344}\x{9345}\x{9346}'
. '\x{9347}\x{9348}\x{9349}\x{934A}\x{934B}\x{934C}\x{934D}\x{934E}\x{934F}'
. '\x{9350}\x{9351}\x{9352}\x{9353}\x{9354}\x{9355}\x{9356}\x{9357}\x{9358}'
. '\x{9359}\x{935A}\x{935B}\x{935C}\x{935D}\x{935E}\x{935F}\x{9360}\x{9361}'
. '\x{9363}\x{9364}\x{9365}\x{9366}\x{9367}\x{9369}\x{936A}\x{936C}\x{936D}'
. '\x{936E}\x{9370}\x{9371}\x{9372}\x{9374}\x{9375}\x{9376}\x{9377}\x{9379}'
. '\x{937A}\x{937B}\x{937C}\x{937D}\x{937E}\x{9380}\x{9382}\x{9383}\x{9384}'
. '\x{9385}\x{9386}\x{9387}\x{9388}\x{9389}\x{938A}\x{938C}\x{938D}\x{938E}'
. '\x{938F}\x{9390}\x{9391}\x{9392}\x{9393}\x{9394}\x{9395}\x{9396}\x{9397}'
. '\x{9398}\x{9399}\x{939A}\x{939B}\x{939D}\x{939E}\x{939F}\x{93A1}\x{93A2}'
. '\x{93A3}\x{93A4}\x{93A5}\x{93A6}\x{93A7}\x{93A8}\x{93A9}\x{93AA}\x{93AC}'
. '\x{93AD}\x{93AE}\x{93AF}\x{93B0}\x{93B1}\x{93B2}\x{93B3}\x{93B4}\x{93B5}'
. '\x{93B6}\x{93B7}\x{93B8}\x{93B9}\x{93BA}\x{93BC}\x{93BD}\x{93BE}\x{93BF}'
. '\x{93C0}\x{93C1}\x{93C2}\x{93C3}\x{93C4}\x{93C5}\x{93C6}\x{93C7}\x{93C8}'
. '\x{93C9}\x{93CA}\x{93CB}\x{93CC}\x{93CD}\x{93CE}\x{93CF}\x{93D0}\x{93D1}'
. '\x{93D2}\x{93D3}\x{93D4}\x{93D5}\x{93D6}\x{93D7}\x{93D8}\x{93D9}\x{93DA}'
. '\x{93DB}\x{93DC}\x{93DD}\x{93DE}\x{93DF}\x{93E1}\x{93E2}\x{93E3}\x{93E4}'
. '\x{93E6}\x{93E7}\x{93E8}\x{93E9}\x{93EA}\x{93EB}\x{93EC}\x{93ED}\x{93EE}'
. '\x{93EF}\x{93F0}\x{93F1}\x{93F2}\x{93F4}\x{93F5}\x{93F6}\x{93F7}\x{93F8}'
. '\x{93F9}\x{93FA}\x{93FB}\x{93FC}\x{93FD}\x{93FE}\x{93FF}\x{9400}\x{9401}'
. '\x{9403}\x{9404}\x{9405}\x{9406}\x{9407}\x{9408}\x{9409}\x{940A}\x{940B}'
. '\x{940C}\x{940D}\x{940E}\x{940F}\x{9410}\x{9411}\x{9412}\x{9413}\x{9414}'
. '\x{9415}\x{9416}\x{9418}\x{9419}\x{941B}\x{941D}\x{9420}\x{9422}\x{9423}'
. '\x{9425}\x{9426}\x{9427}\x{9428}\x{9429}\x{942A}\x{942B}\x{942C}\x{942D}'
. '\x{942E}\x{942F}\x{9430}\x{9431}\x{9432}\x{9433}\x{9434}\x{9435}\x{9436}'
. '\x{9437}\x{9438}\x{9439}\x{943A}\x{943B}\x{943C}\x{943D}\x{943E}\x{943F}'
. '\x{9440}\x{9441}\x{9442}\x{9444}\x{9445}\x{9446}\x{9447}\x{9448}\x{9449}'
. '\x{944A}\x{944B}\x{944C}\x{944D}\x{944F}\x{9450}\x{9451}\x{9452}\x{9453}'
. '\x{9454}\x{9455}\x{9456}\x{9457}\x{9458}\x{9459}\x{945B}\x{945C}\x{945D}'
. '\x{945E}\x{945F}\x{9460}\x{9461}\x{9462}\x{9463}\x{9464}\x{9465}\x{9466}'
. '\x{9467}\x{9468}\x{9469}\x{946A}\x{946B}\x{946D}\x{946E}\x{946F}\x{9470}'
. '\x{9471}\x{9472}\x{9473}\x{9474}\x{9475}\x{9476}\x{9477}\x{9478}\x{9479}'
. '\x{947A}\x{947C}\x{947D}\x{947E}\x{947F}\x{9480}\x{9481}\x{9482}\x{9483}'
. '\x{9484}\x{9485}\x{9486}\x{9487}\x{9488}\x{9489}\x{948A}\x{948B}\x{948C}'
. '\x{948D}\x{948E}\x{948F}\x{9490}\x{9491}\x{9492}\x{9493}\x{9494}\x{9495}'
. '\x{9496}\x{9497}\x{9498}\x{9499}\x{949A}\x{949B}\x{949C}\x{949D}\x{949E}'
. '\x{949F}\x{94A0}\x{94A1}\x{94A2}\x{94A3}\x{94A4}\x{94A5}\x{94A6}\x{94A7}'
. '\x{94A8}\x{94A9}\x{94AA}\x{94AB}\x{94AC}\x{94AD}\x{94AE}\x{94AF}\x{94B0}'
. '\x{94B1}\x{94B2}\x{94B3}\x{94B4}\x{94B5}\x{94B6}\x{94B7}\x{94B8}\x{94B9}'
. '\x{94BA}\x{94BB}\x{94BC}\x{94BD}\x{94BE}\x{94BF}\x{94C0}\x{94C1}\x{94C2}'
. '\x{94C3}\x{94C4}\x{94C5}\x{94C6}\x{94C7}\x{94C8}\x{94C9}\x{94CA}\x{94CB}'
. '\x{94CC}\x{94CD}\x{94CE}\x{94CF}\x{94D0}\x{94D1}\x{94D2}\x{94D3}\x{94D4}'
. '\x{94D5}\x{94D6}\x{94D7}\x{94D8}\x{94D9}\x{94DA}\x{94DB}\x{94DC}\x{94DD}'
. '\x{94DE}\x{94DF}\x{94E0}\x{94E1}\x{94E2}\x{94E3}\x{94E4}\x{94E5}\x{94E6}'
. '\x{94E7}\x{94E8}\x{94E9}\x{94EA}\x{94EB}\x{94EC}\x{94ED}\x{94EE}\x{94EF}'
. '\x{94F0}\x{94F1}\x{94F2}\x{94F3}\x{94F4}\x{94F5}\x{94F6}\x{94F7}\x{94F8}'
. '\x{94F9}\x{94FA}\x{94FB}\x{94FC}\x{94FD}\x{94FE}\x{94FF}\x{9500}\x{9501}'
. '\x{9502}\x{9503}\x{9504}\x{9505}\x{9506}\x{9507}\x{9508}\x{9509}\x{950A}'
. '\x{950B}\x{950C}\x{950D}\x{950E}\x{950F}\x{9510}\x{9511}\x{9512}\x{9513}'
. '\x{9514}\x{9515}\x{9516}\x{9517}\x{9518}\x{9519}\x{951A}\x{951B}\x{951C}'
. '\x{951D}\x{951E}\x{951F}\x{9520}\x{9521}\x{9522}\x{9523}\x{9524}\x{9525}'
. '\x{9526}\x{9527}\x{9528}\x{9529}\x{952A}\x{952B}\x{952C}\x{952D}\x{952E}'
. '\x{952F}\x{9530}\x{9531}\x{9532}\x{9533}\x{9534}\x{9535}\x{9536}\x{9537}'
. '\x{9538}\x{9539}\x{953A}\x{953B}\x{953C}\x{953D}\x{953E}\x{953F}\x{9540}'
. '\x{9541}\x{9542}\x{9543}\x{9544}\x{9545}\x{9546}\x{9547}\x{9548}\x{9549}'
. '\x{954A}\x{954B}\x{954C}\x{954D}\x{954E}\x{954F}\x{9550}\x{9551}\x{9552}'
. '\x{9553}\x{9554}\x{9555}\x{9556}\x{9557}\x{9558}\x{9559}\x{955A}\x{955B}'
. '\x{955C}\x{955D}\x{955E}\x{955F}\x{9560}\x{9561}\x{9562}\x{9563}\x{9564}'
. '\x{9565}\x{9566}\x{9567}\x{9568}\x{9569}\x{956A}\x{956B}\x{956C}\x{956D}'
. '\x{956E}\x{956F}\x{9570}\x{9571}\x{9572}\x{9573}\x{9574}\x{9575}\x{9576}'
. '\x{9577}\x{957A}\x{957B}\x{957C}\x{957D}\x{957F}\x{9580}\x{9581}\x{9582}'
. '\x{9583}\x{9584}\x{9586}\x{9587}\x{9588}\x{9589}\x{958A}\x{958B}\x{958C}'
. '\x{958D}\x{958E}\x{958F}\x{9590}\x{9591}\x{9592}\x{9593}\x{9594}\x{9595}'
. '\x{9596}\x{9598}\x{9599}\x{959A}\x{959B}\x{959C}\x{959D}\x{959E}\x{959F}'
. '\x{95A1}\x{95A2}\x{95A3}\x{95A4}\x{95A5}\x{95A6}\x{95A7}\x{95A8}\x{95A9}'
. '\x{95AA}\x{95AB}\x{95AC}\x{95AD}\x{95AE}\x{95AF}\x{95B0}\x{95B1}\x{95B2}'
. '\x{95B5}\x{95B6}\x{95B7}\x{95B9}\x{95BA}\x{95BB}\x{95BC}\x{95BD}\x{95BE}'
. '\x{95BF}\x{95C0}\x{95C2}\x{95C3}\x{95C4}\x{95C5}\x{95C6}\x{95C7}\x{95C8}'
. '\x{95C9}\x{95CA}\x{95CB}\x{95CC}\x{95CD}\x{95CE}\x{95CF}\x{95D0}\x{95D1}'
. '\x{95D2}\x{95D3}\x{95D4}\x{95D5}\x{95D6}\x{95D7}\x{95D8}\x{95DA}\x{95DB}'
. '\x{95DC}\x{95DE}\x{95DF}\x{95E0}\x{95E1}\x{95E2}\x{95E3}\x{95E4}\x{95E5}'
. '\x{95E6}\x{95E7}\x{95E8}\x{95E9}\x{95EA}\x{95EB}\x{95EC}\x{95ED}\x{95EE}'
. '\x{95EF}\x{95F0}\x{95F1}\x{95F2}\x{95F3}\x{95F4}\x{95F5}\x{95F6}\x{95F7}'
. '\x{95F8}\x{95F9}\x{95FA}\x{95FB}\x{95FC}\x{95FD}\x{95FE}\x{95FF}\x{9600}'
. '\x{9601}\x{9602}\x{9603}\x{9604}\x{9605}\x{9606}\x{9607}\x{9608}\x{9609}'
. '\x{960A}\x{960B}\x{960C}\x{960D}\x{960E}\x{960F}\x{9610}\x{9611}\x{9612}'
. '\x{9613}\x{9614}\x{9615}\x{9616}\x{9617}\x{9618}\x{9619}\x{961A}\x{961B}'
. '\x{961C}\x{961D}\x{961E}\x{961F}\x{9620}\x{9621}\x{9622}\x{9623}\x{9624}'
. '\x{9627}\x{9628}\x{962A}\x{962B}\x{962C}\x{962D}\x{962E}\x{962F}\x{9630}'
. '\x{9631}\x{9632}\x{9633}\x{9634}\x{9635}\x{9636}\x{9637}\x{9638}\x{9639}'
. '\x{963A}\x{963B}\x{963C}\x{963D}\x{963F}\x{9640}\x{9641}\x{9642}\x{9643}'
. '\x{9644}\x{9645}\x{9646}\x{9647}\x{9648}\x{9649}\x{964A}\x{964B}\x{964C}'
. '\x{964D}\x{964E}\x{964F}\x{9650}\x{9651}\x{9652}\x{9653}\x{9654}\x{9655}'
. '\x{9658}\x{9659}\x{965A}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9660}'
. '\x{9661}\x{9662}\x{9663}\x{9664}\x{9666}\x{9667}\x{9668}\x{9669}\x{966A}'
. '\x{966B}\x{966C}\x{966D}\x{966E}\x{966F}\x{9670}\x{9671}\x{9672}\x{9673}'
. '\x{9674}\x{9675}\x{9676}\x{9677}\x{9678}\x{967C}\x{967D}\x{967E}\x{9680}'
. '\x{9683}\x{9684}\x{9685}\x{9686}\x{9687}\x{9688}\x{9689}\x{968A}\x{968B}'
. '\x{968D}\x{968E}\x{968F}\x{9690}\x{9691}\x{9692}\x{9693}\x{9694}\x{9695}'
. '\x{9697}\x{9698}\x{9699}\x{969B}\x{969C}\x{969E}\x{96A0}\x{96A1}\x{96A2}'
. '\x{96A3}\x{96A4}\x{96A5}\x{96A6}\x{96A7}\x{96A8}\x{96A9}\x{96AA}\x{96AC}'
. '\x{96AD}\x{96AE}\x{96B0}\x{96B1}\x{96B3}\x{96B4}\x{96B6}\x{96B7}\x{96B8}'
. '\x{96B9}\x{96BA}\x{96BB}\x{96BC}\x{96BD}\x{96BE}\x{96BF}\x{96C0}\x{96C1}'
. '\x{96C2}\x{96C3}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C8}\x{96C9}\x{96CA}'
. '\x{96CB}\x{96CC}\x{96CD}\x{96CE}\x{96CF}\x{96D0}\x{96D1}\x{96D2}\x{96D3}'
. '\x{96D4}\x{96D5}\x{96D6}\x{96D7}\x{96D8}\x{96D9}\x{96DA}\x{96DB}\x{96DC}'
. '\x{96DD}\x{96DE}\x{96DF}\x{96E0}\x{96E1}\x{96E2}\x{96E3}\x{96E5}\x{96E8}'
. '\x{96E9}\x{96EA}\x{96EB}\x{96EC}\x{96ED}\x{96EE}\x{96EF}\x{96F0}\x{96F1}'
. '\x{96F2}\x{96F3}\x{96F4}\x{96F5}\x{96F6}\x{96F7}\x{96F8}\x{96F9}\x{96FA}'
. '\x{96FB}\x{96FD}\x{96FE}\x{96FF}\x{9700}\x{9701}\x{9702}\x{9703}\x{9704}'
. '\x{9705}\x{9706}\x{9707}\x{9708}\x{9709}\x{970A}\x{970B}\x{970C}\x{970D}'
. '\x{970E}\x{970F}\x{9710}\x{9711}\x{9712}\x{9713}\x{9715}\x{9716}\x{9718}'
. '\x{9719}\x{971C}\x{971D}\x{971E}\x{971F}\x{9720}\x{9721}\x{9722}\x{9723}'
. '\x{9724}\x{9725}\x{9726}\x{9727}\x{9728}\x{9729}\x{972A}\x{972B}\x{972C}'
. '\x{972D}\x{972E}\x{972F}\x{9730}\x{9731}\x{9732}\x{9735}\x{9736}\x{9738}'
. '\x{9739}\x{973A}\x{973B}\x{973C}\x{973D}\x{973E}\x{973F}\x{9742}\x{9743}'
. '\x{9744}\x{9745}\x{9746}\x{9747}\x{9748}\x{9749}\x{974A}\x{974B}\x{974C}'
. '\x{974E}\x{974F}\x{9750}\x{9751}\x{9752}\x{9753}\x{9754}\x{9755}\x{9756}'
. '\x{9758}\x{9759}\x{975A}\x{975B}\x{975C}\x{975D}\x{975E}\x{975F}\x{9760}'
. '\x{9761}\x{9762}\x{9765}\x{9766}\x{9767}\x{9768}\x{9769}\x{976A}\x{976B}'
. '\x{976C}\x{976D}\x{976E}\x{976F}\x{9770}\x{9772}\x{9773}\x{9774}\x{9776}'
. '\x{9777}\x{9778}\x{9779}\x{977A}\x{977B}\x{977C}\x{977D}\x{977E}\x{977F}'
. '\x{9780}\x{9781}\x{9782}\x{9783}\x{9784}\x{9785}\x{9786}\x{9788}\x{978A}'
. '\x{978B}\x{978C}\x{978D}\x{978E}\x{978F}\x{9790}\x{9791}\x{9792}\x{9793}'
. '\x{9794}\x{9795}\x{9796}\x{9797}\x{9798}\x{9799}\x{979A}\x{979C}\x{979D}'
. '\x{979E}\x{979F}\x{97A0}\x{97A1}\x{97A2}\x{97A3}\x{97A4}\x{97A5}\x{97A6}'
. '\x{97A7}\x{97A8}\x{97AA}\x{97AB}\x{97AC}\x{97AD}\x{97AE}\x{97AF}\x{97B2}'
. '\x{97B3}\x{97B4}\x{97B6}\x{97B7}\x{97B8}\x{97B9}\x{97BA}\x{97BB}\x{97BC}'
. '\x{97BD}\x{97BF}\x{97C1}\x{97C2}\x{97C3}\x{97C4}\x{97C5}\x{97C6}\x{97C7}'
. '\x{97C8}\x{97C9}\x{97CA}\x{97CB}\x{97CC}\x{97CD}\x{97CE}\x{97CF}\x{97D0}'
. '\x{97D1}\x{97D3}\x{97D4}\x{97D5}\x{97D6}\x{97D7}\x{97D8}\x{97D9}\x{97DA}'
. '\x{97DB}\x{97DC}\x{97DD}\x{97DE}\x{97DF}\x{97E0}\x{97E1}\x{97E2}\x{97E3}'
. '\x{97E4}\x{97E5}\x{97E6}\x{97E7}\x{97E8}\x{97E9}\x{97EA}\x{97EB}\x{97EC}'
. '\x{97ED}\x{97EE}\x{97EF}\x{97F0}\x{97F1}\x{97F2}\x{97F3}\x{97F4}\x{97F5}'
. '\x{97F6}\x{97F7}\x{97F8}\x{97F9}\x{97FA}\x{97FB}\x{97FD}\x{97FE}\x{97FF}'
. '\x{9800}\x{9801}\x{9802}\x{9803}\x{9804}\x{9805}\x{9806}\x{9807}\x{9808}'
. '\x{9809}\x{980A}\x{980B}\x{980C}\x{980D}\x{980E}\x{980F}\x{9810}\x{9811}'
. '\x{9812}\x{9813}\x{9814}\x{9815}\x{9816}\x{9817}\x{9818}\x{9819}\x{981A}'
. '\x{981B}\x{981C}\x{981D}\x{981E}\x{9820}\x{9821}\x{9822}\x{9823}\x{9824}'
. '\x{9826}\x{9827}\x{9828}\x{9829}\x{982B}\x{982D}\x{982E}\x{982F}\x{9830}'
. '\x{9831}\x{9832}\x{9834}\x{9835}\x{9836}\x{9837}\x{9838}\x{9839}\x{983B}'
. '\x{983C}\x{983D}\x{983F}\x{9840}\x{9841}\x{9843}\x{9844}\x{9845}\x{9846}'
. '\x{9848}\x{9849}\x{984A}\x{984C}\x{984D}\x{984E}\x{984F}\x{9850}\x{9851}'
. '\x{9852}\x{9853}\x{9854}\x{9855}\x{9857}\x{9858}\x{9859}\x{985A}\x{985B}'
. '\x{985C}\x{985D}\x{985E}\x{985F}\x{9860}\x{9861}\x{9862}\x{9863}\x{9864}'
. '\x{9865}\x{9867}\x{9869}\x{986A}\x{986B}\x{986C}\x{986D}\x{986E}\x{986F}'
. '\x{9870}\x{9871}\x{9872}\x{9873}\x{9874}\x{9875}\x{9876}\x{9877}\x{9878}'
. '\x{9879}\x{987A}\x{987B}\x{987C}\x{987D}\x{987E}\x{987F}\x{9880}\x{9881}'
. '\x{9882}\x{9883}\x{9884}\x{9885}\x{9886}\x{9887}\x{9888}\x{9889}\x{988A}'
. '\x{988B}\x{988C}\x{988D}\x{988E}\x{988F}\x{9890}\x{9891}\x{9892}\x{9893}'
. '\x{9894}\x{9895}\x{9896}\x{9897}\x{9898}\x{9899}\x{989A}\x{989B}\x{989C}'
. '\x{989D}\x{989E}\x{989F}\x{98A0}\x{98A1}\x{98A2}\x{98A3}\x{98A4}\x{98A5}'
. '\x{98A6}\x{98A7}\x{98A8}\x{98A9}\x{98AA}\x{98AB}\x{98AC}\x{98AD}\x{98AE}'
. '\x{98AF}\x{98B0}\x{98B1}\x{98B2}\x{98B3}\x{98B4}\x{98B5}\x{98B6}\x{98B8}'
. '\x{98B9}\x{98BA}\x{98BB}\x{98BC}\x{98BD}\x{98BE}\x{98BF}\x{98C0}\x{98C1}'
. '\x{98C2}\x{98C3}\x{98C4}\x{98C5}\x{98C6}\x{98C8}\x{98C9}\x{98CB}\x{98CC}'
. '\x{98CD}\x{98CE}\x{98CF}\x{98D0}\x{98D1}\x{98D2}\x{98D3}\x{98D4}\x{98D5}'
. '\x{98D6}\x{98D7}\x{98D8}\x{98D9}\x{98DA}\x{98DB}\x{98DC}\x{98DD}\x{98DE}'
. '\x{98DF}\x{98E0}\x{98E2}\x{98E3}\x{98E5}\x{98E6}\x{98E7}\x{98E8}\x{98E9}'
. '\x{98EA}\x{98EB}\x{98ED}\x{98EF}\x{98F0}\x{98F2}\x{98F3}\x{98F4}\x{98F5}'
. '\x{98F6}\x{98F7}\x{98F9}\x{98FA}\x{98FC}\x{98FD}\x{98FE}\x{98FF}\x{9900}'
. '\x{9901}\x{9902}\x{9903}\x{9904}\x{9905}\x{9906}\x{9907}\x{9908}\x{9909}'
. '\x{990A}\x{990B}\x{990C}\x{990D}\x{990E}\x{990F}\x{9910}\x{9911}\x{9912}'
. '\x{9913}\x{9914}\x{9915}\x{9916}\x{9917}\x{9918}\x{991A}\x{991B}\x{991C}'
. '\x{991D}\x{991E}\x{991F}\x{9920}\x{9921}\x{9922}\x{9923}\x{9924}\x{9925}'
. '\x{9926}\x{9927}\x{9928}\x{9929}\x{992A}\x{992B}\x{992C}\x{992D}\x{992E}'
. '\x{992F}\x{9930}\x{9931}\x{9932}\x{9933}\x{9934}\x{9935}\x{9936}\x{9937}'
. '\x{9938}\x{9939}\x{993A}\x{993C}\x{993D}\x{993E}\x{993F}\x{9940}\x{9941}'
. '\x{9942}\x{9943}\x{9945}\x{9946}\x{9947}\x{9948}\x{9949}\x{994A}\x{994B}'
. '\x{994C}\x{994E}\x{994F}\x{9950}\x{9951}\x{9952}\x{9953}\x{9954}\x{9955}'
. '\x{9956}\x{9957}\x{9958}\x{9959}\x{995B}\x{995C}\x{995E}\x{995F}\x{9960}'
. '\x{9961}\x{9962}\x{9963}\x{9964}\x{9965}\x{9966}\x{9967}\x{9968}\x{9969}'
. '\x{996A}\x{996B}\x{996C}\x{996D}\x{996E}\x{996F}\x{9970}\x{9971}\x{9972}'
. '\x{9973}\x{9974}\x{9975}\x{9976}\x{9977}\x{9978}\x{9979}\x{997A}\x{997B}'
. '\x{997C}\x{997D}\x{997E}\x{997F}\x{9980}\x{9981}\x{9982}\x{9983}\x{9984}'
. '\x{9985}\x{9986}\x{9987}\x{9988}\x{9989}\x{998A}\x{998B}\x{998C}\x{998D}'
. '\x{998E}\x{998F}\x{9990}\x{9991}\x{9992}\x{9993}\x{9994}\x{9995}\x{9996}'
. '\x{9997}\x{9998}\x{9999}\x{999A}\x{999B}\x{999C}\x{999D}\x{999E}\x{999F}'
. '\x{99A0}\x{99A1}\x{99A2}\x{99A3}\x{99A4}\x{99A5}\x{99A6}\x{99A7}\x{99A8}'
. '\x{99A9}\x{99AA}\x{99AB}\x{99AC}\x{99AD}\x{99AE}\x{99AF}\x{99B0}\x{99B1}'
. '\x{99B2}\x{99B3}\x{99B4}\x{99B5}\x{99B6}\x{99B7}\x{99B8}\x{99B9}\x{99BA}'
. '\x{99BB}\x{99BC}\x{99BD}\x{99BE}\x{99C0}\x{99C1}\x{99C2}\x{99C3}\x{99C4}'
. '\x{99C6}\x{99C7}\x{99C8}\x{99C9}\x{99CA}\x{99CB}\x{99CC}\x{99CD}\x{99CE}'
. '\x{99CF}\x{99D0}\x{99D1}\x{99D2}\x{99D3}\x{99D4}\x{99D5}\x{99D6}\x{99D7}'
. '\x{99D8}\x{99D9}\x{99DA}\x{99DB}\x{99DC}\x{99DD}\x{99DE}\x{99DF}\x{99E1}'
. '\x{99E2}\x{99E3}\x{99E4}\x{99E5}\x{99E7}\x{99E8}\x{99E9}\x{99EA}\x{99EC}'
. '\x{99ED}\x{99EE}\x{99EF}\x{99F0}\x{99F1}\x{99F2}\x{99F3}\x{99F4}\x{99F6}'
. '\x{99F7}\x{99F8}\x{99F9}\x{99FA}\x{99FB}\x{99FC}\x{99FD}\x{99FE}\x{99FF}'
. '\x{9A00}\x{9A01}\x{9A02}\x{9A03}\x{9A04}\x{9A05}\x{9A06}\x{9A07}\x{9A08}'
. '\x{9A09}\x{9A0A}\x{9A0B}\x{9A0C}\x{9A0D}\x{9A0E}\x{9A0F}\x{9A11}\x{9A14}'
. '\x{9A15}\x{9A16}\x{9A19}\x{9A1A}\x{9A1B}\x{9A1C}\x{9A1D}\x{9A1E}\x{9A1F}'
. '\x{9A20}\x{9A21}\x{9A22}\x{9A23}\x{9A24}\x{9A25}\x{9A26}\x{9A27}\x{9A29}'
. '\x{9A2A}\x{9A2B}\x{9A2C}\x{9A2D}\x{9A2E}\x{9A2F}\x{9A30}\x{9A31}\x{9A32}'
. '\x{9A33}\x{9A34}\x{9A35}\x{9A36}\x{9A37}\x{9A38}\x{9A39}\x{9A3A}\x{9A3C}'
. '\x{9A3D}\x{9A3E}\x{9A3F}\x{9A40}\x{9A41}\x{9A42}\x{9A43}\x{9A44}\x{9A45}'
. '\x{9A46}\x{9A47}\x{9A48}\x{9A49}\x{9A4A}\x{9A4B}\x{9A4C}\x{9A4D}\x{9A4E}'
. '\x{9A4F}\x{9A50}\x{9A52}\x{9A53}\x{9A54}\x{9A55}\x{9A56}\x{9A57}\x{9A59}'
. '\x{9A5A}\x{9A5B}\x{9A5C}\x{9A5E}\x{9A5F}\x{9A60}\x{9A61}\x{9A62}\x{9A64}'
. '\x{9A65}\x{9A66}\x{9A67}\x{9A68}\x{9A69}\x{9A6A}\x{9A6B}\x{9A6C}\x{9A6D}'
. '\x{9A6E}\x{9A6F}\x{9A70}\x{9A71}\x{9A72}\x{9A73}\x{9A74}\x{9A75}\x{9A76}'
. '\x{9A77}\x{9A78}\x{9A79}\x{9A7A}\x{9A7B}\x{9A7C}\x{9A7D}\x{9A7E}\x{9A7F}'
. '\x{9A80}\x{9A81}\x{9A82}\x{9A83}\x{9A84}\x{9A85}\x{9A86}\x{9A87}\x{9A88}'
. '\x{9A89}\x{9A8A}\x{9A8B}\x{9A8C}\x{9A8D}\x{9A8E}\x{9A8F}\x{9A90}\x{9A91}'
. '\x{9A92}\x{9A93}\x{9A94}\x{9A95}\x{9A96}\x{9A97}\x{9A98}\x{9A99}\x{9A9A}'
. '\x{9A9B}\x{9A9C}\x{9A9D}\x{9A9E}\x{9A9F}\x{9AA0}\x{9AA1}\x{9AA2}\x{9AA3}'
. '\x{9AA4}\x{9AA5}\x{9AA6}\x{9AA7}\x{9AA8}\x{9AAA}\x{9AAB}\x{9AAC}\x{9AAD}'
. '\x{9AAE}\x{9AAF}\x{9AB0}\x{9AB1}\x{9AB2}\x{9AB3}\x{9AB4}\x{9AB5}\x{9AB6}'
. '\x{9AB7}\x{9AB8}\x{9AB9}\x{9ABA}\x{9ABB}\x{9ABC}\x{9ABE}\x{9ABF}\x{9AC0}'
. '\x{9AC1}\x{9AC2}\x{9AC3}\x{9AC4}\x{9AC5}\x{9AC6}\x{9AC7}\x{9AC9}\x{9ACA}'
. '\x{9ACB}\x{9ACC}\x{9ACD}\x{9ACE}\x{9ACF}\x{9AD0}\x{9AD1}\x{9AD2}\x{9AD3}'
. '\x{9AD4}\x{9AD5}\x{9AD6}\x{9AD8}\x{9AD9}\x{9ADA}\x{9ADB}\x{9ADC}\x{9ADD}'
. '\x{9ADE}\x{9ADF}\x{9AE1}\x{9AE2}\x{9AE3}\x{9AE5}\x{9AE6}\x{9AE7}\x{9AEA}'
. '\x{9AEB}\x{9AEC}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF2}\x{9AF3}\x{9AF4}'
. '\x{9AF5}\x{9AF6}\x{9AF7}\x{9AF8}\x{9AF9}\x{9AFA}\x{9AFB}\x{9AFC}\x{9AFD}'
. '\x{9AFE}\x{9AFF}\x{9B01}\x{9B03}\x{9B04}\x{9B05}\x{9B06}\x{9B07}\x{9B08}'
. '\x{9B0A}\x{9B0B}\x{9B0C}\x{9B0D}\x{9B0E}\x{9B0F}\x{9B10}\x{9B11}\x{9B12}'
. '\x{9B13}\x{9B15}\x{9B16}\x{9B17}\x{9B18}\x{9B19}\x{9B1A}\x{9B1C}\x{9B1D}'
. '\x{9B1E}\x{9B1F}\x{9B20}\x{9B21}\x{9B22}\x{9B23}\x{9B24}\x{9B25}\x{9B26}'
. '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2B}\x{9B2C}\x{9B2D}\x{9B2E}\x{9B2F}'
. '\x{9B30}\x{9B31}\x{9B32}\x{9B33}\x{9B35}\x{9B36}\x{9B37}\x{9B38}\x{9B39}'
. '\x{9B3A}\x{9B3B}\x{9B3C}\x{9B3E}\x{9B3F}\x{9B41}\x{9B42}\x{9B43}\x{9B44}'
. '\x{9B45}\x{9B46}\x{9B47}\x{9B48}\x{9B49}\x{9B4A}\x{9B4B}\x{9B4C}\x{9B4D}'
. '\x{9B4E}\x{9B4F}\x{9B51}\x{9B52}\x{9B53}\x{9B54}\x{9B55}\x{9B56}\x{9B58}'
. '\x{9B59}\x{9B5A}\x{9B5B}\x{9B5C}\x{9B5D}\x{9B5E}\x{9B5F}\x{9B60}\x{9B61}'
. '\x{9B63}\x{9B64}\x{9B65}\x{9B66}\x{9B67}\x{9B68}\x{9B69}\x{9B6A}\x{9B6B}'
. '\x{9B6C}\x{9B6D}\x{9B6E}\x{9B6F}\x{9B70}\x{9B71}\x{9B73}\x{9B74}\x{9B75}'
. '\x{9B76}\x{9B77}\x{9B78}\x{9B79}\x{9B7A}\x{9B7B}\x{9B7C}\x{9B7D}\x{9B7E}'
. '\x{9B7F}\x{9B80}\x{9B81}\x{9B82}\x{9B83}\x{9B84}\x{9B85}\x{9B86}\x{9B87}'
. '\x{9B88}\x{9B8A}\x{9B8B}\x{9B8D}\x{9B8E}\x{9B8F}\x{9B90}\x{9B91}\x{9B92}'
. '\x{9B93}\x{9B94}\x{9B95}\x{9B96}\x{9B97}\x{9B98}\x{9B9A}\x{9B9B}\x{9B9C}'
. '\x{9B9D}\x{9B9E}\x{9B9F}\x{9BA0}\x{9BA1}\x{9BA2}\x{9BA3}\x{9BA4}\x{9BA5}'
. '\x{9BA6}\x{9BA7}\x{9BA8}\x{9BA9}\x{9BAA}\x{9BAB}\x{9BAC}\x{9BAD}\x{9BAE}'
. '\x{9BAF}\x{9BB0}\x{9BB1}\x{9BB2}\x{9BB3}\x{9BB4}\x{9BB5}\x{9BB6}\x{9BB7}'
. '\x{9BB8}\x{9BB9}\x{9BBA}\x{9BBB}\x{9BBC}\x{9BBD}\x{9BBE}\x{9BBF}\x{9BC0}'
. '\x{9BC1}\x{9BC3}\x{9BC4}\x{9BC5}\x{9BC6}\x{9BC7}\x{9BC8}\x{9BC9}\x{9BCA}'
. '\x{9BCB}\x{9BCC}\x{9BCD}\x{9BCE}\x{9BCF}\x{9BD0}\x{9BD1}\x{9BD2}\x{9BD3}'
. '\x{9BD4}\x{9BD5}\x{9BD6}\x{9BD7}\x{9BD8}\x{9BD9}\x{9BDA}\x{9BDB}\x{9BDC}'
. '\x{9BDD}\x{9BDE}\x{9BDF}\x{9BE0}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}\x{9BE5}'
. '\x{9BE6}\x{9BE7}\x{9BE8}\x{9BE9}\x{9BEA}\x{9BEB}\x{9BEC}\x{9BED}\x{9BEE}'
. '\x{9BEF}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF3}\x{9BF4}\x{9BF5}\x{9BF7}\x{9BF8}'
. '\x{9BF9}\x{9BFA}\x{9BFB}\x{9BFC}\x{9BFD}\x{9BFE}\x{9BFF}\x{9C02}\x{9C05}'
. '\x{9C06}\x{9C07}\x{9C08}\x{9C09}\x{9C0A}\x{9C0B}\x{9C0C}\x{9C0D}\x{9C0E}'
. '\x{9C0F}\x{9C10}\x{9C11}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C16}\x{9C17}'
. '\x{9C18}\x{9C19}\x{9C1A}\x{9C1B}\x{9C1C}\x{9C1D}\x{9C1E}\x{9C1F}\x{9C20}'
. '\x{9C21}\x{9C22}\x{9C23}\x{9C24}\x{9C25}\x{9C26}\x{9C27}\x{9C28}\x{9C29}'
. '\x{9C2A}\x{9C2B}\x{9C2C}\x{9C2D}\x{9C2F}\x{9C30}\x{9C31}\x{9C32}\x{9C33}'
. '\x{9C34}\x{9C35}\x{9C36}\x{9C37}\x{9C38}\x{9C39}\x{9C3A}\x{9C3B}\x{9C3C}'
. '\x{9C3D}\x{9C3E}\x{9C3F}\x{9C40}\x{9C41}\x{9C43}\x{9C44}\x{9C45}\x{9C46}'
. '\x{9C47}\x{9C48}\x{9C49}\x{9C4A}\x{9C4B}\x{9C4C}\x{9C4D}\x{9C4E}\x{9C50}'
. '\x{9C52}\x{9C53}\x{9C54}\x{9C55}\x{9C56}\x{9C57}\x{9C58}\x{9C59}\x{9C5A}'
. '\x{9C5B}\x{9C5C}\x{9C5D}\x{9C5E}\x{9C5F}\x{9C60}\x{9C62}\x{9C63}\x{9C65}'
. '\x{9C66}\x{9C67}\x{9C68}\x{9C69}\x{9C6A}\x{9C6B}\x{9C6C}\x{9C6D}\x{9C6E}'
. '\x{9C6F}\x{9C70}\x{9C71}\x{9C72}\x{9C73}\x{9C74}\x{9C75}\x{9C77}\x{9C78}'
. '\x{9C79}\x{9C7A}\x{9C7C}\x{9C7D}\x{9C7E}\x{9C7F}\x{9C80}\x{9C81}\x{9C82}'
. '\x{9C83}\x{9C84}\x{9C85}\x{9C86}\x{9C87}\x{9C88}\x{9C89}\x{9C8A}\x{9C8B}'
. '\x{9C8C}\x{9C8D}\x{9C8E}\x{9C8F}\x{9C90}\x{9C91}\x{9C92}\x{9C93}\x{9C94}'
. '\x{9C95}\x{9C96}\x{9C97}\x{9C98}\x{9C99}\x{9C9A}\x{9C9B}\x{9C9C}\x{9C9D}'
. '\x{9C9E}\x{9C9F}\x{9CA0}\x{9CA1}\x{9CA2}\x{9CA3}\x{9CA4}\x{9CA5}\x{9CA6}'
. '\x{9CA7}\x{9CA8}\x{9CA9}\x{9CAA}\x{9CAB}\x{9CAC}\x{9CAD}\x{9CAE}\x{9CAF}'
. '\x{9CB0}\x{9CB1}\x{9CB2}\x{9CB3}\x{9CB4}\x{9CB5}\x{9CB6}\x{9CB7}\x{9CB8}'
. '\x{9CB9}\x{9CBA}\x{9CBB}\x{9CBC}\x{9CBD}\x{9CBE}\x{9CBF}\x{9CC0}\x{9CC1}'
. '\x{9CC2}\x{9CC3}\x{9CC4}\x{9CC5}\x{9CC6}\x{9CC7}\x{9CC8}\x{9CC9}\x{9CCA}'
. '\x{9CCB}\x{9CCC}\x{9CCD}\x{9CCE}\x{9CCF}\x{9CD0}\x{9CD1}\x{9CD2}\x{9CD3}'
. '\x{9CD4}\x{9CD5}\x{9CD6}\x{9CD7}\x{9CD8}\x{9CD9}\x{9CDA}\x{9CDB}\x{9CDC}'
. '\x{9CDD}\x{9CDE}\x{9CDF}\x{9CE0}\x{9CE1}\x{9CE2}\x{9CE3}\x{9CE4}\x{9CE5}'
. '\x{9CE6}\x{9CE7}\x{9CE8}\x{9CE9}\x{9CEA}\x{9CEB}\x{9CEC}\x{9CED}\x{9CEE}'
. '\x{9CEF}\x{9CF0}\x{9CF1}\x{9CF2}\x{9CF3}\x{9CF4}\x{9CF5}\x{9CF6}\x{9CF7}'
. '\x{9CF8}\x{9CF9}\x{9CFA}\x{9CFB}\x{9CFC}\x{9CFD}\x{9CFE}\x{9CFF}\x{9D00}'
. '\x{9D01}\x{9D02}\x{9D03}\x{9D04}\x{9D05}\x{9D06}\x{9D07}\x{9D08}\x{9D09}'
. '\x{9D0A}\x{9D0B}\x{9D0F}\x{9D10}\x{9D12}\x{9D13}\x{9D14}\x{9D15}\x{9D16}'
. '\x{9D17}\x{9D18}\x{9D19}\x{9D1A}\x{9D1B}\x{9D1C}\x{9D1D}\x{9D1E}\x{9D1F}'
. '\x{9D20}\x{9D21}\x{9D22}\x{9D23}\x{9D24}\x{9D25}\x{9D26}\x{9D28}\x{9D29}'
. '\x{9D2B}\x{9D2D}\x{9D2E}\x{9D2F}\x{9D30}\x{9D31}\x{9D32}\x{9D33}\x{9D34}'
. '\x{9D36}\x{9D37}\x{9D38}\x{9D39}\x{9D3A}\x{9D3B}\x{9D3D}\x{9D3E}\x{9D3F}'
. '\x{9D40}\x{9D41}\x{9D42}\x{9D43}\x{9D45}\x{9D46}\x{9D47}\x{9D48}\x{9D49}'
. '\x{9D4A}\x{9D4B}\x{9D4C}\x{9D4D}\x{9D4E}\x{9D4F}\x{9D50}\x{9D51}\x{9D52}'
. '\x{9D53}\x{9D54}\x{9D55}\x{9D56}\x{9D57}\x{9D58}\x{9D59}\x{9D5A}\x{9D5B}'
. '\x{9D5C}\x{9D5D}\x{9D5E}\x{9D5F}\x{9D60}\x{9D61}\x{9D62}\x{9D63}\x{9D64}'
. '\x{9D65}\x{9D66}\x{9D67}\x{9D68}\x{9D69}\x{9D6A}\x{9D6B}\x{9D6C}\x{9D6E}'
. '\x{9D6F}\x{9D70}\x{9D71}\x{9D72}\x{9D73}\x{9D74}\x{9D75}\x{9D76}\x{9D77}'
. '\x{9D78}\x{9D79}\x{9D7A}\x{9D7B}\x{9D7C}\x{9D7D}\x{9D7E}\x{9D7F}\x{9D80}'
. '\x{9D81}\x{9D82}\x{9D83}\x{9D84}\x{9D85}\x{9D86}\x{9D87}\x{9D88}\x{9D89}'
. '\x{9D8A}\x{9D8B}\x{9D8C}\x{9D8D}\x{9D8E}\x{9D90}\x{9D91}\x{9D92}\x{9D93}'
. '\x{9D94}\x{9D96}\x{9D97}\x{9D98}\x{9D99}\x{9D9A}\x{9D9B}\x{9D9C}\x{9D9D}'
. '\x{9D9E}\x{9D9F}\x{9DA0}\x{9DA1}\x{9DA2}\x{9DA3}\x{9DA4}\x{9DA5}\x{9DA6}'
. '\x{9DA7}\x{9DA8}\x{9DA9}\x{9DAA}\x{9DAB}\x{9DAC}\x{9DAD}\x{9DAF}\x{9DB0}'
. '\x{9DB1}\x{9DB2}\x{9DB3}\x{9DB4}\x{9DB5}\x{9DB6}\x{9DB7}\x{9DB8}\x{9DB9}'
. '\x{9DBA}\x{9DBB}\x{9DBC}\x{9DBE}\x{9DBF}\x{9DC1}\x{9DC2}\x{9DC3}\x{9DC4}'
. '\x{9DC5}\x{9DC7}\x{9DC8}\x{9DC9}\x{9DCA}\x{9DCB}\x{9DCC}\x{9DCD}\x{9DCE}'
. '\x{9DCF}\x{9DD0}\x{9DD1}\x{9DD2}\x{9DD3}\x{9DD4}\x{9DD5}\x{9DD6}\x{9DD7}'
. '\x{9DD8}\x{9DD9}\x{9DDA}\x{9DDB}\x{9DDC}\x{9DDD}\x{9DDE}\x{9DDF}\x{9DE0}'
. '\x{9DE1}\x{9DE2}\x{9DE3}\x{9DE4}\x{9DE5}\x{9DE6}\x{9DE7}\x{9DE8}\x{9DE9}'
. '\x{9DEB}\x{9DEC}\x{9DED}\x{9DEE}\x{9DEF}\x{9DF0}\x{9DF1}\x{9DF2}\x{9DF3}'
. '\x{9DF4}\x{9DF5}\x{9DF6}\x{9DF7}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFB}\x{9DFD}'
. '\x{9DFE}\x{9DFF}\x{9E00}\x{9E01}\x{9E02}\x{9E03}\x{9E04}\x{9E05}\x{9E06}'
. '\x{9E07}\x{9E08}\x{9E09}\x{9E0A}\x{9E0B}\x{9E0C}\x{9E0D}\x{9E0F}\x{9E10}'
. '\x{9E11}\x{9E12}\x{9E13}\x{9E14}\x{9E15}\x{9E17}\x{9E18}\x{9E19}\x{9E1A}'
. '\x{9E1B}\x{9E1D}\x{9E1E}\x{9E1F}\x{9E20}\x{9E21}\x{9E22}\x{9E23}\x{9E24}'
. '\x{9E25}\x{9E26}\x{9E27}\x{9E28}\x{9E29}\x{9E2A}\x{9E2B}\x{9E2C}\x{9E2D}'
. '\x{9E2E}\x{9E2F}\x{9E30}\x{9E31}\x{9E32}\x{9E33}\x{9E34}\x{9E35}\x{9E36}'
. '\x{9E37}\x{9E38}\x{9E39}\x{9E3A}\x{9E3B}\x{9E3C}\x{9E3D}\x{9E3E}\x{9E3F}'
. '\x{9E40}\x{9E41}\x{9E42}\x{9E43}\x{9E44}\x{9E45}\x{9E46}\x{9E47}\x{9E48}'
. '\x{9E49}\x{9E4A}\x{9E4B}\x{9E4C}\x{9E4D}\x{9E4E}\x{9E4F}\x{9E50}\x{9E51}'
. '\x{9E52}\x{9E53}\x{9E54}\x{9E55}\x{9E56}\x{9E57}\x{9E58}\x{9E59}\x{9E5A}'
. '\x{9E5B}\x{9E5C}\x{9E5D}\x{9E5E}\x{9E5F}\x{9E60}\x{9E61}\x{9E62}\x{9E63}'
. '\x{9E64}\x{9E65}\x{9E66}\x{9E67}\x{9E68}\x{9E69}\x{9E6A}\x{9E6B}\x{9E6C}'
. '\x{9E6D}\x{9E6E}\x{9E6F}\x{9E70}\x{9E71}\x{9E72}\x{9E73}\x{9E74}\x{9E75}'
. '\x{9E76}\x{9E77}\x{9E79}\x{9E7A}\x{9E7C}\x{9E7D}\x{9E7E}\x{9E7F}\x{9E80}'
. '\x{9E81}\x{9E82}\x{9E83}\x{9E84}\x{9E85}\x{9E86}\x{9E87}\x{9E88}\x{9E89}'
. '\x{9E8A}\x{9E8B}\x{9E8C}\x{9E8D}\x{9E8E}\x{9E91}\x{9E92}\x{9E93}\x{9E94}'
. '\x{9E96}\x{9E97}\x{9E99}\x{9E9A}\x{9E9B}\x{9E9C}\x{9E9D}\x{9E9F}\x{9EA0}'
. '\x{9EA1}\x{9EA3}\x{9EA4}\x{9EA5}\x{9EA6}\x{9EA7}\x{9EA8}\x{9EA9}\x{9EAA}'
. '\x{9EAD}\x{9EAE}\x{9EAF}\x{9EB0}\x{9EB2}\x{9EB3}\x{9EB4}\x{9EB5}\x{9EB6}'
. '\x{9EB7}\x{9EB8}\x{9EBB}\x{9EBC}\x{9EBD}\x{9EBE}\x{9EBF}\x{9EC0}\x{9EC1}'
. '\x{9EC2}\x{9EC3}\x{9EC4}\x{9EC5}\x{9EC6}\x{9EC7}\x{9EC8}\x{9EC9}\x{9ECA}'
. '\x{9ECB}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED1}\x{9ED2}\x{9ED3}'
. '\x{9ED4}\x{9ED5}\x{9ED6}\x{9ED7}\x{9ED8}\x{9ED9}\x{9EDA}\x{9EDB}\x{9EDC}'
. '\x{9EDD}\x{9EDE}\x{9EDF}\x{9EE0}\x{9EE1}\x{9EE2}\x{9EE3}\x{9EE4}\x{9EE5}'
. '\x{9EE6}\x{9EE7}\x{9EE8}\x{9EE9}\x{9EEA}\x{9EEB}\x{9EED}\x{9EEE}\x{9EEF}'
. '\x{9EF0}\x{9EF2}\x{9EF3}\x{9EF4}\x{9EF5}\x{9EF6}\x{9EF7}\x{9EF8}\x{9EF9}'
. '\x{9EFA}\x{9EFB}\x{9EFC}\x{9EFD}\x{9EFE}\x{9EFF}\x{9F00}\x{9F01}\x{9F02}'
. '\x{9F04}\x{9F05}\x{9F06}\x{9F07}\x{9F08}\x{9F09}\x{9F0A}\x{9F0B}\x{9F0C}'
. '\x{9F0D}\x{9F0E}\x{9F0F}\x{9F10}\x{9F12}\x{9F13}\x{9F15}\x{9F16}\x{9F17}'
. '\x{9F18}\x{9F19}\x{9F1A}\x{9F1B}\x{9F1C}\x{9F1D}\x{9F1E}\x{9F1F}\x{9F20}'
. '\x{9F22}\x{9F23}\x{9F24}\x{9F25}\x{9F27}\x{9F28}\x{9F29}\x{9F2A}\x{9F2B}'
. '\x{9F2C}\x{9F2D}\x{9F2E}\x{9F2F}\x{9F30}\x{9F31}\x{9F32}\x{9F33}\x{9F34}'
. '\x{9F35}\x{9F36}\x{9F37}\x{9F38}\x{9F39}\x{9F3A}\x{9F3B}\x{9F3C}\x{9F3D}'
. '\x{9F3E}\x{9F3F}\x{9F40}\x{9F41}\x{9F42}\x{9F43}\x{9F44}\x{9F46}\x{9F47}'
. '\x{9F48}\x{9F49}\x{9F4A}\x{9F4B}\x{9F4C}\x{9F4D}\x{9F4E}\x{9F4F}\x{9F50}'
. '\x{9F51}\x{9F52}\x{9F54}\x{9F55}\x{9F56}\x{9F57}\x{9F58}\x{9F59}\x{9F5A}'
. '\x{9F5B}\x{9F5C}\x{9F5D}\x{9F5E}\x{9F5F}\x{9F60}\x{9F61}\x{9F63}\x{9F64}'
. '\x{9F65}\x{9F66}\x{9F67}\x{9F68}\x{9F69}\x{9F6A}\x{9F6B}\x{9F6C}\x{9F6E}'
. '\x{9F6F}\x{9F70}\x{9F71}\x{9F72}\x{9F73}\x{9F74}\x{9F75}\x{9F76}\x{9F77}'
. '\x{9F78}\x{9F79}\x{9F7A}\x{9F7B}\x{9F7C}\x{9F7D}\x{9F7E}\x{9F7F}\x{9F80}'
. '\x{9F81}\x{9F82}\x{9F83}\x{9F84}\x{9F85}\x{9F86}\x{9F87}\x{9F88}\x{9F89}'
. '\x{9F8A}\x{9F8B}\x{9F8C}\x{9F8D}\x{9F8E}\x{9F8F}\x{9F90}\x{9F91}\x{9F92}'
. '\x{9F93}\x{9F94}\x{9F95}\x{9F96}\x{9F97}\x{9F98}\x{9F99}\x{9F9A}\x{9F9B}'
. '\x{9F9C}\x{9F9D}\x{9F9E}\x{9F9F}\x{9FA0}\x{9FA2}\x{9FA4}\x{9FA5}]{1,20}$/iu',
];
laminas-validator/src/Hostname/Com.php 0000644 00000031037 15240152635 0013756 0 ustar 00 <?php // phpcs:disable PSR12.Files.FileHeader.IncorrectOrder,WebimpressCodingStandard.Arrays.DoubleArrow.SpacesBefore
namespace Laminas\Validator\Hostname;
/**
* Resource file for com and net idn validation
*/
return [
1 => '/^[\x{002d}0-9\x{0400}-\x{052f}]{1,63}$/iu',
2 => '/^[\x{002d}0-9\x{0370}-\x{03ff}]{1,63}$/iu',
3 => '/^[\x{002d}0-9a-z\x{ac00}-\x{d7a3}]{1,17}$/iu',
// @codingStandardsIgnoreStart
4 => '/^[\x{002d}0-9a-z·à-öø-ÿāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĸĺļľłńņňŋōŏőœŕŗřśŝşšţťŧũūŭůűųŵŷźżž]{1,63}$/iu',
// @codingStandardsIgnoreEnd
5 => '/^[\x{002d}0-9A-Za-z\x{3400}-\x{3401}\x{3404}-\x{3406}\x{340C}\x{3416}\x{341C}'
. '\x{3421}\x{3424}\x{3428}-\x{3429}\x{342B}-\x{342E}\x{3430}-\x{3434}\x{3436}'
. '\x{3438}-\x{343C}\x{343E}\x{3441}-\x{3445}\x{3447}\x{3449}-\x{3451}\x{3453}'
. '\x{3457}-\x{345F}\x{3463}-\x{3467}\x{346E}-\x{3471}\x{3473}-\x{3477}\x{3479}-\x{348E}\x{3491}-\x{3497}'
. '\x{3499}-\x{34A1}\x{34A4}-\x{34AD}\x{34AF}-\x{34B0}\x{34B2}-\x{34BF}\x{34C2}-\x{34C5}\x{34C7}-\x{34CC}'
. '\x{34CE}-\x{34D1}\x{34D3}-\x{34D8}\x{34DA}-\x{34E4}\x{34E7}-\x{34E9}\x{34EC}-\x{34EF}\x{34F1}-\x{34FE}'
. '\x{3500}-\x{3507}\x{350A}-\x{3513}\x{3515}\x{3517}-\x{351A}\x{351C}-\x{351E}\x{3520}-\x{352A}'
. '\x{352C}-\x{3552}\x{3554}-\x{355C}\x{355E}-\x{3567}\x{3569}-\x{3573}\x{3575}-\x{357C}\x{3580}-\x{3588}'
. '\x{358F}-\x{3598}\x{359E}-\x{35AB}\x{35B4}-\x{35CD}\x{35D0}\x{35D3}-\x{35DC}\x{35E2}-\x{35ED}'
. '\x{35F0}-\x{35F6}\x{35FB}-\x{3602}\x{3605}-\x{360E}\x{3610}-\x{3611}\x{3613}-\x{3616}\x{3619}-\x{362D}'
. '\x{362F}-\x{3634}\x{3636}-\x{363B}\x{363F}-\x{3645}\x{3647}-\x{364B}\x{364D}-\x{3653}\x{3655}'
. '\x{3659}-\x{365E}\x{3660}-\x{3665}\x{3667}-\x{367C}\x{367E}\x{3680}-\x{3685}\x{3687}'
. '\x{3689}-\x{3690}\x{3692}-\x{3698}\x{369A}\x{369C}-\x{36AE}\x{36B0}-\x{36BF}\x{36C1}-\x{36C5}'
. '\x{36C9}-\x{36CA}\x{36CD}-\x{36DE}\x{36E1}-\x{36E2}\x{36E5}-\x{36FE}\x{3701}-\x{3713}\x{3715}-\x{371E}'
. '\x{3720}-\x{372C}\x{372E}-\x{3745}\x{3747}-\x{3748}\x{374A}\x{374C}-\x{3759}\x{375B}-\x{3760}'
. '\x{3762}-\x{3767}\x{3769}-\x{3772}\x{3774}-\x{378C}\x{378F}-\x{379C}\x{379F}\x{37A1}-\x{37AD}'
. '\x{37AF}-\x{37B7}\x{37B9}-\x{37C1}\x{37C3}-\x{37C5}\x{37C7}-\x{37D4}\x{37D6}-\x{37E0}\x{37E2}'
. '\x{37E5}-\x{37ED}\x{37EF}-\x{37F6}\x{37F8}-\x{3802}\x{3804}-\x{381D}\x{3820}-\x{3822}\x{3825}-\x{382A}'
. '\x{382D}-\x{382F}\x{3831}-\x{3832}\x{3834}-\x{384C}\x{384E}-\x{3860}\x{3862}-\x{3863}\x{3865}-\x{386B}'
. '\x{386D}-\x{3886}\x{3888}-\x{38A1}\x{38A3}\x{38A5}-\x{38AA}\x{38AC}\x{38AE}-\x{38B0}'
. '\x{38B2}-\x{38B6}\x{38B8}\x{38BA}-\x{38BE}\x{38C0}-\x{38C9}\x{38CB}-\x{38D4}\x{38D8}-\x{38E0}'
. '\x{38E2}-\x{38E6}\x{38EB}-\x{38ED}\x{38EF}-\x{38F2}\x{38F5}-\x{38F7}\x{38FA}-\x{38FF}\x{3901}-\x{392A}'
. '\x{392C}\x{392E}-\x{393B}\x{393E}-\x{3956}\x{395A}-\x{3969}\x{396B}-\x{397A}\x{397C}-\x{3987}'
. '\x{3989}-\x{3998}\x{399A}-\x{39B0}\x{39B2}\x{39B4}-\x{39D0}\x{39D2}-\x{39DA}\x{39DE}-\x{39DF}'
. '\x{39E1}-\x{39EF}\x{39F1}-\x{3A17}\x{3A19}-\x{3A2A}\x{3A2D}-\x{3A40}\x{3A43}-\x{3A4E}\x{3A50}'
. '\x{3A52}-\x{3A5E}\x{3A60}-\x{3A6D}\x{3A6F}-\x{3A77}\x{3A79}-\x{3A82}\x{3A84}-\x{3A85}\x{3A87}-\x{3A89}'
. '\x{3A8B}-\x{3A8F}\x{3A91}-\x{3A93}\x{3A95}-\x{3A96}\x{3A9A}\x{3A9C}-\x{3AA6}\x{3AA8}-\x{3AA9}'
. '\x{3AAB}-\x{3AB1}\x{3AB4}-\x{3ABC}\x{3ABE}-\x{3AC5}\x{3ACA}-\x{3ACB}\x{3ACD}-\x{3AD5}\x{3AD7}-\x{3AE1}'
. '\x{3AE4}-\x{3AE7}\x{3AE9}-\x{3AEC}\x{3AEE}-\x{3AFD}\x{3B01}-\x{3B10}\x{3B12}-\x{3B15}\x{3B17}-\x{3B1E}'
. '\x{3B20}-\x{3B23}\x{3B25}-\x{3B27}\x{3B29}-\x{3B36}\x{3B38}-\x{3B39}\x{3B3B}-\x{3B3C}\x{3B3F}'
. '\x{3B41}-\x{3B44}\x{3B47}-\x{3B4C}\x{3B4E}\x{3B51}-\x{3B55}\x{3B58}-\x{3B62}\x{3B68}-\x{3B72}'
. '\x{3B78}-\x{3B88}\x{3B8B}-\x{3B9F}\x{3BA1}\x{3BA3}-\x{3BBA}\x{3BBC}\x{3BBF}-\x{3BD0}'
. '\x{3BD3}-\x{3BE6}\x{3BEA}-\x{3BFB}\x{3BFE}-\x{3C12}\x{3C14}-\x{3C1B}\x{3C1D}-\x{3C37}\x{3C39}-\x{3C4F}'
. '\x{3C52}\x{3C54}-\x{3C5C}\x{3C5E}-\x{3C68}\x{3C6A}-\x{3C76}\x{3C78}-\x{3C8F}\x{3C91}-\x{3CA8}'
. '\x{3CAA}-\x{3CAD}\x{3CAF}-\x{3CBE}\x{3CC0}-\x{3CC8}\x{3CCA}-\x{3CD3}\x{3CD6}-\x{3CE0}\x{3CE4}-\x{3CEE}'
. '\x{3CF3}-\x{3D0A}\x{3D0E}-\x{3D1E}\x{3D20}-\x{3D21}\x{3D25}-\x{3D38}\x{3D3B}-\x{3D46}\x{3D4A}-\x{3D59}'
. '\x{3D5D}-\x{3D7B}\x{3D7D}-\x{3D81}\x{3D84}-\x{3D88}\x{3D8C}-\x{3D8F}\x{3D91}-\x{3D98}\x{3D9A}-\x{3D9C}'
. '\x{3D9E}-\x{3DA1}\x{3DA3}-\x{3DB0}\x{3DB2}-\x{3DB5}\x{3DB9}-\x{3DBC}\x{3DBE}-\x{3DCB}\x{3DCD}-\x{3DDB}'
. '\x{3DDF}-\x{3DE8}\x{3DEB}-\x{3DF0}\x{3DF3}-\x{3DF9}\x{3DFB}-\x{3DFC}\x{3DFE}-\x{3E05}\x{3E08}-\x{3E33}'
. '\x{3E35}-\x{3E3E}\x{3E40}-\x{3E47}\x{3E49}-\x{3E67}\x{3E6B}-\x{3E6F}\x{3E71}-\x{3E85}\x{3E87}-\x{3E8C}'
. '\x{3E8E}-\x{3E98}\x{3E9A}-\x{3EA1}\x{3EA3}-\x{3EAE}\x{3EB0}-\x{3EB5}\x{3EB7}-\x{3EBA}\x{3EBD}'
. '\x{3EBF}-\x{3EC4}\x{3EC7}-\x{3ECE}\x{3ED1}-\x{3ED7}\x{3ED9}-\x{3EDA}\x{3EDD}-\x{3EE3}\x{3EE7}-\x{3EE8}'
. '\x{3EEB}-\x{3EF2}\x{3EF5}-\x{3EFF}\x{3F01}-\x{3F02}\x{3F04}-\x{3F07}\x{3F09}-\x{3F44}\x{3F46}-\x{3F4E}'
. '\x{3F50}-\x{3F53}\x{3F55}-\x{3F72}\x{3F74}-\x{3F75}\x{3F77}-\x{3F7B}\x{3F7D}-\x{3FB0}\x{3FB6}-\x{3FBF}'
. '\x{3FC1}-\x{3FCF}\x{3FD1}-\x{3FD3}\x{3FD5}-\x{3FDF}\x{3FE1}-\x{400B}\x{400D}-\x{401C}\x{401E}-\x{4024}'
. '\x{4027}-\x{403F}\x{4041}-\x{4060}\x{4062}-\x{4069}\x{406B}-\x{408A}\x{408C}-\x{40A7}\x{40A9}-\x{40B4}'
. '\x{40B6}-\x{40C2}\x{40C7}-\x{40CF}\x{40D1}-\x{40DE}\x{40E0}-\x{40E7}\x{40E9}-\x{40EE}\x{40F0}-\x{40FB}'
. '\x{40FD}-\x{4109}\x{410B}-\x{4115}\x{4118}-\x{411D}\x{411F}-\x{4122}\x{4124}-\x{4133}\x{4136}-\x{4138}'
. '\x{413A}-\x{4148}\x{414A}-\x{4169}\x{416C}-\x{4185}\x{4188}-\x{418B}\x{418D}-\x{41AD}\x{41AF}-\x{41B3}'
. '\x{41B5}-\x{41C3}\x{41C5}-\x{41C9}\x{41CB}-\x{41F2}\x{41F5}-\x{41FE}\x{4200}-\x{4227}\x{422A}-\x{4246}'
. '\x{4248}-\x{4263}\x{4265}-\x{428B}\x{428D}-\x{42A1}\x{42A3}-\x{42C4}\x{42C8}-\x{42DC}\x{42DE}-\x{430A}'
. '\x{430C}-\x{4335}\x{4337}\x{4342}-\x{435F}\x{4361}-\x{439A}\x{439C}-\x{439D}\x{439F}-\x{43A4}'
. '\x{43A6}-\x{43EC}\x{43EF}-\x{4405}\x{4407}-\x{4429}\x{442B}-\x{4455}\x{4457}-\x{4468}\x{446A}-\x{446D}'
. '\x{446F}-\x{4476}\x{4479}-\x{447D}\x{447F}-\x{4486}\x{4488}-\x{4490}\x{4492}-\x{4498}\x{449A}-\x{44AD}'
. '\x{44B0}-\x{44BD}\x{44C1}-\x{44D3}\x{44D6}-\x{44E7}\x{44EA}\x{44EC}-\x{44FA}\x{44FC}-\x{4541}'
. '\x{4543}-\x{454F}\x{4551}-\x{4562}\x{4564}-\x{4575}\x{4577}-\x{45AB}\x{45AD}-\x{45BD}\x{45BF}-\x{45D5}'
. '\x{45D7}-\x{45EC}\x{45EE}-\x{45F2}\x{45F4}-\x{45FA}\x{45FC}-\x{461A}\x{461C}-\x{461D}\x{461F}-\x{4631}'
. '\x{4633}-\x{4649}\x{464C}\x{464E}-\x{4652}\x{4654}-\x{466A}\x{466C}-\x{4675}\x{4677}-\x{467A}'
. '\x{467C}-\x{4694}\x{4696}-\x{46A3}\x{46A5}-\x{46AB}\x{46AD}-\x{46D2}\x{46D4}-\x{4723}\x{4729}-\x{4732}'
. '\x{4734}-\x{4758}\x{475A}\x{475C}-\x{478B}\x{478D}\x{4791}-\x{47B1}\x{47B3}-\x{47F1}'
. '\x{47F3}-\x{480B}\x{480D}-\x{4815}\x{4817}-\x{4839}\x{483B}-\x{4870}\x{4872}-\x{487A}\x{487C}-\x{487F}'
. '\x{4883}-\x{488E}\x{4890}-\x{4896}\x{4899}-\x{48A2}\x{48A4}-\x{48B9}\x{48BB}-\x{48C8}\x{48CA}-\x{48D1}'
. '\x{48D3}-\x{48E5}\x{48E7}-\x{48F2}\x{48F4}-\x{48FF}\x{4901}-\x{4922}\x{4924}-\x{4928}\x{492A}-\x{4931}'
. '\x{4933}-\x{495B}\x{495D}-\x{4978}\x{497A}\x{497D}\x{4982}-\x{4983}\x{4985}-\x{49A8}'
. '\x{49AA}-\x{49AF}\x{49B1}-\x{49B7}\x{49B9}-\x{49BD}\x{49C1}-\x{49C7}\x{49C9}-\x{49CE}\x{49D0}-\x{49E8}'
. '\x{49EA}\x{49EC}\x{49EE}-\x{4A19}\x{4A1B}-\x{4A43}\x{4A45}-\x{4A4D}\x{4A4F}-\x{4A9E}'
. '\x{4AA0}-\x{4AA9}\x{4AAB}-\x{4B4E}\x{4B50}-\x{4B5B}\x{4B5D}-\x{4B69}\x{4B6B}-\x{4BC2}\x{4BC6}-\x{4BE8}'
. '\x{4BEA}-\x{4BFA}\x{4BFC}-\x{4C06}\x{4C08}-\x{4C2D}\x{4C2F}-\x{4C32}\x{4C34}-\x{4C35}\x{4C37}-\x{4C69}'
. '\x{4C6B}-\x{4C73}\x{4C75}-\x{4C86}\x{4C88}-\x{4C97}\x{4C99}-\x{4C9C}\x{4C9F}-\x{4CA3}\x{4CA5}-\x{4CB5}'
. '\x{4CB7}-\x{4CF8}\x{4CFA}-\x{4D27}\x{4D29}-\x{4DAC}\x{4DAE}-\x{4DB1}\x{4DB3}-\x{4DB5}\x{4E00}-\x{4E54}'
. '\x{4E56}-\x{4E89}\x{4E8B}-\x{4EEC}\x{4EEE}-\x{4FAC}\x{4FAE}-\x{503C}\x{503E}-\x{51E5}\x{51E7}-\x{5270}'
. '\x{5272}-\x{56A1}\x{56A3}-\x{5840}\x{5842}-\x{58B5}\x{58B7}-\x{58CB}\x{58CD}-\x{5BC8}\x{5BCA}-\x{5C01}'
. '\x{5C03}-\x{5C25}\x{5C27}-\x{5D5B}\x{5D5D}-\x{5F08}\x{5F0A}-\x{61F3}\x{61F5}-\x{63BA}\x{63BC}-\x{6441}'
. '\x{6443}-\x{657C}\x{657E}-\x{663E}\x{6640}-\x{66FC}\x{66FE}-\x{6728}\x{672A}-\x{6766}\x{6768}-\x{67A8}'
. '\x{67AA}-\x{685B}\x{685D}-\x{685E}\x{6860}-\x{68B9}\x{68BB}-\x{6AC8}\x{6ACA}-\x{6BB0}\x{6BB2}-\x{6C16}'
. '\x{6C18}-\x{6D9B}\x{6D9D}-\x{6E12}\x{6E14}-\x{6E8B}\x{6E8D}-\x{704D}\x{704F}-\x{7113}\x{7115}-\x{713B}'
. '\x{713D}-\x{7154}\x{7156}-\x{729F}\x{72A1}-\x{731E}\x{7320}-\x{7362}\x{7364}-\x{7533}\x{7535}-\x{7551}'
. '\x{7553}-\x{7572}\x{7574}-\x{75E8}\x{75EA}-\x{7679}\x{767B}-\x{783E}\x{7840}-\x{7A62}\x{7A64}-\x{7AC2}'
. '\x{7AC4}-\x{7B06}\x{7B08}-\x{7B79}\x{7B7B}-\x{7BCE}\x{7BD0}-\x{7D99}\x{7D9B}-\x{7E49}\x{7E4C}-\x{8132}'
. '\x{8134}\x{8136}-\x{81D2}\x{81D4}-\x{8216}\x{8218}-\x{822D}\x{822F}-\x{83B4}\x{83B6}-\x{841F}'
. '\x{8421}-\x{86CC}\x{86CE}-\x{874A}\x{874C}-\x{877E}\x{8780}-\x{8A32}\x{8A34}-\x{8B71}\x{8B73}-\x{8B8E}'
. '\x{8B90}-\x{8DE4}\x{8DE6}-\x{8E9A}\x{8E9C}-\x{8EE1}\x{8EE4}-\x{8F0B}\x{8F0D}-\x{8FB9}\x{8FBB}-\x{9038}'
. '\x{903A}-\x{9196}\x{9198}-\x{91A3}\x{91A5}-\x{91B7}\x{91B9}-\x{91C7}\x{91C9}-\x{91E0}\x{91E2}-\x{91FB}'
. '\x{91FD}-\x{922B}\x{922D}-\x{9270}\x{9272}-\x{9420}\x{9422}-\x{9664}\x{9666}-\x{9679}\x{967B}-\x{9770}'
. '\x{9772}-\x{982B}\x{982D}-\x{98ED}\x{98EF}-\x{99C4}\x{99C6}-\x{9A11}\x{9A14}-\x{9A27}\x{9A29}-\x{9D0D}'
. '\x{9D0F}-\x{9D2B}\x{9D2D}-\x{9D8E}\x{9D90}-\x{9DC5}\x{9DC7}-\x{9E77}\x{9E79}-\x{9EB8}\x{9EBB}-\x{9F20}'
. '\x{9F22}-\x{9F61}\x{9F63}-\x{9FA5}\x{FA28}]{1,20}$/iu',
6 => '/^[\x{002d}0-9A-Za-z]{1,63}$/iu',
7 => '/^[\x{00A1}-\x{00FF}]{1,63}$/iu',
8 => '/^[\x{0100}-\x{017f}]{1,63}$/iu',
9 => '/^[\x{0180}-\x{024f}]{1,63}$/iu',
10 => '/^[\x{0250}-\x{02af}]{1,63}$/iu',
11 => '/^[\x{02b0}-\x{02ff}]{1,63}$/iu',
12 => '/^[\x{0300}-\x{036f}]{1,63}$/iu',
13 => '/^[\x{0370}-\x{03ff}]{1,63}$/iu',
14 => '/^[\x{0400}-\x{04ff}]{1,63}$/iu',
15 => '/^[\x{0500}-\x{052f}]{1,63}$/iu',
16 => '/^[\x{0530}-\x{058F}]{1,63}$/iu',
17 => '/^[\x{0590}-\x{05FF}]{1,63}$/iu',
18 => '/^[\x{0600}-\x{06FF}]{1,63}$/iu',
19 => '/^[\x{0700}-\x{074F}]{1,63}$/iu',
20 => '/^[\x{0780}-\x{07BF}]{1,63}$/iu',
21 => '/^[\x{0900}-\x{097F}]{1,63}$/iu',
22 => '/^[\x{0980}-\x{09FF}]{1,63}$/iu',
23 => '/^[\x{0A00}-\x{0A7F}]{1,63}$/iu',
24 => '/^[\x{0A80}-\x{0AFF}]{1,63}$/iu',
25 => '/^[\x{0B00}-\x{0B7F}]{1,63}$/iu',
26 => '/^[\x{0B80}-\x{0BFF}]{1,63}$/iu',
27 => '/^[\x{0C00}-\x{0C7F}]{1,63}$/iu',
28 => '/^[\x{0C80}-\x{0CFF}]{1,63}$/iu',
29 => '/^[\x{0D00}-\x{0D7F}]{1,63}$/iu',
30 => '/^[\x{0D80}-\x{0DFF}]{1,63}$/iu',
31 => '/^[\x{0E00}-\x{0E7F}]{1,63}$/iu',
32 => '/^[\x{0E80}-\x{0EFF}]{1,63}$/iu',
33 => '/^[\x{0F00}-\x{0FFF}]{1,63}$/iu',
34 => '/^[\x{1000}-\x{109F}]{1,63}$/iu',
35 => '/^[\x{10A0}-\x{10FF}]{1,63}$/iu',
36 => '/^[\x{1100}-\x{11FF}]{1,63}$/iu',
37 => '/^[\x{1200}-\x{137F}]{1,63}$/iu',
38 => '/^[\x{13A0}-\x{13FF}]{1,63}$/iu',
39 => '/^[\x{1400}-\x{167F}]{1,63}$/iu',
40 => '/^[\x{1680}-\x{169F}]{1,63}$/iu',
41 => '/^[\x{16A0}-\x{16FF}]{1,63}$/iu',
42 => '/^[\x{1700}-\x{171F}]{1,63}$/iu',
43 => '/^[\x{1720}-\x{173F}]{1,63}$/iu',
44 => '/^[\x{1740}-\x{175F}]{1,63}$/iu',
45 => '/^[\x{1760}-\x{177F}]{1,63}$/iu',
46 => '/^[\x{1780}-\x{17FF}]{1,63}$/iu',
47 => '/^[\x{1800}-\x{18AF}]{1,63}$/iu',
48 => '/^[\x{1E00}-\x{1EFF}]{1,63}$/iu',
49 => '/^[\x{1F00}-\x{1FFF}]{1,63}$/iu',
50 => '/^[\x{2070}-\x{209F}]{1,63}$/iu',
51 => '/^[\x{2100}-\x{214F}]{1,63}$/iu',
52 => '/^[\x{2150}-\x{218F}]{1,63}$/iu',
53 => '/^[\x{2460}-\x{24FF}]{1,63}$/iu',
54 => '/^[\x{2E80}-\x{2EFF}]{1,63}$/iu',
55 => '/^[\x{2F00}-\x{2FDF}]{1,63}$/iu',
56 => '/^[\x{2FF0}-\x{2FFF}]{1,63}$/iu',
57 => '/^[\x{3040}-\x{309F}]{1,63}$/iu',
58 => '/^[\x{30A0}-\x{30FF}]{1,63}$/iu',
59 => '/^[\x{3100}-\x{312F}]{1,63}$/iu',
60 => '/^[\x{3130}-\x{318F}]{1,63}$/iu',
61 => '/^[\x{3190}-\x{319F}]{1,63}$/iu',
62 => '/^[\x{31A0}-\x{31BF}]{1,63}$/iu',
63 => '/^[\x{31F0}-\x{31FF}]{1,63}$/iu',
64 => '/^[\x{3200}-\x{32FF}]{1,63}$/iu',
65 => '/^[\x{3300}-\x{33FF}]{1,63}$/iu',
66 => '/^[\x{3400}-\x{4DBF}]{1,63}$/iu',
67 => '/^[\x{4E00}-\x{9FFF}]{1,63}$/iu',
68 => '/^[\x{A000}-\x{A48F}]{1,63}$/iu',
69 => '/^[\x{A490}-\x{A4CF}]{1,63}$/iu',
70 => '/^[\x{AC00}-\x{D7AF}]{1,63}$/iu',
73 => '/^[\x{F900}-\x{FAFF}]{1,63}$/iu',
74 => '/^[\x{FB00}-\x{FB4F}]{1,63}$/iu',
75 => '/^[\x{FB50}-\x{FDFF}]{1,63}$/iu',
76 => '/^[\x{FE20}-\x{FE2F}]{1,63}$/iu',
77 => '/^[\x{FE70}-\x{FEFF}]{1,63}$/iu',
78 => '/^[\x{FF00}-\x{FFEF}]{1,63}$/iu',
79 => '/^[\x{20000}-\x{2A6DF}]{1,63}$/iu',
80 => '/^[\x{2F800}-\x{2FA1F}]{1,63}$/iu',
];
laminas-validator/src/BusinessIdentifierCode.php 0000644 00000013047 15240152635 0016054 0 ustar 00 <?php
namespace Laminas\Validator;
use function in_array;
use function is_string;
use function preg_match;
use function strtoupper;
class BusinessIdentifierCode extends AbstractValidator
{
public const INVALID = 'valueNotBic';
public const NOT_STRING = 'valueNotString';
public const NOT_VALID_COUNTRY = 'valueNotCountry';
/** @var string[] */
protected $messageTemplates = [
self::NOT_STRING => 'Invalid type given; string expected',
self::INVALID => 'Invalid BIC format',
self::NOT_VALID_COUNTRY => 'Invalid country code',
];
/**
* @see https://www.bundesbank.de/resource/blob/749660/d2c6e00664251b4d83483c229e084e44/mL/technische-spezifikationen-scc-anhang-112018-data.pdf (page 39)
*/
private const REGEX_BIC = '/^[a-z]{4}(?<country>[a-z]{2})[a-z2-9][a-np-z0-9]([0-9a-z]{3})?$/i';
/**
* List of all country codes defined by ISO 3166-1 alpha-2
*
* @see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Current_codes
*
* @var string[]
*/
private const ISO_COUNTRIES = [
'AD',
'AE',
'AF',
'AG',
'AI',
'AL',
'AM',
'AO',
'AQ',
'AR',
'AS',
'AT',
'AU',
'AW',
'AX',
'AZ',
'BA',
'BB',
'BD',
'BE',
'BF',
'BG',
'BH',
'BI',
'BJ',
'BL',
'BM',
'BN',
'BO',
'BQ',
'BQ',
'BR',
'BS',
'BT',
'BV',
'BW',
'BY',
'BZ',
'CA',
'CC',
'CD',
'CF',
'CG',
'CH',
'CI',
'CK',
'CL',
'CM',
'CN',
'CO',
'CR',
'CU',
'CV',
'CW',
'CX',
'CY',
'CZ',
'DE',
'DJ',
'DK',
'DM',
'DO',
'DZ',
'EC',
'EE',
'EG',
'EH',
'ER',
'ES',
'ET',
'FI',
'FJ',
'FK',
'FM',
'FO',
'FR',
'GA',
'GB',
'GD',
'GE',
'GF',
'GG',
'GH',
'GI',
'GL',
'GM',
'GN',
'GP',
'GQ',
'GR',
'GS',
'GT',
'GU',
'GW',
'GY',
'HK',
'HM',
'HN',
'HR',
'HT',
'HU',
'ID',
'IE',
'IL',
'IM',
'IN',
'IO',
'IQ',
'IR',
'IS',
'IT',
'JE',
'JM',
'JO',
'JP',
'KE',
'KG',
'KH',
'KI',
'KM',
'KN',
'KP',
'KR',
'KW',
'KY',
'KZ',
'LA',
'LB',
'LC',
'LI',
'LK',
'LR',
'LS',
'LT',
'LU',
'LV',
'LY',
'MA',
'MC',
'MD',
'ME',
'MF',
'MG',
'MH',
'MK',
'ML',
'MM',
'MN',
'MO',
'MP',
'MQ',
'MR',
'MS',
'MT',
'MU',
'MV',
'MW',
'MX',
'MY',
'MZ',
'NA',
'NC',
'NE',
'NF',
'NG',
'NI',
'NL',
'NO',
'NP',
'NR',
'NU',
'NZ',
'OM',
'PA',
'PE',
'PF',
'PG',
'PH',
'PK',
'PL',
'PM',
'PN',
'PR',
'PS',
'PT',
'PW',
'PY',
'QA',
'RE',
'RO',
'RS',
'RU',
'RW',
'SA',
'SB',
'SC',
'SD',
'SE',
'SG',
'SH',
'SI',
'SJ',
'SK',
'SL',
'SM',
'SN',
'SO',
'SR',
'SS',
'ST',
'SV',
'SX',
'SY',
'SZ',
'TC',
'TD',
'TF',
'TG',
'TH',
'TJ',
'TK',
'TL',
'TM',
'TN',
'TO',
'TR',
'TT',
'TV',
'TW',
'TZ',
'UA',
'UG',
'UM',
'US',
'UY',
'UZ',
'VA',
'VC',
'VE',
'VG',
'VI',
'VN',
'VU',
'WF',
'WS',
'YE',
'YT',
'ZA',
'ZM',
'ZW',
];
/**
* This code is the only one used by SWIFT that is not defined by ISO 3166-1 alpha-2
*
* @see https://en.wikipedia.org/wiki/ISO_9362
*
* @var string
*/
private const KOSOVO_EXCEPTION = 'XK';
/** {@inheritDoc} */
public function isValid($value): bool
{
if (! is_string($value)) {
$this->error(self::NOT_STRING);
return false;
}
if (
empty($value)
|| ! preg_match(self::REGEX_BIC, $value, $matches)
) {
$this->error(self::INVALID);
return false;
}
if (! $this->isSwiftValidCountry($matches['country'])) {
$this->error(self::NOT_VALID_COUNTRY);
return false;
}
return true;
}
private function isSwiftValidCountry(string $countryCode): bool
{
$countryCode = strtoupper($countryCode);
return in_array($countryCode, self::ISO_COUNTRIES, true)
|| $countryCode === self::KOSOVO_EXCEPTION;
}
}
laminas-validator/src/IsCountable.php 0000644 00000012564 15240152635 0013676 0 ustar 00 <?php // phpcs:disable SlevomatCodingStandard.Classes.UnusedPrivateElements.UnusedMethod
namespace Laminas\Validator;
use Traversable;
use function count;
use function is_array;
use function is_countable;
use function is_numeric;
use function sprintf;
use function ucfirst;
/**
* Validate that a value is countable and the count meets expectations.
*
* The validator has five specific behaviors:
*
* - You can determine if a value is countable only
* - You can test if the value is an exact count
* - You can test if the value is greater than a minimum count value
* - You can test if the value is greater than a maximum count value
* - You can test if the value is between the minimum and maximum count values
*
* When creating the instance or calling `setOptions()`, if you specify a
* "count" option, specifying either "min" or "max" leads to an inconsistent
* state and, as such will raise an Exception\InvalidArgumentException.
*/
class IsCountable extends AbstractValidator
{
public const NOT_COUNTABLE = 'notCountable';
public const NOT_EQUALS = 'notEquals';
public const GREATER_THAN = 'greaterThan';
public const LESS_THAN = 'lessThan';
/**
* Validation failure message template definitions
*
* @var array
*/
protected $messageTemplates = [
self::NOT_COUNTABLE => 'The input must be an array or an instance of \\Countable',
self::NOT_EQUALS => "The input count must equal '%count%'",
self::GREATER_THAN => "The input count must be less than '%max%', inclusively",
self::LESS_THAN => "The input count must be greater than '%min%', inclusively",
];
/**
* Additional variables available for validation failure messages
*
* @var array
*/
protected $messageVariables = [
'count' => ['options' => 'count'],
'min' => ['options' => 'min'],
'max' => ['options' => 'max'],
];
/**
* Options for the between validator
*
* @var array
*/
protected $options = [
'count' => null,
'min' => null,
'max' => null,
];
/**
* @param array|Traversable $options
* @return $this Provides fluid interface
*/
public function setOptions($options = [])
{
foreach (['count', 'min', 'max'] as $option) {
if (! is_array($options) || ! isset($options[$option])) {
continue;
}
$method = sprintf('set%s', ucfirst($option));
$this->$method($options[$option]);
unset($options[$option]);
}
return parent::setOptions($options);
}
/**
* Returns true if and only if $value is countable (and the count validates against optional values).
*
* @param iterable $value
* @return bool
*/
public function isValid($value)
{
if (! is_countable($value)) {
$this->error(self::NOT_COUNTABLE);
return false;
}
$count = count($value);
if (is_numeric($this->getCount())) {
if ($count !== $this->getCount()) {
$this->error(self::NOT_EQUALS);
return false;
}
return true;
}
if (is_numeric($this->getMax()) && $count > $this->getMax()) {
$this->error(self::GREATER_THAN);
return false;
}
if (is_numeric($this->getMin()) && $count < $this->getMin()) {
$this->error(self::LESS_THAN);
return false;
}
return true;
}
/**
* Returns the count option
*
* @return mixed
*/
public function getCount()
{
return $this->options['count'];
}
/**
* Returns the min option
*
* @return mixed
*/
public function getMin()
{
return $this->options['min'];
}
/**
* Returns the max option
*
* @return mixed
*/
public function getMax()
{
return $this->options['max'];
}
/**
* @return void
* @throws Exception\InvalidArgumentException If either a min or max option
* was previously set.
*/
private function setCount(mixed $value)
{
if (isset($this->options['min']) || isset($this->options['max'])) {
throw new Exception\InvalidArgumentException(
'Cannot set count; conflicts with either a min or max option previously set'
);
}
$this->options['count'] = $value;
}
/**
* @return void
* @throws Exception\InvalidArgumentException If either a count or max option
* was previously set.
*/
private function setMin(mixed $value)
{
if (isset($this->options['count'])) {
throw new Exception\InvalidArgumentException(
'Cannot set count; conflicts with either a count option previously set'
);
}
$this->options['min'] = $value;
}
/**
* @return void
* @throws Exception\InvalidArgumentException If either a count or min option
* was previously set.
*/
private function setMax(mixed $value)
{
if (isset($this->options['count'])) {
throw new Exception\InvalidArgumentException(
'Cannot set count; conflicts with either a count option previously set'
);
}
$this->options['max'] = $value;
}
}
laminas-validator/src/Exception/InvalidArgumentException.php 0000644 00000000222 15240152635 0020360 0 ustar 00 <?php
namespace Laminas\Validator\Exception;
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
laminas-validator/src/Exception/ExceptionInterface.php 0000644 00000000120 15240152636 0017165 0 ustar 00 <?php
namespace Laminas\Validator\Exception;
interface ExceptionInterface
{
}
laminas-validator/src/Exception/InvalidMagicMimeFileException.php 0000644 00000000170 15240152636 0021231 0 ustar 00 <?php
namespace Laminas\Validator\Exception;
class InvalidMagicMimeFileException extends InvalidArgumentException
{
}
laminas-validator/src/Exception/BadMethodCallException.php 0000644 00000000216 15240152636 0017716 0 ustar 00 <?php
namespace Laminas\Validator\Exception;
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
}
laminas-validator/src/Exception/ExtensionNotLoadedException.php 0000644 00000000156 15240152636 0021044 0 ustar 00 <?php
namespace Laminas\Validator\Exception;
class ExtensionNotLoadedException extends RuntimeException
{
}
laminas-validator/src/Exception/RuntimeException.php 0000644 00000000202 15240152636 0016711 0 ustar 00 <?php
namespace Laminas\Validator\Exception;
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
laminas-validator/src/Explode.php 0000644 00000012225 15240152636 0013061 0 ustar 00 <?php
namespace Laminas\Validator;
use Laminas\ServiceManager\ServiceManager;
use Laminas\Stdlib\ArrayUtils;
use Traversable;
use function explode;
use function is_array;
use function is_string;
use function sprintf;
/**
* @psalm-import-type ValidatorSpecification from ValidatorInterface
*/
class Explode extends AbstractValidator implements ValidatorPluginManagerAwareInterface
{
public const INVALID = 'explodeInvalid';
/** @var null|ValidatorPluginManager */
protected $pluginManager;
/** @var array */
protected $messageTemplates = [
self::INVALID => 'Invalid type given',
];
/** @var array */
protected $messageVariables = [];
/** @var string */
protected $valueDelimiter = ',';
/** @var ValidatorInterface|null */
protected $validator;
/** @var bool */
protected $breakOnFirstFailure = false;
/**
* Sets the delimiter string that the values will be split upon
*
* @param string $delimiter
* @return $this
*/
public function setValueDelimiter($delimiter)
{
$this->valueDelimiter = $delimiter;
return $this;
}
/**
* Returns the delimiter string that the values will be split upon
*
* @return string
*/
public function getValueDelimiter()
{
return $this->valueDelimiter;
}
/**
* Set validator plugin manager
*
* @return void
*/
public function setValidatorPluginManager(ValidatorPluginManager $pluginManager)
{
$this->pluginManager = $pluginManager;
}
/**
* Get validator plugin manager
*
* @return ValidatorPluginManager
*/
public function getValidatorPluginManager()
{
if (! $this->pluginManager) {
$this->pluginManager = new ValidatorPluginManager(new ServiceManager());
}
return $this->pluginManager;
}
/**
* Sets the Validator for validating each value
*
* @param ValidatorInterface|ValidatorSpecification $validator
* @throws Exception\RuntimeException
* @return $this
*/
public function setValidator($validator)
{
if (is_array($validator)) {
if (! isset($validator['name'])) {
throw new Exception\RuntimeException(
'Invalid validator specification provided; does not include "name" key'
);
}
$name = $validator['name'];
$options = $validator['options'] ?? [];
/** @psalm-suppress MixedAssignment $validator */
$validator = $this->getValidatorPluginManager()->get($name, $options);
}
if (! $validator instanceof ValidatorInterface) {
throw new Exception\RuntimeException(
'Invalid validator given'
);
}
$this->validator = $validator;
return $this;
}
/**
* Gets the Validator for validating each value
*
* @return ValidatorInterface|null
*/
public function getValidator()
{
return $this->validator;
}
/**
* Set break on first failure setting
*
* @param bool $break
* @return $this
*/
public function setBreakOnFirstFailure($break)
{
$this->breakOnFirstFailure = (bool) $break;
return $this;
}
/**
* Get break on first failure setting
*
* @return bool
*/
public function isBreakOnFirstFailure()
{
return $this->breakOnFirstFailure;
}
/**
* Defined by Laminas\Validator\ValidatorInterface
*
* Returns true if all values validate true
*
* @param mixed $value
* @param mixed $context Extra "context" to provide the composed validator
* @return bool
* @throws Exception\RuntimeException
*/
public function isValid($value, $context = null)
{
$this->setValue($value);
if ($value instanceof Traversable) {
$value = ArrayUtils::iteratorToArray($value);
}
if (is_array($value)) {
$values = $value;
} elseif (is_string($value)) {
$delimiter = $this->getValueDelimiter();
// Skip explode if delimiter is null,
// used when value is expected to be either an
// array when multiple values and a string for
// single values (ie. MultiCheckbox form behavior)
$values = null !== $delimiter
? explode($this->valueDelimiter, $value)
: [$value];
} else {
$values = [$value];
}
$validator = $this->getValidator();
if (! $validator) {
throw new Exception\RuntimeException(sprintf(
'%s expects a validator to be set; none given',
__METHOD__
));
}
foreach ($values as $value) {
if (! $validator->isValid($value, $context)) {
$this->abstractOptions['messages'][] = $validator->getMessages();
if ($this->isBreakOnFirstFailure()) {
return false;
}
}
}
return ! $this->abstractOptions['messages'];
}
}
laminas-validator/src/ValidatorPluginManager.php 0000644 00000105134 15240152636 0016062 0 ustar 00 <?php
namespace Laminas\Validator;
use Laminas\I18n\Validator as I18nValidator;
use Laminas\ServiceManager\AbstractPluginManager;
use Laminas\ServiceManager\ConfigInterface;
use Laminas\ServiceManager\Exception\InvalidServiceException;
use Laminas\ServiceManager\Factory\InvokableFactory;
use Laminas\ServiceManager\ServiceManager;
use Psr\Container\ContainerInterface;
use Zend\I18n\Validator\Alnum;
use Zend\I18n\Validator\Alpha;
use Zend\I18n\Validator\DateTime;
use Zend\I18n\Validator\IsFloat;
use Zend\I18n\Validator\IsInt;
use Zend\I18n\Validator\PhoneNumber;
use Zend\I18n\Validator\PostCode;
use Zend\Validator\Db\NoRecordExists;
use Zend\Validator\Db\RecordExists;
use Zend\Validator\File\Count;
use Zend\Validator\File\Crc32;
use Zend\Validator\File\ExcludeExtension;
use Zend\Validator\File\ExcludeMimeType;
use Zend\Validator\File\Exists;
use Zend\Validator\File\Extension;
use Zend\Validator\File\FilesSize;
use Zend\Validator\File\Hash;
use Zend\Validator\File\ImageSize;
use Zend\Validator\File\IsCompressed;
use Zend\Validator\File\IsImage;
use Zend\Validator\File\Md5;
use Zend\Validator\File\MimeType;
use Zend\Validator\File\NotExists;
use Zend\Validator\File\Sha1;
use Zend\Validator\File\Size;
use Zend\Validator\File\Upload;
use Zend\Validator\File\UploadFile;
use Zend\Validator\File\WordCount;
use Zend\Validator\Sitemap\Changefreq;
use Zend\Validator\Sitemap\Lastmod;
use Zend\Validator\Sitemap\Loc;
use Zend\Validator\Sitemap\Priority;
use function get_debug_type;
use function method_exists;
use function sprintf;
/**
* @link ConfigInterface
* @link ServiceManager
*
* @psalm-import-type ServiceManagerConfiguration from ServiceManager
* @psalm-import-type FactoriesConfigurationType from ConfigInterface
* @template InstanceType of ValidatorInterface
* @extends AbstractPluginManager<InstanceType>
*/
class ValidatorPluginManager extends AbstractPluginManager
{
/**
* Default set of aliases
*
* @var array<array-key, string>
* @psalm-suppress UndefinedClass
*/
protected $aliases = [
'alnum' => I18nValidator\Alnum::class,
'Alnum' => I18nValidator\Alnum::class,
'alpha' => I18nValidator\Alpha::class,
'Alpha' => I18nValidator\Alpha::class,
'barcode' => Barcode::class,
'Barcode' => Barcode::class,
'between' => Between::class,
'Between' => Between::class,
'BIC' => BusinessIdentifierCode::class,
'bic' => BusinessIdentifierCode::class,
'bitwise' => Bitwise::class,
'Bitwise' => Bitwise::class,
'BusinessIdentifierCode' => BusinessIdentifierCode::class,
'businessidentifiercode' => BusinessIdentifierCode::class,
'callback' => Callback::class,
'Callback' => Callback::class,
'creditcard' => CreditCard::class,
'creditCard' => CreditCard::class,
'CreditCard' => CreditCard::class,
'csrf' => Csrf::class,
'Csrf' => Csrf::class,
'date' => Date::class,
'Date' => Date::class,
'datestep' => DateStep::class,
'dateStep' => DateStep::class,
'DateStep' => DateStep::class,
'datetime' => I18nValidator\DateTime::class,
'dateTime' => I18nValidator\DateTime::class,
'DateTime' => I18nValidator\DateTime::class,
'dbnorecordexists' => Db\NoRecordExists::class,
'dbNoRecordExists' => Db\NoRecordExists::class,
'DbNoRecordExists' => Db\NoRecordExists::class,
'dbrecordexists' => Db\RecordExists::class,
'dbRecordExists' => Db\RecordExists::class,
'DbRecordExists' => Db\RecordExists::class,
'digits' => Digits::class,
'Digits' => Digits::class,
'emailaddress' => EmailAddress::class,
'emailAddress' => EmailAddress::class,
'EmailAddress' => EmailAddress::class,
'explode' => Explode::class,
'Explode' => Explode::class,
'filecount' => File\Count::class,
'fileCount' => File\Count::class,
'FileCount' => File\Count::class,
'filecrc32' => File\Crc32::class,
'fileCrc32' => File\Crc32::class,
'FileCrc32' => File\Crc32::class,
'fileexcludeextension' => File\ExcludeExtension::class,
'fileExcludeExtension' => File\ExcludeExtension::class,
'FileExcludeExtension' => File\ExcludeExtension::class,
'fileexcludemimetype' => File\ExcludeMimeType::class,
'fileExcludeMimeType' => File\ExcludeMimeType::class,
'FileExcludeMimeType' => File\ExcludeMimeType::class,
'fileexists' => File\Exists::class,
'fileExists' => File\Exists::class,
'FileExists' => File\Exists::class,
'fileextension' => File\Extension::class,
'fileExtension' => File\Extension::class,
'FileExtension' => File\Extension::class,
'filefilessize' => File\FilesSize::class,
'fileFilesSize' => File\FilesSize::class,
'FileFilesSize' => File\FilesSize::class,
'filehash' => File\Hash::class,
'fileHash' => File\Hash::class,
'FileHash' => File\Hash::class,
'fileimagesize' => File\ImageSize::class,
'fileImageSize' => File\ImageSize::class,
'FileImageSize' => File\ImageSize::class,
'fileiscompressed' => File\IsCompressed::class,
'fileIsCompressed' => File\IsCompressed::class,
'FileIsCompressed' => File\IsCompressed::class,
'fileisimage' => File\IsImage::class,
'fileIsImage' => File\IsImage::class,
'FileIsImage' => File\IsImage::class,
'filemd5' => File\Md5::class,
'fileMd5' => File\Md5::class,
'FileMd5' => File\Md5::class,
'filemimetype' => File\MimeType::class,
'fileMimeType' => File\MimeType::class,
'FileMimeType' => File\MimeType::class,
'filenotexists' => File\NotExists::class,
'fileNotExists' => File\NotExists::class,
'FileNotExists' => File\NotExists::class,
'filesha1' => File\Sha1::class,
'fileSha1' => File\Sha1::class,
'FileSha1' => File\Sha1::class,
'filesize' => File\Size::class,
'fileSize' => File\Size::class,
'FileSize' => File\Size::class,
'fileupload' => File\Upload::class,
'fileUpload' => File\Upload::class,
'FileUpload' => File\Upload::class,
'fileuploadfile' => File\UploadFile::class,
'fileUploadFile' => File\UploadFile::class,
'FileUploadFile' => File\UploadFile::class,
'filewordcount' => File\WordCount::class,
'fileWordCount' => File\WordCount::class,
'FileWordCount' => File\WordCount::class,
'float' => I18nValidator\IsFloat::class,
'Float' => I18nValidator\IsFloat::class,
'gpspoint' => GpsPoint::class,
'gpsPoint' => GpsPoint::class,
'GpsPoint' => GpsPoint::class,
'greaterthan' => GreaterThan::class,
'greaterThan' => GreaterThan::class,
'GreaterThan' => GreaterThan::class,
'hex' => Hex::class,
'Hex' => Hex::class,
'hostname' => Hostname::class,
'Hostname' => Hostname::class,
'iban' => Iban::class,
'Iban' => Iban::class,
'identical' => Identical::class,
'Identical' => Identical::class,
'inarray' => InArray::class,
'inArray' => InArray::class,
'InArray' => InArray::class,
'int' => I18nValidator\IsInt::class,
'Int' => I18nValidator\IsInt::class,
'ip' => Ip::class,
'Ip' => Ip::class,
'isbn' => Isbn::class,
'Isbn' => Isbn::class,
'isCountable' => IsCountable::class,
'IsCountable' => IsCountable::class,
'iscountable' => IsCountable::class,
'isfloat' => I18nValidator\IsFloat::class,
'isFloat' => I18nValidator\IsFloat::class,
'IsFloat' => I18nValidator\IsFloat::class,
'isinstanceof' => IsInstanceOf::class,
'isInstanceOf' => IsInstanceOf::class,
'IsInstanceOf' => IsInstanceOf::class,
'isint' => I18nValidator\IsInt::class,
'isInt' => I18nValidator\IsInt::class,
'IsInt' => I18nValidator\IsInt::class,
'lessthan' => LessThan::class,
'lessThan' => LessThan::class,
'LessThan' => LessThan::class,
'notempty' => NotEmpty::class,
'notEmpty' => NotEmpty::class,
'NotEmpty' => NotEmpty::class,
'phonenumber' => I18nValidator\PhoneNumber::class,
'phoneNumber' => I18nValidator\PhoneNumber::class,
'PhoneNumber' => I18nValidator\PhoneNumber::class,
'postcode' => I18nValidator\PostCode::class,
'postCode' => I18nValidator\PostCode::class,
'PostCode' => I18nValidator\PostCode::class,
'regex' => Regex::class,
'Regex' => Regex::class,
'sitemapchangefreq' => Sitemap\Changefreq::class,
'sitemapChangefreq' => Sitemap\Changefreq::class,
'SitemapChangefreq' => Sitemap\Changefreq::class,
'sitemaplastmod' => Sitemap\Lastmod::class,
'sitemapLastmod' => Sitemap\Lastmod::class,
'SitemapLastmod' => Sitemap\Lastmod::class,
'sitemaploc' => Sitemap\Loc::class,
'sitemapLoc' => Sitemap\Loc::class,
'SitemapLoc' => Sitemap\Loc::class,
'sitemappriority' => Sitemap\Priority::class,
'sitemapPriority' => Sitemap\Priority::class,
'SitemapPriority' => Sitemap\Priority::class,
'stringlength' => StringLength::class,
'stringLength' => StringLength::class,
'StringLength' => StringLength::class,
'step' => Step::class,
'Step' => Step::class,
'timezone' => Timezone::class,
'Timezone' => Timezone::class,
'uri' => Uri::class,
'Uri' => Uri::class,
'uuid' => Uuid::class,
'Uuid' => Uuid::class,
// Legacy Zend Framework aliases
Alnum::class => I18nValidator\Alnum::class,
Alpha::class => I18nValidator\Alpha::class,
\Zend\Validator\Barcode::class => Barcode::class,
\Zend\Validator\Between::class => Between::class,
\Zend\Validator\Bitwise::class => Bitwise::class,
\Zend\Validator\Callback::class => Callback::class,
\Zend\Validator\CreditCard::class => CreditCard::class,
\Zend\Validator\Csrf::class => Csrf::class,
\Zend\Validator\DateStep::class => DateStep::class,
\Zend\Validator\Date::class => Date::class,
DateTime::class => I18nValidator\DateTime::class,
NoRecordExists::class => Db\NoRecordExists::class,
RecordExists::class => Db\RecordExists::class,
\Zend\Validator\Digits::class => Digits::class,
\Zend\Validator\EmailAddress::class => EmailAddress::class,
\Zend\Validator\Explode::class => Explode::class,
Count::class => File\Count::class,
Crc32::class => File\Crc32::class,
ExcludeExtension::class => File\ExcludeExtension::class,
ExcludeMimeType::class => File\ExcludeMimeType::class,
Exists::class => File\Exists::class,
Extension::class => File\Extension::class,
FilesSize::class => File\FilesSize::class,
Hash::class => File\Hash::class,
ImageSize::class => File\ImageSize::class,
IsCompressed::class => File\IsCompressed::class,
IsImage::class => File\IsImage::class,
Md5::class => File\Md5::class,
MimeType::class => File\MimeType::class,
NotExists::class => File\NotExists::class,
Sha1::class => File\Sha1::class,
Size::class => File\Size::class,
Upload::class => File\Upload::class,
UploadFile::class => File\UploadFile::class,
WordCount::class => File\WordCount::class,
IsFloat::class => I18nValidator\IsFloat::class,
\Zend\Validator\GpsPoint::class => GpsPoint::class,
\Zend\Validator\GreaterThan::class => GreaterThan::class,
\Zend\Validator\Hex::class => Hex::class,
\Zend\Validator\Hostname::class => Hostname::class,
\Zend\Validator\Iban::class => Iban::class,
\Zend\Validator\Identical::class => Identical::class,
\Zend\Validator\InArray::class => InArray::class,
IsInt::class => I18nValidator\IsInt::class,
\Zend\Validator\Ip::class => Ip::class,
\Zend\Validator\Isbn::class => Isbn::class,
\Zend\Validator\IsInstanceOf::class => IsInstanceOf::class,
\Zend\Validator\LessThan::class => LessThan::class,
\Zend\Validator\NotEmpty::class => NotEmpty::class,
PhoneNumber::class => I18nValidator\PhoneNumber::class,
PostCode::class => I18nValidator\PostCode::class,
\Zend\Validator\Regex::class => Regex::class,
Changefreq::class => Sitemap\Changefreq::class,
Lastmod::class => Sitemap\Lastmod::class,
Loc::class => Sitemap\Loc::class,
Priority::class => Sitemap\Priority::class,
\Zend\Validator\StringLength::class => StringLength::class,
\Zend\Validator\Step::class => Step::class,
\Zend\Validator\Timezone::class => Timezone::class,
\Zend\Validator\Uri::class => Uri::class,
\Zend\Validator\Uuid::class => Uuid::class,
// v2 normalized FQCNs
'zendvalidatorbarcode' => Barcode::class,
'zendvalidatorbetween' => Between::class,
'zendvalidatorbitwise' => Bitwise::class,
'zendvalidatorcallback' => Callback::class,
'zendvalidatorcreditcard' => CreditCard::class,
'zendvalidatorcsrf' => Csrf::class,
'zendvalidatordatestep' => DateStep::class,
'zendvalidatordate' => Date::class,
'zendvalidatordbnorecordexists' => Db\NoRecordExists::class,
'zendvalidatordbrecordexists' => Db\RecordExists::class,
'zendvalidatordigits' => Digits::class,
'zendvalidatoremailaddress' => EmailAddress::class,
'zendvalidatorexplode' => Explode::class,
'zendvalidatorfilecount' => File\Count::class,
'zendvalidatorfilecrc32' => File\Crc32::class,
'zendvalidatorfileexcludeextension' => File\ExcludeExtension::class,
'zendvalidatorfileexcludemimetype' => File\ExcludeMimeType::class,
'zendvalidatorfileexists' => File\Exists::class,
'zendvalidatorfileextension' => File\Extension::class,
'zendvalidatorfilefilessize' => File\FilesSize::class,
'zendvalidatorfilehash' => File\Hash::class,
'zendvalidatorfileimagesize' => File\ImageSize::class,
'zendvalidatorfileiscompressed' => File\IsCompressed::class,
'zendvalidatorfileisimage' => File\IsImage::class,
'zendvalidatorfilemd5' => File\Md5::class,
'zendvalidatorfilemimetype' => File\MimeType::class,
'zendvalidatorfilenotexists' => File\NotExists::class,
'zendvalidatorfilesha1' => File\Sha1::class,
'zendvalidatorfilesize' => File\Size::class,
'zendvalidatorfileupload' => File\Upload::class,
'zendvalidatorfileuploadfile' => File\UploadFile::class,
'zendvalidatorfilewordcount' => File\WordCount::class,
'zendvalidatorgpspoint' => GpsPoint::class,
'zendvalidatorgreaterthan' => GreaterThan::class,
'zendvalidatorhex' => Hex::class,
'zendvalidatorhostname' => Hostname::class,
'zendi18nvalidatoralnum' => I18nValidator\Alnum::class,
'zendi18nvalidatoralpha' => I18nValidator\Alpha::class,
'zendi18nvalidatordatetime' => I18nValidator\DateTime::class,
'zendi18nvalidatorisfloat' => I18nValidator\IsFloat::class,
'zendi18nvalidatorisint' => I18nValidator\IsInt::class,
'zendi18nvalidatorphonenumber' => I18nValidator\PhoneNumber::class,
'zendi18nvalidatorpostcode' => I18nValidator\PostCode::class,
'zendvalidatoriban' => Iban::class,
'zendvalidatoridentical' => Identical::class,
'zendvalidatorinarray' => InArray::class,
'zendvalidatorip' => Ip::class,
'zendvalidatorisbn' => Isbn::class,
'zendvalidatorisinstanceof' => IsInstanceOf::class,
'zendvalidatorlessthan' => LessThan::class,
'zendvalidatornotempty' => NotEmpty::class,
'zendvalidatorregex' => Regex::class,
'zendvalidatorsitemapchangefreq' => Sitemap\Changefreq::class,
'zendvalidatorsitemaplastmod' => Sitemap\Lastmod::class,
'zendvalidatorsitemaploc' => Sitemap\Loc::class,
'zendvalidatorsitemappriority' => Sitemap\Priority::class,
'zendvalidatorstringlength' => StringLength::class,
'zendvalidatorstep' => Step::class,
'zendvalidatortimezone' => Timezone::class,
'zendvalidatoruri' => Uri::class,
'zendvalidatoruuid' => Uuid::class,
];
/**
* Default set of factories
*
* @var FactoriesConfigurationType
*/
protected $factories = [
I18nValidator\Alnum::class => InvokableFactory::class,
I18nValidator\Alpha::class => InvokableFactory::class,
Barcode::class => InvokableFactory::class,
Between::class => InvokableFactory::class,
Bitwise::class => InvokableFactory::class,
BusinessIdentifierCode::class => InvokableFactory::class,
Callback::class => InvokableFactory::class,
CreditCard::class => InvokableFactory::class,
Csrf::class => InvokableFactory::class,
DateStep::class => InvokableFactory::class,
Date::class => InvokableFactory::class,
I18nValidator\DateTime::class => InvokableFactory::class,
Db\NoRecordExists::class => InvokableFactory::class,
Db\RecordExists::class => InvokableFactory::class,
Digits::class => InvokableFactory::class,
EmailAddress::class => InvokableFactory::class,
Explode::class => InvokableFactory::class,
File\Count::class => InvokableFactory::class,
File\Crc32::class => InvokableFactory::class,
File\ExcludeExtension::class => InvokableFactory::class,
File\ExcludeMimeType::class => InvokableFactory::class,
File\Exists::class => InvokableFactory::class,
File\Extension::class => InvokableFactory::class,
File\FilesSize::class => InvokableFactory::class,
File\Hash::class => InvokableFactory::class,
File\ImageSize::class => InvokableFactory::class,
File\IsCompressed::class => InvokableFactory::class,
File\IsImage::class => InvokableFactory::class,
File\Md5::class => InvokableFactory::class,
File\MimeType::class => InvokableFactory::class,
File\NotExists::class => InvokableFactory::class,
File\Sha1::class => InvokableFactory::class,
File\Size::class => InvokableFactory::class,
File\Upload::class => InvokableFactory::class,
File\UploadFile::class => InvokableFactory::class,
File\WordCount::class => InvokableFactory::class,
I18nValidator\IsFloat::class => InvokableFactory::class,
GpsPoint::class => InvokableFactory::class,
GreaterThan::class => InvokableFactory::class,
Hex::class => InvokableFactory::class,
Hostname::class => InvokableFactory::class,
Iban::class => InvokableFactory::class,
Identical::class => InvokableFactory::class,
InArray::class => InvokableFactory::class,
I18nValidator\IsInt::class => InvokableFactory::class,
Ip::class => InvokableFactory::class,
Isbn::class => InvokableFactory::class,
IsCountable::class => InvokableFactory::class,
IsInstanceOf::class => InvokableFactory::class,
LessThan::class => InvokableFactory::class,
NotEmpty::class => InvokableFactory::class,
I18nValidator\PhoneNumber::class => InvokableFactory::class,
I18nValidator\PostCode::class => InvokableFactory::class,
Regex::class => InvokableFactory::class,
Sitemap\Changefreq::class => InvokableFactory::class,
Sitemap\Lastmod::class => InvokableFactory::class,
Sitemap\Loc::class => InvokableFactory::class,
Sitemap\Priority::class => InvokableFactory::class,
StringLength::class => InvokableFactory::class,
Step::class => InvokableFactory::class,
Timezone::class => InvokableFactory::class,
Uri::class => InvokableFactory::class,
Uuid::class => InvokableFactory::class,
// v2 canonical FQCNs
'laminasvalidatorbarcodecode25interleaved' => InvokableFactory::class,
'laminasvalidatorbarcodecode25' => InvokableFactory::class,
'laminasvalidatorbarcodecode39ext' => InvokableFactory::class,
'laminasvalidatorbarcodecode39' => InvokableFactory::class,
'laminasvalidatorbarcodecode93ext' => InvokableFactory::class,
'laminasvalidatorbarcodecode93' => InvokableFactory::class,
'laminasvalidatorbarcodeean12' => InvokableFactory::class,
'laminasvalidatorbarcodeean13' => InvokableFactory::class,
'laminasvalidatorbarcodeean14' => InvokableFactory::class,
'laminasvalidatorbarcodeean18' => InvokableFactory::class,
'laminasvalidatorbarcodeean2' => InvokableFactory::class,
'laminasvalidatorbarcodeean5' => InvokableFactory::class,
'laminasvalidatorbarcodeean8' => InvokableFactory::class,
'laminasvalidatorbarcodegtin12' => InvokableFactory::class,
'laminasvalidatorbarcodegtin13' => InvokableFactory::class,
'laminasvalidatorbarcodegtin14' => InvokableFactory::class,
'laminasvalidatorbarcodeidentcode' => InvokableFactory::class,
'laminasvalidatorbarcodeintelligentmail' => InvokableFactory::class,
'laminasvalidatorbarcodeissn' => InvokableFactory::class,
'laminasvalidatorbarcodeitf14' => InvokableFactory::class,
'laminasvalidatorbarcodeleitcode' => InvokableFactory::class,
'laminasvalidatorbarcodeplanet' => InvokableFactory::class,
'laminasvalidatorbarcodepostnet' => InvokableFactory::class,
'laminasvalidatorbarcoderoyalmail' => InvokableFactory::class,
'laminasvalidatorbarcodesscc' => InvokableFactory::class,
'laminasvalidatorbarcodeupca' => InvokableFactory::class,
'laminasvalidatorbarcodeupce' => InvokableFactory::class,
'laminasvalidatorbarcode' => InvokableFactory::class,
'laminasvalidatorbetween' => InvokableFactory::class,
'laminasvalidatorbitwise' => InvokableFactory::class,
'laminasvalidatorcallback' => InvokableFactory::class,
'laminasvalidatorcreditcard' => InvokableFactory::class,
'laminasvalidatorcsrf' => InvokableFactory::class,
'laminasvalidatordatestep' => InvokableFactory::class,
'laminasvalidatordate' => InvokableFactory::class,
'laminasvalidatordbnorecordexists' => InvokableFactory::class,
'laminasvalidatordbrecordexists' => InvokableFactory::class,
'laminasvalidatordigits' => InvokableFactory::class,
'laminasvalidatoremailaddress' => InvokableFactory::class,
'laminasvalidatorexplode' => InvokableFactory::class,
'laminasvalidatorfilecount' => InvokableFactory::class,
'laminasvalidatorfilecrc32' => InvokableFactory::class,
'laminasvalidatorfileexcludeextension' => InvokableFactory::class,
'laminasvalidatorfileexcludemimetype' => InvokableFactory::class,
'laminasvalidatorfileexists' => InvokableFactory::class,
'laminasvalidatorfileextension' => InvokableFactory::class,
'laminasvalidatorfilefilessize' => InvokableFactory::class,
'laminasvalidatorfilehash' => InvokableFactory::class,
'laminasvalidatorfileimagesize' => InvokableFactory::class,
'laminasvalidatorfileiscompressed' => InvokableFactory::class,
'laminasvalidatorfileisimage' => InvokableFactory::class,
'laminasvalidatorfilemd5' => InvokableFactory::class,
'laminasvalidatorfilemimetype' => InvokableFactory::class,
'laminasvalidatorfilenotexists' => InvokableFactory::class,
'laminasvalidatorfilesha1' => InvokableFactory::class,
'laminasvalidatorfilesize' => InvokableFactory::class,
'laminasvalidatorfileupload' => InvokableFactory::class,
'laminasvalidatorfileuploadfile' => InvokableFactory::class,
'laminasvalidatorfilewordcount' => InvokableFactory::class,
'laminasvalidatorgpspoint' => InvokableFactory::class,
'laminasvalidatorgreaterthan' => InvokableFactory::class,
'laminasvalidatorhex' => InvokableFactory::class,
'laminasvalidatorhostname' => InvokableFactory::class,
'laminasi18nvalidatoralnum' => InvokableFactory::class,
'laminasi18nvalidatoralpha' => InvokableFactory::class,
'laminasi18nvalidatordatetime' => InvokableFactory::class,
'laminasi18nvalidatorisfloat' => InvokableFactory::class,
'laminasi18nvalidatorisint' => InvokableFactory::class,
'laminasi18nvalidatorphonenumber' => InvokableFactory::class,
'laminasi18nvalidatorpostcode' => InvokableFactory::class,
'laminasvalidatoriban' => InvokableFactory::class,
'laminasvalidatoridentical' => InvokableFactory::class,
'laminasvalidatorinarray' => InvokableFactory::class,
'laminasvalidatorip' => InvokableFactory::class,
'laminasvalidatorisbn' => InvokableFactory::class,
'laminasvalidatoriscountable' => InvokableFactory::class,
'laminasvalidatorisinstanceof' => InvokableFactory::class,
'laminasvalidatorlessthan' => InvokableFactory::class,
'laminasvalidatornotempty' => InvokableFactory::class,
'laminasvalidatorregex' => InvokableFactory::class,
'laminasvalidatorsitemapchangefreq' => InvokableFactory::class,
'laminasvalidatorsitemaplastmod' => InvokableFactory::class,
'laminasvalidatorsitemaploc' => InvokableFactory::class,
'laminasvalidatorsitemappriority' => InvokableFactory::class,
'laminasvalidatorstringlength' => InvokableFactory::class,
'laminasvalidatorstep' => InvokableFactory::class,
'laminasvalidatortimezone' => InvokableFactory::class,
'laminasvalidatoruri' => InvokableFactory::class,
'laminasvalidatoruuid' => InvokableFactory::class,
];
/**
* Whether or not to share by default; default to false (v2)
*
* @var bool
*/
protected $shareByDefault = false;
/**
* Whether or not to share by default; default to false (v3)
*
* @var bool
*/
protected $sharedByDefault = false;
/**
* Default instance type
*
* @var string
*/
protected $instanceOf = ValidatorInterface::class;
/**
* Constructor
*
* After invoking parent constructor, add an initializer to inject the
* attached translator, if any, to the currently requested helper.
*
* {@inheritDoc}
*
* @param ServiceManagerConfiguration $v3config
*/
public function __construct($configOrContainerInstance = null, array $v3config = [])
{
parent::__construct($configOrContainerInstance, $v3config);
$this->addInitializer([$this, 'injectTranslator']);
$this->addInitializer([$this, 'injectValidatorPluginManager']);
}
/**
* Validate plugin instance
*
* {@inheritDoc}
*
* @param mixed $instance
* @psalm-assert InstanceType $instance
*/
public function validate($instance)
{
if (! $instance instanceof $this->instanceOf) {
throw new InvalidServiceException(sprintf(
'%s expects only to create instances of %s; %s is invalid',
static::class,
$this->instanceOf,
get_debug_type($instance)
));
}
}
/**
* For v2 compatibility: validate plugin instance.
*
* Proxies to `validate()`.
*
* @return void
* @throws Exception\RuntimeException
*/
public function validatePlugin(mixed $plugin)
{
try {
$this->validate($plugin);
} catch (InvalidServiceException $e) {
throw new Exception\RuntimeException(sprintf(
'Plugin of type %s is invalid; must implement %s',
get_debug_type($plugin),
ValidatorInterface::class
), $e->getCode(), $e);
}
}
/**
* Inject a validator instance with the registered translator
*
* @param ContainerInterface|object $first
* @param ContainerInterface|object $second
* @return void
*/
public function injectTranslator($first, $second)
{
if ($first instanceof ContainerInterface) {
$container = $first;
$validator = $second;
} else {
$container = $second;
$validator = $first;
}
// V2 means we pull it from the parent container
if ($container === $this && method_exists($container, 'getServiceLocator') && $container->getServiceLocator()) {
$container = $container->getServiceLocator();
}
if ($validator instanceof Translator\TranslatorAwareInterface) {
if ($container && $container->has('MvcTranslator')) {
$validator->setTranslator($container->get('MvcTranslator'));
}
}
}
/**
* Inject a validator plugin manager
*
* @param ContainerInterface|object $first
* @param ContainerInterface|object $second
* @return void
*/
public function injectValidatorPluginManager($first, $second)
{
if ($first instanceof ContainerInterface) {
$validator = $second;
} else {
$validator = $first;
}
if ($validator instanceof ValidatorPluginManagerAwareInterface) {
$validator->setValidatorPluginManager($this);
}
}
}
laminas-validator/src/Module.php 0000644 00000002042 15240152636 0012702 0 ustar 00 <?php
namespace Laminas\Validator;
use Laminas\ModuleManager\ModuleManager;
class Module
{
/**
* Return default laminas-validator configuration for laminas-mvc applications.
*
* @return array[]
* @psalm-return array{service_manager: array}
*/
public function getConfig()
{
$provider = new ConfigProvider();
return [
'service_manager' => $provider->getDependencyConfig(),
];
}
/**
* Register a specification for the ValidatorManager with the ServiceListener.
*
* @param ModuleManager $moduleManager
* @return void
*/
public function init($moduleManager)
{
$event = $moduleManager->getEvent();
$container = $event->getParam('ServiceManager');
$serviceListener = $container->get('ServiceListener');
$serviceListener->addServiceManager(
'ValidatorManager',
'validators',
ValidatorProviderInterface::class,
'getValidatorConfig'
);
}
}
laminas-validator/src/Bitwise.php 0000644 00000011264 15240152636 0013071 0 ustar 00 <?php // phpcs:disable WebimpressCodingStandard.Formatting.Reference.UnexpectedSpace
namespace Laminas\Validator;
use Traversable;
use function array_shift;
use function func_get_args;
use function is_array;
use function iterator_to_array;
class Bitwise extends AbstractValidator
{
public const OP_AND = 'and';
public const OP_XOR = 'xor';
public const NOT_AND = 'notAnd';
public const NOT_AND_STRICT = 'notAndStrict';
public const NOT_XOR = 'notXor';
public const NO_OP = 'noOp';
/** @var int */
protected $control;
/**
* Validation failure message template definitions
*
* @var array<string, string>
*/
protected $messageTemplates = [
self::NOT_AND => "The input has no common bit set with '%control%'",
self::NOT_AND_STRICT => "The input doesn't have the same bits set as '%control%'",
self::NOT_XOR => "The input has common bit set with '%control%'",
self::NO_OP => "No operator was present to compare '%control%' against",
];
/**
* Additional variables available for validation failure messages
*
* @var array<string, string>
*/
protected $messageVariables = [
'control' => 'control',
];
/** @var null|int */
protected $operator;
/** @var bool */
protected $strict = false;
/**
* Sets validator options
* Accepts the following option keys:
* 'control' => int
* 'operator' =>
* 'strict' => bool
*
* @param array|Traversable $options
*/
public function __construct($options = null)
{
if ($options instanceof Traversable) {
$options = iterator_to_array($options);
}
if (! is_array($options)) {
$options = func_get_args();
$temp['control'] = array_shift($options);
if (! empty($options)) {
$temp['operator'] = array_shift($options);
}
if (! empty($options)) {
$temp['strict'] = array_shift($options);
}
$options = $temp;
}
parent::__construct($options);
}
/**
* Returns the control parameter.
*
* @return integer
*/
public function getControl()
{
return $this->control;
}
/**
* Returns the operator parameter.
*
* @return null|int
*/
public function getOperator()
{
return $this->operator;
}
/**
* Returns the strict parameter.
*
* @return boolean
*/
public function getStrict()
{
return $this->strict;
}
/**
* Returns true if and only if $value is between min and max options, inclusively
* if inclusive option is true.
*
* @param mixed $value
* @return bool
*/
public function isValid($value)
{
$this->setValue($value);
if (self::OP_AND === $this->operator) {
if ($this->strict) {
// All the bits set in value must be set in control
$result = ($this->control & $value) === $value;
if (! $result) {
$this->error(self::NOT_AND_STRICT);
}
return $result;
}
// At least one of the bits must be common between value and control
$result = (bool) ($this->control & $value);
if (! $result) {
$this->error(self::NOT_AND);
}
return $result;
}
if (self::OP_XOR === $this->operator) {
// Parentheses are required due to order of operations with bitwise operations
// phpcs:ignore WebimpressCodingStandard.Formatting.RedundantParentheses.SingleEquality
$result = ($this->control ^ $value) === ($this->control | $value);
if (! $result) {
$this->error(self::NOT_XOR);
}
return $result;
}
$this->error(self::NO_OP);
return false;
}
/**
* Sets the control parameter.
*
* @param integer $control
* @return $this
*/
public function setControl($control)
{
$this->control = (int) $control;
return $this;
}
/**
* Sets the operator parameter.
*
* @param string $operator
* @return $this
*/
public function setOperator($operator)
{
$this->operator = $operator;
return $this;
}
/**
* Sets the strict parameter.
*
* @param boolean $strict
* @return $this
*/
public function setStrict($strict)
{
$this->strict = (bool) $strict;
return $this;
}
}
laminas-validator/src/InArray.php 0000644 00000016250 15240152636 0013030 0 ustar 00 <?php
namespace Laminas\Validator;
use RecursiveArrayIterator;
use RecursiveIteratorIterator;
use function in_array;
use function is_bool;
use function is_float;
use function is_int;
use function is_string;
class InArray extends AbstractValidator
{
public const NOT_IN_ARRAY = 'notInArray';
// Type of Strict check
/**
* standard in_array strict checking value and type
*/
public const COMPARE_STRICT = 1;
/**
* Non strict check but prevents "asdf" == 0 returning TRUE causing false/positive.
* This is the most secure option for non-strict checks and replaces strict = false
* This will only be effective when the input is a string
*/
public const COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY = 0;
/**
* Standard non-strict check where "asdf" == 0 returns TRUE
* This will be wanted when comparing "0" against int 0
*/
public const COMPARE_NOT_STRICT = -1;
/** @var array<string, string> */
protected $messageTemplates = [
self::NOT_IN_ARRAY => 'The input was not found in the haystack',
];
/**
* Haystack of possible values
*
* @var array
*/
protected $haystack;
/**
* Type of strict check to be used. Due to "foo" == 0 === TRUE with in_array when strict = false,
* an option has been added to prevent this. When $strict = 0/false, the most
* secure non-strict check is implemented. if $strict = -1, the default in_array non-strict
* behaviour is used
*
* @var int
*/
protected $strict = self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY;
/**
* Whether a recursive search should be done
*
* @var bool
*/
protected $recursive = false;
/**
* Returns the haystack option
*
* @return mixed
* @throws Exception\RuntimeException If haystack option is not set.
*/
public function getHaystack()
{
if ($this->haystack === null) {
throw new Exception\RuntimeException('haystack option is mandatory');
}
return $this->haystack;
}
/**
* Sets the haystack option
*
* @param mixed $haystack
* @return $this Provides a fluent interface
*/
public function setHaystack(array $haystack)
{
$this->haystack = $haystack;
return $this;
}
/**
* Returns the strict option
*
* @return bool|int
*/
public function getStrict()
{
// To keep BC with new strict modes
if (
$this->strict === self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY
|| $this->strict === self::COMPARE_STRICT
) {
return (bool) $this->strict;
}
return $this->strict;
}
/**
* Sets the strict option mode
* InArray::COMPARE_STRICT
* InArray::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY
* InArray::COMPARE_NOT_STRICT
*
* @param int|bool $strict
* @return $this Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setStrict($strict)
{
if (is_bool($strict)) {
$strict = $strict ? self::COMPARE_STRICT : self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY;
}
$checkTypes = [
self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY, // 0
self::COMPARE_STRICT, // 1
self::COMPARE_NOT_STRICT, // -1
];
// validate strict value
if (! in_array($strict, $checkTypes)) {
throw new Exception\InvalidArgumentException('Strict option must be one of the COMPARE_ constants');
}
$this->strict = $strict;
return $this;
}
/**
* Returns the recursive option
*
* @return bool
*/
public function getRecursive()
{
return $this->recursive;
}
/**
* Sets the recursive option
*
* @param bool $recursive
* @return $this Provides a fluent interface
*/
public function setRecursive($recursive)
{
$this->recursive = (bool) $recursive;
return $this;
}
/**
* Returns true if and only if $value is contained in the haystack option. If the strict
* option is true, then the type of $value is also checked.
*
* @param mixed $value
* See {@link http://php.net/manual/function.in-array.php#104501}
* @return bool
*/
public function isValid($value)
{
// we create a copy of the haystack in case we need to modify it
$haystack = $this->getHaystack();
// if the input is a string or float, and vulnerability protection is on
// we type cast the input to a string
if (
self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY === $this->strict
&& (is_int($value) || is_float($value))
) {
$value = (string) $value;
}
$this->setValue($value);
if ($this->getRecursive()) {
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($haystack));
foreach ($iterator as $element) {
if (self::COMPARE_STRICT === $this->strict) {
if ($element === $value) {
return true;
}
continue;
}
// add protection to prevent string to int vuln's
$el = $element;
if (
self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY === $this->strict
&& is_string($value) && (is_int($el) || is_float($el))
) {
$el = (string) $el;
}
// phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator
if ($el == $value) {
return true;
}
}
$this->error(self::NOT_IN_ARRAY);
return false;
}
/**
* If the check is not strict, then, to prevent "asdf" being converted to 0
* and returning a false positive if 0 is in haystack, we type cast
* the haystack to strings. To prevent "56asdf" == 56 === TRUE we also
* type cast values like 56 to strings as well.
*
* This occurs only if the input is a string and a haystack member is an int
*/
if (
self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY === $this->strict
&& is_string($value)
) {
foreach ($haystack as &$h) {
if (is_int($h) || is_float($h)) {
$h = (string) $h;
}
}
if (in_array($value, $haystack, (bool) $this->strict)) {
return true;
}
$this->error(self::NOT_IN_ARRAY);
return false;
}
if (in_array($value, $haystack, self::COMPARE_STRICT === $this->strict)) {
return true;
}
if (self::COMPARE_NOT_STRICT === $this->strict) {
return true;
}
$this->error(self::NOT_IN_ARRAY);
return false;
}
}
laminas-validator/src/Isbn/Isbn10.php 0000644 00000001617 15240152636 0013413 0 ustar 00 <?php
namespace Laminas\Validator\Isbn;
class Isbn10
{
/**
* @param string $value
* @return int|string
*/
public function getChecksum($value)
{
$sum = $this->sum($value);
return $this->checksum($sum);
}
/**
* Calculate the value sum.
*
* @param string $value
* @return int
*/
private function sum($value)
{
$sum = 0;
for ($i = 0; $i < 9; $i++) {
$sum += (10 - $i) * (int) $value[$i];
}
return $sum;
}
/**
* Calculate the checksum for the value's sum.
*
* @param int $sum
* @return int|string
*/
private function checksum($sum)
{
$checksum = 11 - ($sum % 11);
if ($checksum === 11) {
return '0';
}
if ($checksum === 10) {
return 'X';
}
return $checksum;
}
}
laminas-validator/src/Isbn/Isbn13.php 0000644 00000001670 15240152636 0013415 0 ustar 00 <?php
namespace Laminas\Validator\Isbn;
class Isbn13
{
/**
* @param string $value
* @return int|string
*/
public function getChecksum($value)
{
$sum = $this->sum($value);
return $this->checksum($sum);
}
/**
* Calculate the value sum.
*
* @param string $value
* @return int
*/
private function sum($value)
{
$sum = 0;
for ($i = 0; $i < 12; $i++) {
if ($i % 2 === 0) {
$sum += (int) $value[$i];
continue;
}
$sum += 3 * (int) $value[$i];
}
return $sum;
}
/**
* Calculate the checksum for the value's sum.
*
* @param int $sum
* @return int|string
*/
private function checksum($sum)
{
$checksum = 10 - ($sum % 10);
if ($checksum === 10) {
return '0';
}
return $checksum;
}
}
laminas-validator/src/Db/RecordExists.php 0000644 00000001347 15240152637 0014430 0 ustar 00 <?php
namespace Laminas\Validator\Db;
use Laminas\Validator\Exception;
/**
* Confirms a record exists in a table.
*/
class RecordExists extends AbstractDb
{
/**
* @param mixed $value
* @return bool
*/
public function isValid($value)
{
/*
* Check for an adapter being defined. If not, throw an exception.
*/
if (null === $this->adapter) {
throw new Exception\RuntimeException('No database adapter present');
}
$valid = true;
$this->setValue($value);
$result = $this->query($value);
if (! $result) {
$valid = false;
$this->error(self::ERROR_NO_RECORD_FOUND);
}
return $valid;
}
}
laminas-validator/src/Db/NoRecordExists.php 0000644 00000001354 15240152637 0014723 0 ustar 00 <?php
namespace Laminas\Validator\Db;
use Laminas\Validator\Exception;
/**
* Confirms a record does not exist in a table.
*/
class NoRecordExists extends AbstractDb
{
/**
* @param mixed $value
* @return bool
*/
public function isValid($value)
{
/*
* Check for an adapter being defined. If not, throw an exception.
*/
if (null === $this->adapter) {
throw new Exception\RuntimeException('No database adapter present');
}
$valid = true;
$this->setValue($value);
$result = $this->query($value);
if ($result) {
$valid = false;
$this->error(self::ERROR_RECORD_FOUND);
}
return $valid;
}
}
laminas-validator/src/Db/AbstractDb.php 0000644 00000020212 15240152637 0014013 0 ustar 00 <?php
namespace Laminas\Validator\Db;
use Laminas\Db\Adapter\Adapter as DbAdapter;
use Laminas\Db\Adapter\AdapterAwareInterface;
use Laminas\Db\Adapter\AdapterAwareTrait;
use Laminas\Db\Sql\Select;
use Laminas\Db\Sql\Sql;
use Laminas\Db\Sql\TableIdentifier;
use Laminas\Stdlib\ArrayUtils;
use Laminas\Validator\AbstractValidator;
use Laminas\Validator\Exception;
use Laminas\Validator\Exception\InvalidArgumentException;
use Laminas\Validator\Exception\RuntimeException;
use Traversable;
use function array_key_exists;
use function array_shift;
use function func_get_args;
use function func_num_args;
use function is_array;
/**
* Class for Database record validation
*/
abstract class AbstractDb extends AbstractValidator implements AdapterAwareInterface
{
use AdapterAwareTrait;
/**
* Error constants
*/
public const ERROR_NO_RECORD_FOUND = 'noRecordFound';
public const ERROR_RECORD_FOUND = 'recordFound';
/** @var array<string, string> Message templates */
protected $messageTemplates = [
self::ERROR_NO_RECORD_FOUND => 'No record matching the input was found',
self::ERROR_RECORD_FOUND => 'A record matching the input was found',
];
/**
* Select object to use. can be set, or will be auto-generated
*
* @var Select
*/
protected $select;
/** @var string */
protected $schema;
/** @var string */
protected $table = '';
/** @var string */
protected $field = '';
/** @var mixed */
protected $exclude;
/**
* Provides basic configuration for use with Laminas\Validator\Db Validators
* Setting $exclude allows a single record to be excluded from matching.
* Exclude can either be a String containing a where clause, or an array with `field` and `value` keys
* to define the where clause added to the sql.
* A database adapter may optionally be supplied to avoid using the registered default adapter.
*
* The following option keys are supported:
* 'table' => The database table to validate against
* 'schema' => The schema keys
* 'field' => The field to check for a match
* 'exclude' => An optional where clause or field/value pair to exclude from the query
* 'adapter' => An optional database adapter to use
*
* @param array|Traversable|Select $options Options to use for this validator
* @throws InvalidArgumentException
*/
public function __construct($options = null)
{
parent::__construct($options);
if ($options instanceof Select) {
$this->setSelect($options);
return;
}
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
} elseif (func_num_args() > 1) {
$options = func_get_args();
$firstArgument = array_shift($options);
if (is_array($firstArgument)) {
$temp = ArrayUtils::iteratorToArray($firstArgument);
} else {
$temp['table'] = $firstArgument;
}
$temp['field'] = array_shift($options);
if (! empty($options)) {
$temp['exclude'] = array_shift($options);
}
if (! empty($options)) {
$temp['adapter'] = array_shift($options);
}
$options = $temp;
}
if (! array_key_exists('table', $options) && ! array_key_exists('schema', $options)) {
throw new Exception\InvalidArgumentException('Table or Schema option missing!');
}
if (! array_key_exists('field', $options)) {
throw new Exception\InvalidArgumentException('Field option missing!');
}
if (array_key_exists('adapter', $options)) {
$this->setAdapter($options['adapter']);
}
if (array_key_exists('exclude', $options)) {
$this->setExclude($options['exclude']);
}
$this->setField($options['field']);
if (array_key_exists('table', $options)) {
$this->setTable($options['table']);
}
if (array_key_exists('schema', $options)) {
$this->setSchema($options['schema']);
}
}
/**
* Returns the set adapter
*
* @throws RuntimeException When no database adapter is defined.
* @return DbAdapter
*/
public function getAdapter()
{
return $this->adapter;
}
/**
* Sets a new database adapter
*
* @return self Provides a fluent interface
*/
public function setAdapter(DbAdapter $adapter)
{
return $this->setDbAdapter($adapter);
}
/**
* Returns the set exclude clause
*
* @return string|array
*/
public function getExclude()
{
return $this->exclude;
}
/**
* Sets a new exclude clause
*
* @param string|array $exclude
* @return $this Provides a fluent interface
*/
public function setExclude($exclude)
{
$this->exclude = $exclude;
$this->select = null;
return $this;
}
/**
* Returns the set field
*
* @return string|array
*/
public function getField()
{
return $this->field;
}
/**
* Sets a new field
*
* @param string $field
* @return $this
*/
public function setField($field)
{
$this->field = (string) $field;
$this->select = null;
return $this;
}
/**
* Returns the set table
*
* @return string
*/
public function getTable()
{
return $this->table;
}
/**
* Sets a new table
*
* @param string $table
* @return $this Provides a fluent interface
*/
public function setTable($table)
{
$this->table = (string) $table;
$this->select = null;
return $this;
}
/**
* Returns the set schema
*
* @return string
*/
public function getSchema()
{
return $this->schema;
}
/**
* Sets a new schema
*
* @param string $schema
* @return $this Provides a fluent interface
*/
public function setSchema($schema)
{
$this->schema = $schema;
$this->select = null;
return $this;
}
/**
* Sets the select object to be used by the validator
*
* @return $this Provides a fluent interface
*/
public function setSelect(Select $select)
{
$this->select = $select;
return $this;
}
/**
* Gets the select object to be used by the validator.
* If no select object was supplied to the constructor,
* then it will auto-generate one from the given table,
* schema, field, and adapter options.
*
* @return Select The Select object which will be used
*/
public function getSelect()
{
if ($this->select instanceof Select) {
return $this->select;
}
// Build select object
$select = new Select();
$tableIdentifier = new TableIdentifier($this->table, $this->schema);
$select->from($tableIdentifier)->columns([$this->field]);
$select->where->equalTo($this->field, null);
if ($this->exclude !== null) {
if (is_array($this->exclude)) {
$select->where->notEqualTo(
$this->exclude['field'],
$this->exclude['value']
);
} else {
$select->where($this->exclude);
}
}
$this->select = $select;
return $this->select;
}
/**
* Run query and returns matches, or null if no matches are found.
*
* @param string $value
* @return array when matches are found.
*/
protected function query($value)
{
$sql = new Sql($this->getAdapter());
$select = $this->getSelect();
$statement = $sql->prepareStatementForSqlObject($select);
$parameters = $statement->getParameterContainer();
$parameters['where1'] = $value;
$result = $statement->execute();
return $result->current();
}
}
laminas-validator/src/EmailAddress.php 0000644 00000046007 15240152637 0014024 0 ustar 00 <?php
namespace Laminas\Validator;
use Traversable;
use UConverter;
use function array_combine;
use function array_flip;
use function array_keys;
use function array_shift;
use function arsort;
use function checkdnsrr;
use function defined;
use function extension_loaded;
use function func_get_args;
use function function_exists;
use function gethostbynamel;
use function getmxrr;
use function idn_to_ascii;
use function idn_to_utf8;
use function is_array;
use function is_string;
use function preg_match;
use function str_contains;
use function strlen;
use function trim;
use const INTL_IDNA_VARIANT_UTS46;
class EmailAddress extends AbstractValidator
{
public const INVALID = 'emailAddressInvalid';
public const INVALID_FORMAT = 'emailAddressInvalidFormat';
public const INVALID_HOSTNAME = 'emailAddressInvalidHostname';
public const INVALID_MX_RECORD = 'emailAddressInvalidMxRecord';
public const INVALID_SEGMENT = 'emailAddressInvalidSegment';
public const DOT_ATOM = 'emailAddressDotAtom';
public const QUOTED_STRING = 'emailAddressQuotedString';
public const INVALID_LOCAL_PART = 'emailAddressInvalidLocalPart';
public const LENGTH_EXCEEDED = 'emailAddressLengthExceeded';
// phpcs:disable Generic.Files.LineLength.TooLong
/** @var array<string, string> */
protected $messageTemplates = [
self::INVALID => "Invalid type given. String expected",
self::INVALID_FORMAT => "The input is not a valid email address. Use the basic format local-part@hostname",
self::INVALID_HOSTNAME => "'%hostname%' is not a valid hostname for the email address",
self::INVALID_MX_RECORD => "'%hostname%' does not appear to have any valid MX or A records for the email address",
self::INVALID_SEGMENT => "'%hostname%' is not in a routable network segment. The email address should not be resolved from public network",
self::DOT_ATOM => "'%localPart%' can not be matched against dot-atom format",
self::QUOTED_STRING => "'%localPart%' can not be matched against quoted-string format",
self::INVALID_LOCAL_PART => "'%localPart%' is not a valid local part for the email address",
self::LENGTH_EXCEEDED => "The input exceeds the allowed length",
];
// phpcs:enable
/** @var array */
protected $messageVariables = [
'hostname' => 'hostname',
'localPart' => 'localPart',
];
/** @var string */
protected $hostname;
/** @var string */
protected $localPart;
/**
* Returns the found mx record information
*
* @var array
*/
protected $mxRecord = [];
/**
* Internal options array
*
* @var array<string, mixed>
*/
protected $options = [
'useMxCheck' => false,
'useDeepMxCheck' => false,
'useDomainCheck' => true,
'allow' => Hostname::ALLOW_DNS,
'strict' => true,
'hostnameValidator' => null,
];
/**
* Instantiates hostname validator for local use
*
* The following additional option keys are supported:
* 'hostnameValidator' => A hostname validator, see Laminas\Validator\Hostname
* 'allow' => Options for the hostname validator, see Laminas\Validator\Hostname::ALLOW_*
* 'strict' => Whether to adhere to strictest requirements in the spec
* 'useMxCheck' => If MX check should be enabled, boolean
* 'useDeepMxCheck' => If a deep MX check should be done, boolean
*
* @param array|Traversable $options OPTIONAL
*/
public function __construct($options = [])
{
if (! is_array($options)) {
$options = func_get_args();
$temp['allow'] = array_shift($options);
if (! empty($options)) {
$temp['useMxCheck'] = array_shift($options);
}
if (! empty($options)) {
$temp['hostnameValidator'] = array_shift($options);
}
$options = $temp;
}
parent::__construct($options);
}
/**
* Sets the validation failure message template for a particular key
* Adds the ability to set messages to the attached hostname validator
*
* @param string $messageString
* @param string $messageKey OPTIONAL
* @return AbstractValidator Provides a fluent interface
*/
public function setMessage($messageString, $messageKey = null)
{
if ($messageKey === null) {
$this->getHostnameValidator()->setMessage($messageString);
parent::setMessage($messageString);
return $this;
}
if (! isset($this->messageTemplates[$messageKey])) {
$this->getHostnameValidator()->setMessage($messageString, $messageKey);
} else {
parent::setMessage($messageString, $messageKey);
}
return $this;
}
/**
* Returns the set hostname validator
*
* If was not previously set then lazy load a new one
*
* @return Hostname
*/
public function getHostnameValidator()
{
if (! isset($this->options['hostnameValidator'])) {
$this->options['hostnameValidator'] = new Hostname($this->getAllow());
}
return $this->options['hostnameValidator'];
}
/**
* @param Hostname $hostnameValidator OPTIONAL
* @return $this Provides a fluent interface
*/
public function setHostnameValidator(?Hostname $hostnameValidator = null)
{
$this->options['hostnameValidator'] = $hostnameValidator;
return $this;
}
/**
* Returns the allow option of the attached hostname validator
*
* @return int
*/
public function getAllow()
{
return $this->options['allow'];
}
/**
* Sets the allow option of the hostname validator to use
*
* @param int $allow
* @return $this Provides a fluent interface
*/
public function setAllow($allow)
{
$this->options['allow'] = $allow;
if (isset($this->options['hostnameValidator'])) {
$this->options['hostnameValidator']->setAllow($allow);
}
return $this;
}
/**
* Whether MX checking via getmxrr is supported or not
*
* @return bool
*/
public function isMxSupported()
{
return function_exists('getmxrr');
}
/**
* Returns the set validateMx option
*
* @return bool
*/
public function getMxCheck()
{
return $this->options['useMxCheck'];
}
/**
* Set whether we check for a valid MX record via DNS
*
* This only applies when DNS hostnames are validated
*
* @param bool $mx Set allowed to true to validate for MX records, and false to not validate them
* @return $this Fluid Interface
*/
public function useMxCheck($mx)
{
$this->options['useMxCheck'] = (bool) $mx;
return $this;
}
/**
* Returns the set deepMxCheck option
*
* @return bool
*/
public function getDeepMxCheck()
{
return $this->options['useDeepMxCheck'];
}
/**
* Use deep validation for MX records
*
* @param bool $deep Set deep to true to perform a deep validation process for MX records
* @return $this Fluid Interface
*/
public function useDeepMxCheck($deep)
{
$this->options['useDeepMxCheck'] = (bool) $deep;
return $this;
}
/**
* Returns the set domainCheck option
*
* @return bool
*/
public function getDomainCheck()
{
return $this->options['useDomainCheck'];
}
/**
* Sets if the domain should also be checked
* or only the local part of the email address
*
* @param bool $domain
* @return $this Fluid Interface
*/
public function useDomainCheck($domain = true)
{
$this->options['useDomainCheck'] = (bool) $domain;
return $this;
}
/**
* Returns if the given host is reserved
*
* The following addresses are seen as reserved
* '0.0.0.0/8', '10.0.0.0/8', '127.0.0.0/8'
* '100.64.0.0/10'
* '172.16.0.0/12'
* '198.18.0.0/15'
* '169.254.0.0/16', '192.168.0.0/16'
* '192.0.2.0/24', '192.88.99.0/24', '198.51.100.0/24', '203.0.113.0/24'
* '224.0.0.0/4', '240.0.0.0/4'
*
* @see http://en.wikipedia.org/wiki/Reserved_IP_addresses
*
* As of RFC5753 (JAN 2010), the following blocks are no longer reserved:
* - 128.0.0.0/16
* - 191.255.0.0/16
* - 223.255.255.0/24
* @see http://tools.ietf.org/html/rfc5735#page-6
*
* As of RFC6598 (APR 2012), the following blocks are now reserved:
* - 100.64.0.0/10
* @see http://tools.ietf.org/html/rfc6598#section-7
*
* @param string $host
* @return bool Returns false when minimal one of the given addresses is not reserved
*/
protected function isReserved($host)
{
if (! preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $host)) {
$host = gethostbynamel($host);
} else {
$host = [$host];
}
if (empty($host)) {
return false;
}
foreach ($host as $server) {
// @codingStandardsIgnoreStart
// Search for 0.0.0.0/8, 10.0.0.0/8, 127.0.0.0/8
if (!preg_match('/^(0|10|127)(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){3}$/', $server) &&
// Search for 100.64.0.0/10
!preg_match('/^100\.(6[0-4]|[7-9][0-9]|1[0-1][0-9]|12[0-7])(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) &&
// Search for 172.16.0.0/12
!preg_match('/^172\.(1[6-9]|2[0-9]|3[0-1])(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) &&
// Search for 198.18.0.0/15
!preg_match('/^198\.(1[8-9])(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) &&
// Search for 169.254.0.0/16, 192.168.0.0/16
!preg_match('/^(169\.254|192\.168)(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) &&
// Search for 192.0.2.0/24, 192.88.99.0/24, 198.51.100.0/24, 203.0.113.0/24
!preg_match('/^(192\.0\.2|192\.88\.99|198\.51\.100|203\.0\.113)\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$/', $server) &&
// Search for 224.0.0.0/4, 240.0.0.0/4
!preg_match('/^(2(2[4-9]|[3-4][0-9]|5[0-5]))(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){3}$/', $server)
) {
return false;
}
// @codingStandardsIgnoreEnd
}
return true;
}
/**
* Internal method to validate the local part of the email address
*
* @return bool
*/
protected function validateLocalPart()
{
// First try to match the local part on the common dot-atom format
// Dot-atom characters are: 1*atext *("." 1*atext)
// atext: ALPHA / DIGIT / and "!", "#", "$", "%", "&", "'", "*",
// "+", "-", "/", "=", "?", "^", "_", "`", "{", "|", "}", "~"
$atext = 'a-zA-Z0-9\x21\x23\x24\x25\x26\x27\x2a\x2b\x2d\x2f\x3d\x3f\x5e\x5f\x60\x7b\x7c\x7d\x7e';
if (preg_match('/^[' . $atext . ']+(\x2e+[' . $atext . ']+)*$/', $this->localPart)) {
return true;
}
if ($this->validateInternationalizedLocalPart($this->localPart)) {
return true;
}
// Try quoted string format (RFC 5321 Chapter 4.1.2)
// Quoted-string characters are: DQUOTE *(qtext/quoted-pair) DQUOTE
$qtext = '\x20-\x21\x23-\x5b\x5d-\x7e'; // %d32-33 / %d35-91 / %d93-126
$quotedPair = '\x20-\x7e'; // %d92 %d32-126
if (preg_match('/^"([' . $qtext . ']|\x5c[' . $quotedPair . '])*"$/', $this->localPart)) {
return true;
}
$this->error(self::DOT_ATOM);
$this->error(self::QUOTED_STRING);
$this->error(self::INVALID_LOCAL_PART);
return false;
}
/**
* @param string $localPart Address local part to validate.
* @return bool
*/
protected function validateInternationalizedLocalPart($localPart)
{
if (
extension_loaded('intl')
&& false === UConverter::transcode($localPart, 'UTF-8', 'UTF-8')
) {
// invalid utf?
return false;
}
$atext = 'a-zA-Z0-9\x21\x23\x24\x25\x26\x27\x2a\x2b\x2d\x2f\x3d\x3f\x5e\x5f\x60\x7b\x7c\x7d\x7e';
// RFC 6532 extends atext to include non-ascii utf
// @see https://tools.ietf.org/html/rfc6532#section-3.1
$uatext = $atext . '\x{80}-\x{FFFF}';
return (bool) preg_match('/^[' . $uatext . ']+(\x2e+[' . $uatext . ']+)*$/u', $localPart);
}
/**
* Returns the found MX Record information after validation including weight for further processing
*
* @return array
*/
public function getMXRecord()
{
return $this->mxRecord;
}
/**
* Internal method to validate the servers MX records
*
* @return bool|string[]
* @psalm-return bool|list<string>
*/
protected function validateMXRecords()
{
$mxHosts = [];
$weight = [];
$result = getmxrr($this->hostname, $mxHosts, $weight);
if (! empty($mxHosts) && ! empty($weight)) {
$this->mxRecord = array_combine($mxHosts, $weight) ?: [];
} else {
$this->mxRecord = [];
}
arsort($this->mxRecord);
// Fallback to IPv4 hosts if no MX record found (RFC 2821 SS 5).
if (! $result) {
$result = gethostbynamel($this->hostname);
if (is_array($result)) {
$this->mxRecord = array_flip($result);
}
}
if (! $result) {
$this->error(self::INVALID_MX_RECORD);
return $result;
}
if (! $this->options['useDeepMxCheck']) {
return $result;
}
$validAddress = false;
$reserved = true;
foreach (array_keys($this->mxRecord) as $hostname) {
$res = $this->isReserved($hostname);
if (! $res) {
$reserved = false;
}
if (! is_string($hostname) || ! trim($hostname)) {
continue;
}
if (
! $res
&& (checkdnsrr($hostname, 'A')
|| checkdnsrr($hostname, 'AAAA')
|| checkdnsrr($hostname, 'A6'))
) {
$validAddress = true;
break;
}
}
if (! $validAddress) {
$result = false;
$error = $reserved ? self::INVALID_SEGMENT : self::INVALID_MX_RECORD;
$this->error($error);
}
return $result;
}
/**
* Internal method to validate the hostname part of the email address
*
* @return bool|string[]
* @psalm-return bool|list<string>
*/
protected function validateHostnamePart()
{
$hostname = $this->getHostnameValidator()->setTranslator($this->getTranslator())
->isValid($this->hostname);
if (! $hostname) {
$this->error(self::INVALID_HOSTNAME);
// Get messages and errors from hostnameValidator
foreach ($this->getHostnameValidator()->getMessages() as $code => $message) {
$this->abstractOptions['messages'][$code] = $message;
}
} elseif ($this->options['useMxCheck']) {
// MX check on hostname
$hostname = $this->validateMXRecords();
}
return $hostname;
}
/**
* Splits the given value in hostname and local part of the email address
*
* @param string $value Email address to be split
* @return bool Returns false when the email can not be split
*/
protected function splitEmailParts($value)
{
$value = is_string($value) ? $value : '';
// Split email address up and disallow '..'
if (
str_contains($value, '..')
|| ! preg_match('/^(.+)@([^@]+)$/', $value, $matches)
) {
return false;
}
$this->localPart = $matches[1];
$this->hostname = $this->idnToAscii($matches[2]);
return true;
}
/**
* Defined by Laminas\Validator\ValidatorInterface
*
* Returns true if and only if $value is a valid email address
* according to RFC2822
*
* @link http://www.ietf.org/rfc/rfc2822.txt RFC2822
* @link http://www.columbia.edu/kermit/ascii.html US-ASCII characters
*
* @param string $value
* @return bool
*/
public function isValid($value)
{
if (! is_string($value)) {
$this->error(self::INVALID);
return false;
}
$length = true;
$this->setValue($value);
// Split email address up and disallow '..'
if (! $this->splitEmailParts($this->getValue())) {
$this->error(self::INVALID_FORMAT);
return false;
}
if ($this->getOption('strict') && (strlen($this->localPart) > 64) || (strlen($this->hostname) > 255)) {
$length = false;
$this->error(self::LENGTH_EXCEEDED);
}
// Match hostname part
$hostname = false;
if ($this->options['useDomainCheck']) {
$hostname = $this->validateHostnamePart();
}
$local = $this->validateLocalPart();
// If both parts valid, return true
return ($local && $length) && (! $this->options['useDomainCheck'] || $hostname);
}
/**
* Safely convert UTF-8 encoded domain name to ASCII
*
* @param string $email the UTF-8 encoded email
* @return string
*/
protected function idnToAscii($email)
{
if (extension_loaded('intl')) {
if (defined('INTL_IDNA_VARIANT_UTS46')) {
return idn_to_ascii($email, 0, INTL_IDNA_VARIANT_UTS46) ?: $email;
}
return idn_to_ascii($email) ?: $email;
}
return $email;
}
/**
* Safely convert ASCII encoded domain name to UTF-8
*
* @param string $email the ASCII encoded email
* @return string
*/
protected function idnToUtf8($email)
{
if (strlen($email) === 0) {
return $email;
}
if (extension_loaded('intl')) {
// The documentation does not clarify what kind of failure
// can happen in idn_to_utf8. One can assume if the source
// is not IDN encoded, it would fail, but it usually returns
// the source string in those cases.
// But not when the source string is long enough.
// Thus we default to source string ourselves.
if (defined('INTL_IDNA_VARIANT_UTS46')) {
return idn_to_utf8($email, 0, INTL_IDNA_VARIANT_UTS46) ?: $email;
}
return idn_to_utf8($email) ?: $email;
}
return $email;
}
}
laminas-validator/src/ValidatorPluginManagerAwareInterface.php 0000644 00000000565 15240152637 0020666 0 ustar 00 <?php
namespace Laminas\Validator;
interface ValidatorPluginManagerAwareInterface
{
/**
* Set validator plugin manager
*/
public function setValidatorPluginManager(ValidatorPluginManager $pluginManager);
/**
* Get validator plugin manager
*
* @return ValidatorPluginManager
*/
public function getValidatorPluginManager();
}
laminas-validator/src/Hostname.php 0000644 00000175230 15240152637 0013246 0 ustar 00 <?php // phpcs:disable Generic.Files.LineLength.TooLong
namespace Laminas\Validator;
use Laminas\Stdlib\StringUtils;
use function array_key_exists;
use function array_pop;
use function array_shift;
use function chr;
use function count;
use function end;
use function explode;
use function func_get_args;
use function implode;
use function in_array;
use function intval;
use function is_array;
use function is_string;
use function ord;
use function preg_match;
use function prev;
use function reset;
use function str_contains;
use function str_ends_with;
use function str_starts_with;
use function strlen;
use function strrpos;
use function strtolower;
use function strtoupper;
use function substr;
/**
* Please note there are two standalone test scripts for testing IDN characters due to problems
* with file encoding.
*
* The first is tests/Laminas/Validator/HostnameTestStandalone.php which is designed to be run on
* the command line.
*
* The second is tests/Laminas/Validator/HostnameTestForm.php which is designed to be run via HTML
* to allow users to test entering UTF-8 characters in a form.
*/
class Hostname extends AbstractValidator
{
public const CANNOT_DECODE_PUNYCODE = 'hostnameCannotDecodePunycode';
public const INVALID = 'hostnameInvalid';
public const INVALID_DASH = 'hostnameDashCharacter';
public const INVALID_HOSTNAME = 'hostnameInvalidHostname';
public const INVALID_HOSTNAME_SCHEMA = 'hostnameInvalidHostnameSchema';
public const INVALID_LOCAL_NAME = 'hostnameInvalidLocalName';
public const INVALID_URI = 'hostnameInvalidUri';
public const IP_ADDRESS_NOT_ALLOWED = 'hostnameIpAddressNotAllowed';
public const LOCAL_NAME_NOT_ALLOWED = 'hostnameLocalNameNotAllowed';
public const UNDECIPHERABLE_TLD = 'hostnameUndecipherableTld';
public const UNKNOWN_TLD = 'hostnameUnknownTld';
/** @var array */
protected $messageTemplates = [
self::CANNOT_DECODE_PUNYCODE => "The input appears to be a DNS hostname but the given punycode notation cannot be decoded",
self::INVALID => "Invalid type given. String expected",
self::INVALID_DASH => "The input appears to be a DNS hostname but contains a dash in an invalid position",
self::INVALID_HOSTNAME => "The input does not match the expected structure for a DNS hostname",
self::INVALID_HOSTNAME_SCHEMA => "The input appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'",
self::INVALID_LOCAL_NAME => "The input does not appear to be a valid local network name",
self::INVALID_URI => "The input does not appear to be a valid URI hostname",
self::IP_ADDRESS_NOT_ALLOWED => "The input appears to be an IP address, but IP addresses are not allowed",
self::LOCAL_NAME_NOT_ALLOWED => "The input appears to be a local network name but local network names are not allowed",
self::UNDECIPHERABLE_TLD => "The input appears to be a DNS hostname but cannot extract TLD part",
self::UNKNOWN_TLD => "The input appears to be a DNS hostname but cannot match TLD against known list",
];
/** @var array */
protected $messageVariables = [
'tld' => 'tld',
];
public const ALLOW_DNS = 1; // Allows Internet domain names (e.g., example.com)
public const ALLOW_IP = 2; // Allows IP addresses
public const ALLOW_LOCAL = 4; // Allows local network names (e.g., localhost, www.localdomain)
public const ALLOW_URI = 8; // Allows URI hostnames
public const ALLOW_ALL = 15; // Allows all types of hostnames
/**
* Array of valid top-level-domains
* IanaVersion 2022072400
*
* @see ftp://data.iana.org/TLD/tlds-alpha-by-domain.txt List of all TLDs by domain
* @see http://www.iana.org/domains/root/db/ Official list of supported TLDs
*
* @var string[]
*/
protected $validTlds = [
'aaa',
'aarp',
'abarth',
'abb',
'abbott',
'abbvie',
'abc',
'able',
'abogado',
'abudhabi',
'ac',
'academy',
'accenture',
'accountant',
'accountants',
'aco',
'actor',
'ad',
'adac',
'ads',
'adult',
'ae',
'aeg',
'aero',
'aetna',
'af',
'afl',
'africa',
'ag',
'agakhan',
'agency',
'ai',
'aig',
'airbus',
'airforce',
'airtel',
'akdn',
'al',
'alfaromeo',
'alibaba',
'alipay',
'allfinanz',
'allstate',
'ally',
'alsace',
'alstom',
'am',
'amazon',
'americanexpress',
'americanfamily',
'amex',
'amfam',
'amica',
'amsterdam',
'analytics',
'android',
'anquan',
'anz',
'ao',
'aol',
'apartments',
'app',
'apple',
'aq',
'aquarelle',
'ar',
'arab',
'aramco',
'archi',
'army',
'arpa',
'art',
'arte',
'as',
'asda',
'asia',
'associates',
'at',
'athleta',
'attorney',
'au',
'auction',
'audi',
'audible',
'audio',
'auspost',
'author',
'auto',
'autos',
'avianca',
'aw',
'aws',
'ax',
'axa',
'az',
'azure',
'ba',
'baby',
'baidu',
'banamex',
'bananarepublic',
'band',
'bank',
'bar',
'barcelona',
'barclaycard',
'barclays',
'barefoot',
'bargains',
'baseball',
'basketball',
'bauhaus',
'bayern',
'bb',
'bbc',
'bbt',
'bbva',
'bcg',
'bcn',
'bd',
'be',
'beats',
'beauty',
'beer',
'bentley',
'berlin',
'best',
'bestbuy',
'bet',
'bf',
'bg',
'bh',
'bharti',
'bi',
'bible',
'bid',
'bike',
'bing',
'bingo',
'bio',
'biz',
'bj',
'black',
'blackfriday',
'blockbuster',
'blog',
'bloomberg',
'blue',
'bm',
'bms',
'bmw',
'bn',
'bnpparibas',
'bo',
'boats',
'boehringer',
'bofa',
'bom',
'bond',
'boo',
'book',
'booking',
'bosch',
'bostik',
'boston',
'bot',
'boutique',
'box',
'br',
'bradesco',
'bridgestone',
'broadway',
'broker',
'brother',
'brussels',
'bs',
'bt',
'bugatti',
'build',
'builders',
'business',
'buy',
'buzz',
'bv',
'bw',
'by',
'bz',
'bzh',
'ca',
'cab',
'cafe',
'cal',
'call',
'calvinklein',
'cam',
'camera',
'camp',
'cancerresearch',
'canon',
'capetown',
'capital',
'capitalone',
'car',
'caravan',
'cards',
'care',
'career',
'careers',
'cars',
'casa',
'case',
'cash',
'casino',
'cat',
'catering',
'catholic',
'cba',
'cbn',
'cbre',
'cbs',
'cc',
'cd',
'center',
'ceo',
'cern',
'cf',
'cfa',
'cfd',
'cg',
'ch',
'chanel',
'channel',
'charity',
'chase',
'chat',
'cheap',
'chintai',
'christmas',
'chrome',
'church',
'ci',
'cipriani',
'circle',
'cisco',
'citadel',
'citi',
'citic',
'city',
'cityeats',
'ck',
'cl',
'claims',
'cleaning',
'click',
'clinic',
'clinique',
'clothing',
'cloud',
'club',
'clubmed',
'cm',
'cn',
'co',
'coach',
'codes',
'coffee',
'college',
'cologne',
'com',
'comcast',
'commbank',
'community',
'company',
'compare',
'computer',
'comsec',
'condos',
'construction',
'consulting',
'contact',
'contractors',
'cooking',
'cookingchannel',
'cool',
'coop',
'corsica',
'country',
'coupon',
'coupons',
'courses',
'cpa',
'cr',
'credit',
'creditcard',
'creditunion',
'cricket',
'crown',
'crs',
'cruise',
'cruises',
'cu',
'cuisinella',
'cv',
'cw',
'cx',
'cy',
'cymru',
'cyou',
'cz',
'dabur',
'dad',
'dance',
'data',
'date',
'dating',
'datsun',
'day',
'dclk',
'dds',
'de',
'deal',
'dealer',
'deals',
'degree',
'delivery',
'dell',
'deloitte',
'delta',
'democrat',
'dental',
'dentist',
'desi',
'design',
'dev',
'dhl',
'diamonds',
'diet',
'digital',
'direct',
'directory',
'discount',
'discover',
'dish',
'diy',
'dj',
'dk',
'dm',
'dnp',
'do',
'docs',
'doctor',
'dog',
'domains',
'dot',
'download',
'drive',
'dtv',
'dubai',
'dunlop',
'dupont',
'durban',
'dvag',
'dvr',
'dz',
'earth',
'eat',
'ec',
'eco',
'edeka',
'edu',
'education',
'ee',
'eg',
'email',
'emerck',
'energy',
'engineer',
'engineering',
'enterprises',
'epson',
'equipment',
'er',
'ericsson',
'erni',
'es',
'esq',
'estate',
'et',
'etisalat',
'eu',
'eurovision',
'eus',
'events',
'exchange',
'expert',
'exposed',
'express',
'extraspace',
'fage',
'fail',
'fairwinds',
'faith',
'family',
'fan',
'fans',
'farm',
'farmers',
'fashion',
'fast',
'fedex',
'feedback',
'ferrari',
'ferrero',
'fi',
'fiat',
'fidelity',
'fido',
'film',
'final',
'finance',
'financial',
'fire',
'firestone',
'firmdale',
'fish',
'fishing',
'fit',
'fitness',
'fj',
'fk',
'flickr',
'flights',
'flir',
'florist',
'flowers',
'fly',
'fm',
'fo',
'foo',
'food',
'foodnetwork',
'football',
'ford',
'forex',
'forsale',
'forum',
'foundation',
'fox',
'fr',
'free',
'fresenius',
'frl',
'frogans',
'frontdoor',
'frontier',
'ftr',
'fujitsu',
'fun',
'fund',
'furniture',
'futbol',
'fyi',
'ga',
'gal',
'gallery',
'gallo',
'gallup',
'game',
'games',
'gap',
'garden',
'gay',
'gb',
'gbiz',
'gd',
'gdn',
'ge',
'gea',
'gent',
'genting',
'george',
'gf',
'gg',
'ggee',
'gh',
'gi',
'gift',
'gifts',
'gives',
'giving',
'gl',
'glass',
'gle',
'global',
'globo',
'gm',
'gmail',
'gmbh',
'gmo',
'gmx',
'gn',
'godaddy',
'gold',
'goldpoint',
'golf',
'goo',
'goodyear',
'goog',
'google',
'gop',
'got',
'gov',
'gp',
'gq',
'gr',
'grainger',
'graphics',
'gratis',
'green',
'gripe',
'grocery',
'group',
'gs',
'gt',
'gu',
'guardian',
'gucci',
'guge',
'guide',
'guitars',
'guru',
'gw',
'gy',
'hair',
'hamburg',
'hangout',
'haus',
'hbo',
'hdfc',
'hdfcbank',
'health',
'healthcare',
'help',
'helsinki',
'here',
'hermes',
'hgtv',
'hiphop',
'hisamitsu',
'hitachi',
'hiv',
'hk',
'hkt',
'hm',
'hn',
'hockey',
'holdings',
'holiday',
'homedepot',
'homegoods',
'homes',
'homesense',
'honda',
'horse',
'hospital',
'host',
'hosting',
'hot',
'hoteles',
'hotels',
'hotmail',
'house',
'how',
'hr',
'hsbc',
'ht',
'hu',
'hughes',
'hyatt',
'hyundai',
'ibm',
'icbc',
'ice',
'icu',
'id',
'ie',
'ieee',
'ifm',
'ikano',
'il',
'im',
'imamat',
'imdb',
'immo',
'immobilien',
'in',
'inc',
'industries',
'infiniti',
'info',
'ing',
'ink',
'institute',
'insurance',
'insure',
'int',
'international',
'intuit',
'investments',
'io',
'ipiranga',
'iq',
'ir',
'irish',
'is',
'ismaili',
'ist',
'istanbul',
'it',
'itau',
'itv',
'jaguar',
'java',
'jcb',
'je',
'jeep',
'jetzt',
'jewelry',
'jio',
'jll',
'jm',
'jmp',
'jnj',
'jo',
'jobs',
'joburg',
'jot',
'joy',
'jp',
'jpmorgan',
'jprs',
'juegos',
'juniper',
'kaufen',
'kddi',
'ke',
'kerryhotels',
'kerrylogistics',
'kerryproperties',
'kfh',
'kg',
'kh',
'ki',
'kia',
'kids',
'kim',
'kinder',
'kindle',
'kitchen',
'kiwi',
'km',
'kn',
'koeln',
'komatsu',
'kosher',
'kp',
'kpmg',
'kpn',
'kr',
'krd',
'kred',
'kuokgroup',
'kw',
'ky',
'kyoto',
'kz',
'la',
'lacaixa',
'lamborghini',
'lamer',
'lancaster',
'lancia',
'land',
'landrover',
'lanxess',
'lasalle',
'lat',
'latino',
'latrobe',
'law',
'lawyer',
'lb',
'lc',
'lds',
'lease',
'leclerc',
'lefrak',
'legal',
'lego',
'lexus',
'lgbt',
'li',
'lidl',
'life',
'lifeinsurance',
'lifestyle',
'lighting',
'like',
'lilly',
'limited',
'limo',
'lincoln',
'linde',
'link',
'lipsy',
'live',
'living',
'lk',
'llc',
'llp',
'loan',
'loans',
'locker',
'locus',
'loft',
'lol',
'london',
'lotte',
'lotto',
'love',
'lpl',
'lplfinancial',
'lr',
'ls',
'lt',
'ltd',
'ltda',
'lu',
'lundbeck',
'luxe',
'luxury',
'lv',
'ly',
'ma',
'macys',
'madrid',
'maif',
'maison',
'makeup',
'man',
'management',
'mango',
'map',
'market',
'marketing',
'markets',
'marriott',
'marshalls',
'maserati',
'mattel',
'mba',
'mc',
'mckinsey',
'md',
'me',
'med',
'media',
'meet',
'melbourne',
'meme',
'memorial',
'men',
'menu',
'merckmsd',
'mg',
'mh',
'miami',
'microsoft',
'mil',
'mini',
'mint',
'mit',
'mitsubishi',
'mk',
'ml',
'mlb',
'mls',
'mm',
'mma',
'mn',
'mo',
'mobi',
'mobile',
'moda',
'moe',
'moi',
'mom',
'monash',
'money',
'monster',
'mormon',
'mortgage',
'moscow',
'moto',
'motorcycles',
'mov',
'movie',
'mp',
'mq',
'mr',
'ms',
'msd',
'mt',
'mtn',
'mtr',
'mu',
'museum',
'music',
'mutual',
'mv',
'mw',
'mx',
'my',
'mz',
'na',
'nab',
'nagoya',
'name',
'natura',
'navy',
'nba',
'nc',
'ne',
'nec',
'net',
'netbank',
'netflix',
'network',
'neustar',
'new',
'news',
'next',
'nextdirect',
'nexus',
'nf',
'nfl',
'ng',
'ngo',
'nhk',
'ni',
'nico',
'nike',
'nikon',
'ninja',
'nissan',
'nissay',
'nl',
'no',
'nokia',
'northwesternmutual',
'norton',
'now',
'nowruz',
'nowtv',
'np',
'nr',
'nra',
'nrw',
'ntt',
'nu',
'nyc',
'nz',
'obi',
'observer',
'office',
'okinawa',
'olayan',
'olayangroup',
'oldnavy',
'ollo',
'om',
'omega',
'one',
'ong',
'onl',
'online',
'ooo',
'open',
'oracle',
'orange',
'org',
'organic',
'origins',
'osaka',
'otsuka',
'ott',
'ovh',
'pa',
'page',
'panasonic',
'paris',
'pars',
'partners',
'parts',
'party',
'passagens',
'pay',
'pccw',
'pe',
'pet',
'pf',
'pfizer',
'pg',
'ph',
'pharmacy',
'phd',
'philips',
'phone',
'photo',
'photography',
'photos',
'physio',
'pics',
'pictet',
'pictures',
'pid',
'pin',
'ping',
'pink',
'pioneer',
'pizza',
'pk',
'pl',
'place',
'play',
'playstation',
'plumbing',
'plus',
'pm',
'pn',
'pnc',
'pohl',
'poker',
'politie',
'porn',
'post',
'pr',
'pramerica',
'praxi',
'press',
'prime',
'pro',
'prod',
'productions',
'prof',
'progressive',
'promo',
'properties',
'property',
'protection',
'pru',
'prudential',
'ps',
'pt',
'pub',
'pw',
'pwc',
'py',
'qa',
'qpon',
'quebec',
'quest',
'racing',
'radio',
're',
'read',
'realestate',
'realtor',
'realty',
'recipes',
'red',
'redstone',
'redumbrella',
'rehab',
'reise',
'reisen',
'reit',
'reliance',
'ren',
'rent',
'rentals',
'repair',
'report',
'republican',
'rest',
'restaurant',
'review',
'reviews',
'rexroth',
'rich',
'richardli',
'ricoh',
'ril',
'rio',
'rip',
'ro',
'rocher',
'rocks',
'rodeo',
'rogers',
'room',
'rs',
'rsvp',
'ru',
'rugby',
'ruhr',
'run',
'rw',
'rwe',
'ryukyu',
'sa',
'saarland',
'safe',
'safety',
'sakura',
'sale',
'salon',
'samsclub',
'samsung',
'sandvik',
'sandvikcoromant',
'sanofi',
'sap',
'sarl',
'sas',
'save',
'saxo',
'sb',
'sbi',
'sbs',
'sc',
'sca',
'scb',
'schaeffler',
'schmidt',
'scholarships',
'school',
'schule',
'schwarz',
'science',
'scot',
'sd',
'se',
'search',
'seat',
'secure',
'security',
'seek',
'select',
'sener',
'services',
'ses',
'seven',
'sew',
'sex',
'sexy',
'sfr',
'sg',
'sh',
'shangrila',
'sharp',
'shaw',
'shell',
'shia',
'shiksha',
'shoes',
'shop',
'shopping',
'shouji',
'show',
'showtime',
'si',
'silk',
'sina',
'singles',
'site',
'sj',
'sk',
'ski',
'skin',
'sky',
'skype',
'sl',
'sling',
'sm',
'smart',
'smile',
'sn',
'sncf',
'so',
'soccer',
'social',
'softbank',
'software',
'sohu',
'solar',
'solutions',
'song',
'sony',
'soy',
'spa',
'space',
'sport',
'spot',
'sr',
'srl',
'ss',
'st',
'stada',
'staples',
'star',
'statebank',
'statefarm',
'stc',
'stcgroup',
'stockholm',
'storage',
'store',
'stream',
'studio',
'study',
'style',
'su',
'sucks',
'supplies',
'supply',
'support',
'surf',
'surgery',
'suzuki',
'sv',
'swatch',
'swiss',
'sx',
'sy',
'sydney',
'systems',
'sz',
'tab',
'taipei',
'talk',
'taobao',
'target',
'tatamotors',
'tatar',
'tattoo',
'tax',
'taxi',
'tc',
'tci',
'td',
'tdk',
'team',
'tech',
'technology',
'tel',
'temasek',
'tennis',
'teva',
'tf',
'tg',
'th',
'thd',
'theater',
'theatre',
'tiaa',
'tickets',
'tienda',
'tiffany',
'tips',
'tires',
'tirol',
'tj',
'tjmaxx',
'tjx',
'tk',
'tkmaxx',
'tl',
'tm',
'tmall',
'tn',
'to',
'today',
'tokyo',
'tools',
'top',
'toray',
'toshiba',
'total',
'tours',
'town',
'toyota',
'toys',
'tr',
'trade',
'trading',
'training',
'travel',
'travelchannel',
'travelers',
'travelersinsurance',
'trust',
'trv',
'tt',
'tube',
'tui',
'tunes',
'tushu',
'tv',
'tvs',
'tw',
'tz',
'ua',
'ubank',
'ubs',
'ug',
'uk',
'unicom',
'university',
'uno',
'uol',
'ups',
'us',
'uy',
'uz',
'va',
'vacations',
'vana',
'vanguard',
'vc',
've',
'vegas',
'ventures',
'verisign',
'versicherung',
'vet',
'vg',
'vi',
'viajes',
'video',
'vig',
'viking',
'villas',
'vin',
'vip',
'virgin',
'visa',
'vision',
'viva',
'vivo',
'vlaanderen',
'vn',
'vodka',
'volkswagen',
'volvo',
'vote',
'voting',
'voto',
'voyage',
'vu',
'vuelos',
'wales',
'walmart',
'walter',
'wang',
'wanggou',
'watch',
'watches',
'weather',
'weatherchannel',
'webcam',
'weber',
'website',
'wed',
'wedding',
'weibo',
'weir',
'wf',
'whoswho',
'wien',
'wiki',
'williamhill',
'win',
'windows',
'wine',
'winners',
'wme',
'wolterskluwer',
'woodside',
'work',
'works',
'world',
'wow',
'ws',
'wtc',
'wtf',
'xbox',
'xerox',
'xfinity',
'xihuan',
'xin',
'कॉम',
'セール',
'佛山',
'ಭಾರತ',
'慈善',
'集团',
'在线',
'한국',
'ଭାରତ',
'点看',
'คอม',
'ভাৰত',
'ভারত',
'八卦',
'ישראל',
'موقع',
'বাংলা',
'公益',
'公司',
'香格里拉',
'网站',
'移动',
'我爱你',
'москва',
'қаз',
'католик',
'онлайн',
'сайт',
'联通',
'срб',
'бг',
'бел',
'קום',
'时尚',
'微博',
'淡马锡',
'ファッション',
'орг',
'नेट',
'ストア',
'アマゾン',
'삼성',
'சிங்கப்பூர்',
'商标',
'商店',
'商城',
'дети',
'мкд',
'ею',
'ポイント',
'新闻',
'家電',
'كوم',
'中文网',
'中信',
'中国',
'中國',
'娱乐',
'谷歌',
'భారత్',
'ලංකා',
'電訊盈科',
'购物',
'クラウド',
'ભારત',
'通販',
'भारतम्',
'भारत',
'भारोत',
'网店',
'संगठन',
'餐厅',
'网络',
'ком',
'укр',
'香港',
'亚马逊',
'诺基亚',
'食品',
'飞利浦',
'台湾',
'台灣',
'手机',
'мон',
'الجزائر',
'عمان',
'ارامكو',
'ایران',
'العليان',
'اتصالات',
'امارات',
'بازار',
'موريتانيا',
'پاکستان',
'الاردن',
'بارت',
'بھارت',
'المغرب',
'ابوظبي',
'البحرين',
'السعودية',
'ڀارت',
'كاثوليك',
'سودان',
'همراه',
'عراق',
'مليسيا',
'澳門',
'닷컴',
'政府',
'شبكة',
'بيتك',
'عرب',
'გე',
'机构',
'组织机构',
'健康',
'ไทย',
'سورية',
'招聘',
'рус',
'рф',
'تونس',
'大拿',
'ລາວ',
'みんな',
'グーグル',
'ευ',
'ελ',
'世界',
'書籍',
'ഭാരതം',
'ਭਾਰਤ',
'网址',
'닷넷',
'コム',
'天主教',
'游戏',
'vermögensberater',
'vermögensberatung',
'企业',
'信息',
'嘉里大酒店',
'嘉里',
'مصر',
'قطر',
'广东',
'இலங்கை',
'இந்தியா',
'հայ',
'新加坡',
'فلسطين',
'政务',
'xxx',
'xyz',
'yachts',
'yahoo',
'yamaxun',
'yandex',
'ye',
'yodobashi',
'yoga',
'yokohama',
'you',
'youtube',
'yt',
'yun',
'za',
'zappos',
'zara',
'zero',
'zip',
'zm',
'zone',
'zuerich',
'zw',
];
/**
* Array for valid Idns
*
* @see http://www.iana.org/domains/idn-tables/ Official list of supported IDN Chars
* (.AC) Ascension Island http://www.nic.ac/pdf/AC-IDN-Policy.pdf
* (.AR) Argentina http://www.nic.ar/faqidn.html
* (.AS) American Samoa http://www.nic.as/idn/chars.cfm
* (.AT) Austria http://www.nic.at/en/service/technical_information/idn/charset_converter/
* (.BIZ) International http://www.iana.org/domains/idn-tables/
* (.BR) Brazil http://registro.br/faq/faq6.html
* (.BV) Bouvett Island http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html
* (.CAT) Catalan http://www.iana.org/domains/idn-tables/tables/cat_ca_1.0.html
* (.CH) Switzerland https://nic.switch.ch/reg/ocView.action?res=EF6GW2JBPVTG67DLNIQXU234MN6SC33JNQQGI7L6#anhang1
* (.CL) Chile http://www.iana.org/domains/idn-tables/tables/cl_latn_1.0.html
* (.COM) International http://www.verisign.com/information-services/naming-services/internationalized-domain-names/index.html
* (.DE) Germany https://www.denic.de/en/know-how/idn-domains/idn-character-list/
* (.DK) Danmark http://www.dk-hostmaster.dk/index.php?id=151
* (.EE) Estonia https://www.iana.org/domains/idn-tables/tables/pl_et-pl_1.0.html
* (.ES) Spain https://www.nic.es/media/2008-05/1210147705287.pdf
* (.FI) Finland http://www.ficora.fi/en/index/palvelut/fiverkkotunnukset/aakkostenkaytto.html
* (.GR) Greece https://grweb.ics.forth.gr/CharacterTable1_en.jsp
* (.HR) Croatia https://www.dns.hr/en/portal/files/Odluka-1,2alfanum-dijak.pdf
* (.HU) Hungary http://www.domain.hu/domain/English/szabalyzat/szabalyzat.html
* (.IL) Israel http://www.isoc.org.il/domains/il-domain-rules.html
* (.INFO) International http://www.nic.info/info/idn
* (.IO) British Indian Ocean Territory http://www.nic.io/IO-IDN-Policy.pdf
* (.IR) Iran http://www.nic.ir/Allowable_Characters_dot-iran
* (.IS) Iceland https://www.isnic.is/en/domain/rules#2
* (.KR) Korea http://www.iana.org/domains/idn-tables/tables/kr_ko-kr_1.0.html
* (.LI) Liechtenstein https://nic.switch.ch/reg/ocView.action?res=EF6GW2JBPVTG67DLNIQXU234MN6SC33JNQQGI7L6#anhang1
* (.LT) Lithuania http://www.domreg.lt/static/doc/public/idn_symbols-en.pdf
* (.MD) Moldova http://www.register.md/
* (.MUSEUM) International http://www.iana.org/domains/idn-tables/tables/museum_latn_1.0.html
* (.NET) International http://www.verisign.com/information-services/naming-services/internationalized-domain-names/index.html
* (.NO) Norway http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html
* (.NU) Niue http://www.worldnames.net/
* (.ORG) International http://www.pir.org/index.php?db=content/FAQs&tbl=FAQs_Registrant&id=2
* (.PE) Peru https://www.nic.pe/nuevas_politicas_faq_2.php
* (.PL) Poland http://www.dns.pl/IDN/allowed_character_sets.pdf
* (.PR) Puerto Rico http://www.nic.pr/idn_rules.asp
* (.PT) Portugal https://online.dns.pt/dns_2008/do?com=DS;8216320233;111;+PAGE(4000058)+K-CAT-CODIGO(C.125)+RCNT(100);
* (.RU) Russia http://www.iana.org/domains/idn-tables/tables/ru_ru-ru_1.0.html
* (.SA) Saudi Arabia http://www.iana.org/domains/idn-tables/tables/sa_ar_1.0.html
* (.SE) Sweden http://www.iis.se/english/IDN_campaignsite.shtml?lang=en
* (.SH) Saint Helena http://www.nic.sh/SH-IDN-Policy.pdf
* (.SJ) Svalbard and Jan Mayen http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html
* (.TH) Thailand http://www.iana.org/domains/idn-tables/tables/th_th-th_1.0.html
* (.TM) Turkmenistan http://www.nic.tm/TM-IDN-Policy.pdf
* (.TR) Turkey https://www.nic.tr/index.php
* (.UA) Ukraine http://www.iana.org/domains/idn-tables/tables/ua_cyrl_1.2.html
* (.VE) Venice http://www.iana.org/domains/idn-tables/tables/ve_es_1.0.html
* (.VN) Vietnam http://www.vnnic.vn/english/5-6-300-2-2-04-20071115.htm#1.%20Introduction
*
* @var array<string, string|array<int, string>>
*/
protected $validIdns = [
'AC' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćĉċčďđēėęěĝġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśŝşšţťŧūŭůűųŵŷźżž]{1,63}$/iu'],
'AR' => [1 => '/^[\x{002d}0-9a-zà-ãç-êìíñ-õü]{1,63}$/iu'],
'AS' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĸĺļľłńņňŋōŏőœŕŗřśŝşšţťŧũūŭůűųŵŷźż]{1,63}$/iu'],
'AT' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿœšž]{1,63}$/iu'],
'BIZ' => 'Hostname/Biz.php',
'BR' => [1 => '/^[\x{002d}0-9a-zà-ãçéíó-õúü]{1,63}$/iu'],
'BV' => [1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'],
'CAT' => [1 => '/^[\x{002d}0-9a-z·àç-éíïòóúü]{1,63}$/iu'],
'CH' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿœ]{1,63}$/iu'],
'CL' => [1 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu'],
'CN' => 'Hostname/Cn.php',
'COM' => 'Hostname/Com.php',
'DE' => [1 => '/^[\x{002d}0-9a-záàăâåäãąāæćĉčċçďđéèĕêěëėęēğĝġģĥħíìĭîïĩįīıĵķĺľļłńňñņŋóòŏôöőõøōœĸŕřŗśŝšşßťţŧúùŭûůüűũųūŵýŷÿźžżðþ]{1,63}$/iu'],
'DK' => [1 => '/^[\x{002d}0-9a-zäåæéöøü]{1,63}$/iu'],
'EE' => [1 => '/^[\x{002d}0-9a-zäõöüšž]{1,63}$/iu'],
'ES' => [1 => '/^[\x{002d}0-9a-zàáçèéíïñòóúü·]{1,63}$/iu'],
'EU' => [
1 => '/^[\x{002d}0-9a-zà-öø-ÿ]{1,63}$/iu',
2 => '/^[\x{002d}0-9a-zāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĺļľŀłńņňʼnŋōŏőœŕŗřśŝšťŧũūŭůűųŵŷźżž]{1,63}$/iu',
3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu',
4 => '/^[\x{002d}0-9a-zΐάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ]{1,63}$/iu',
5 => '/^[\x{002d}0-9a-zабвгдежзийклмнопрстуфхцчшщъыьэюя]{1,63}$/iu',
6 => '/^[\x{002d}0-9a-zἀ-ἇἐ-ἕἠ-ἧἰ-ἷὀ-ὅὐ-ὗὠ-ὧὰ-ὼώᾀ-ᾇᾐ-ᾗᾠ-ᾧᾰ-ᾴᾶᾷῂῃῄῆῇῐ-ῒΐῖῗῠ-ῧῲῳῴῶῷ]{1,63}$/iu',
],
'FI' => [1 => '/^[\x{002d}0-9a-zäåö]{1,63}$/iu'],
'GR' => [1 => '/^[\x{002d}0-9a-zΆΈΉΊΌΎ-ΡΣ-ώἀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼῂῃῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲῳῴῶ-ῼ]{1,63}$/iu'],
'HK' => 'Hostname/Cn.php',
'HR' => [1 => '/^[\x{002d}0-9a-zžćčđš]{1,63}$/iu'],
'HU' => [1 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu'],
'IL' => [
1 => '/^[\x{002d}0-9\x{05D0}-\x{05EA}]{1,63}$/iu',
2 => '/^[\x{002d}0-9a-z]{1,63}$/i',
],
'INFO' => [
1 => '/^[\x{002d}0-9a-zäåæéöøü]{1,63}$/iu',
2 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu',
3 => '/^[\x{002d}0-9a-záæéíðóöúýþ]{1,63}$/iu',
4 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu',
5 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu',
6 => '/^[\x{002d}0-9a-ząčėęįšūųž]{1,63}$/iu',
7 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu',
8 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu',
],
'IO' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'],
'IS' => [1 => '/^[\x{002d}0-9a-záéýúíóþæöð]{1,63}$/iu'],
'IT' => [1 => '/^[\x{002d}0-9a-zàâäèéêëìîïòôöùûüæœçÿß-]{1,63}$/iu'],
'JP' => 'Hostname/Jp.php',
'KR' => [1 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu'],
'LI' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿœ]{1,63}$/iu'],
'LT' => [1 => '/^[\x{002d}0-9ąčęėįšųūž]{1,63}$/iu'],
'MD' => [1 => '/^[\x{002d}0-9ăâîşţ]{1,63}$/iu'],
'MUSEUM' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćċčďđēėęěğġģħīįıķĺļľłńņňŋōőœŕŗřśşšţťŧūůűųŵŷźżžǎǐǒǔ\x{01E5}\x{01E7}\x{01E9}\x{01EF}ə\x{0292}ẁẃẅỳ]{1,63}$/iu'],
'NET' => 'Hostname/Com.php',
'NO' => [1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'],
'NU' => 'Hostname/Com.php',
'ORG' => [
1 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu',
2 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu',
3 => '/^[\x{002d}0-9a-záäåæéëíðóöøúüýþ]{1,63}$/iu',
4 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu',
5 => '/^[\x{002d}0-9a-ząčėęįšūųž]{1,63}$/iu',
6 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu',
7 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu',
],
'PE' => [1 => '/^[\x{002d}0-9a-zñáéíóúü]{1,63}$/iu'],
'PL' => [
1 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu',
2 => '/^[\x{002d}а-ик-ш\x{0450}ѓѕјљњќџ]{1,63}$/iu',
3 => '/^[\x{002d}0-9a-zâîăşţ]{1,63}$/iu',
4 => '/^[\x{002d}0-9а-яё\x{04C2}]{1,63}$/iu',
5 => '/^[\x{002d}0-9a-zàáâèéêìíîòóôùúûċġħż]{1,63}$/iu',
6 => '/^[\x{002d}0-9a-zàäåæéêòóôöøü]{1,63}$/iu',
7 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu',
8 => '/^[\x{002d}0-9a-zàáâãçéêíòóôõúü]{1,63}$/iu',
9 => '/^[\x{002d}0-9a-zâîăşţ]{1,63}$/iu',
10 => '/^[\x{002d}0-9a-záäéíóôúýčďĺľňŕšťž]{1,63}$/iu',
11 => '/^[\x{002d}0-9a-zçë]{1,63}$/iu',
12 => '/^[\x{002d}0-9а-ик-шђјљњћџ]{1,63}$/iu',
13 => '/^[\x{002d}0-9a-zćčđšž]{1,63}$/iu',
14 => '/^[\x{002d}0-9a-zâçöûüğış]{1,63}$/iu',
15 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu',
16 => '/^[\x{002d}0-9a-zäõöüšž]{1,63}$/iu',
17 => '/^[\x{002d}0-9a-zĉĝĥĵŝŭ]{1,63}$/iu',
18 => '/^[\x{002d}0-9a-zâäéëîô]{1,63}$/iu',
19 => '/^[\x{002d}0-9a-zàáâäåæçèéêëìíîïðñòôöøùúûüýćčłńřśš]{1,63}$/iu',
20 => '/^[\x{002d}0-9a-zäåæõöøüšž]{1,63}$/iu',
21 => '/^[\x{002d}0-9a-zàáçèéìíòóùú]{1,63}$/iu',
22 => '/^[\x{002d}0-9a-zàáéíóöúüőű]{1,63}$/iu',
23 => '/^[\x{002d}0-9ΐά-ώ]{1,63}$/iu',
24 => '/^[\x{002d}0-9a-zàáâåæçèéêëðóôöøüþœ]{1,63}$/iu',
25 => '/^[\x{002d}0-9a-záäéíóöúüýčďěňřšťůž]{1,63}$/iu',
26 => '/^[\x{002d}0-9a-z·àçèéíïòóúü]{1,63}$/iu',
27 => '/^[\x{002d}0-9а-ъьюя\x{0450}\x{045D}]{1,63}$/iu',
28 => '/^[\x{002d}0-9а-яёіў]{1,63}$/iu',
29 => '/^[\x{002d}0-9a-ząčėęįšūųž]{1,63}$/iu',
30 => '/^[\x{002d}0-9a-záäåæéëíðóöøúüýþ]{1,63}$/iu',
31 => '/^[\x{002d}0-9a-zàâæçèéêëîïñôùûüÿœ]{1,63}$/iu',
32 => '/^[\x{002d}0-9а-щъыьэюяёєіїґ]{1,63}$/iu',
33 => '/^[\x{002d}0-9א-ת]{1,63}$/iu',
],
'PR' => [1 => '/^[\x{002d}0-9a-záéíóúñäëïüöâêîôûàèùæçœãõ]{1,63}$/iu'],
'PT' => [1 => '/^[\x{002d}0-9a-záàâãçéêíóôõú]{1,63}$/iu'],
'RS' => [1 => '/^[\x{002d}0-9a-zßáâäçéëíîóôöúüýăąćčďđęěĺľłńňőŕřśşšţťůűźżž]{1,63}$/iu'],
'RU' => [1 => '/^[\x{002d}0-9а-яё]{1,63}$/iu'],
'SA' => [1 => '/^[\x{002d}.0-9\x{0621}-\x{063A}\x{0641}-\x{064A}\x{0660}-\x{0669}]{1,63}$/iu'],
'SE' => [1 => '/^[\x{002d}0-9a-zäåéöü]{1,63}$/iu'],
'SH' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'],
'SI' => [
1 => '/^[\x{002d}0-9a-zà-öø-ÿ]{1,63}$/iu',
2 => '/^[\x{002d}0-9a-zāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĺļľŀłńņňʼnŋōŏőœŕŗřśŝšťŧũūŭůűųŵŷźżž]{1,63}$/iu',
3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu',
],
'SJ' => [1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'],
'TH' => [1 => '/^[\x{002d}0-9a-z\x{0E01}-\x{0E3A}\x{0E40}-\x{0E4D}\x{0E50}-\x{0E59}]{1,63}$/iu'],
'TM' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćĉċčďđēėęěĝġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśŝşšţťŧūŭůűųŵŷźżž]{1,63}$/iu'],
'TW' => 'Hostname/Cn.php',
'TR' => [1 => '/^[\x{002d}0-9a-zğıüşöç]{1,63}$/iu'],
'UA' => [1 => '/^[\x{002d}0-9a-zабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓєѕіїјљњћќѝўџґӂʼ]{1,63}$/iu'],
'VE' => [1 => '/^[\x{002d}0-9a-záéíóúüñ]{1,63}$/iu'],
'VN' => [1 => '/^[ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚÝàáâãèéêìíòóôõùúýĂăĐđĨĩŨũƠơƯư\x{1EA0}-\x{1EF9}]{1,63}$/iu'],
'мон' => [1 => '/^[\x{002d}0-9\x{0430}-\x{044F}]{1,63}$/iu'],
'срб' => [1 => '/^[\x{002d}0-9а-ик-шђјљњћџ]{1,63}$/iu'],
'сайт' => [1 => '/^[\x{002d}0-9а-яёіїѝйўґг]{1,63}$/iu'],
'онлайн' => [1 => '/^[\x{002d}0-9а-яёіїѝйўґг]{1,63}$/iu'],
'中国' => 'Hostname/Cn.php',
'中國' => 'Hostname/Cn.php',
'ලංකා' => [1 => '/^[\x{0d80}-\x{0dff}]{1,63}$/iu'],
'香港' => 'Hostname/Cn.php',
'台湾' => 'Hostname/Cn.php',
'台灣' => 'Hostname/Cn.php',
'امارات' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'],
'الاردن' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'],
'السعودية' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'],
'ไทย' => [1 => '/^[\x{002d}0-9a-z\x{0E01}-\x{0E3A}\x{0E40}-\x{0E4D}\x{0E50}-\x{0E59}]{1,63}$/iu'],
'рф' => [1 => '/^[\x{002d}0-9а-яё]{1,63}$/iu'],
'تونس' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'],
'مصر' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'],
'இலங்கை' => [1 => '/^[\x{0b80}-\x{0bff}]{1,63}$/iu'],
'فلسطين' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'],
'شبكة' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'],
];
/** @var array<string, array<int, int>> */
protected $idnLength = [
'BIZ' => [5 => 17, 11 => 15, 12 => 20],
'CN' => [1 => 20],
'COM' => [3 => 17, 5 => 20],
'HK' => [1 => 15],
'INFO' => [4 => 17],
'KR' => [1 => 17],
'NET' => [3 => 17, 5 => 20],
'ORG' => [6 => 17],
'TW' => [1 => 20],
'امارات' => [1 => 30],
'الاردن' => [1 => 30],
'السعودية' => [1 => 30],
'تونس' => [1 => 30],
'مصر' => [1 => 30],
'فلسطين' => [1 => 30],
'شبكة' => [1 => 30],
'中国' => [1 => 20],
'中國' => [1 => 20],
'香港' => [1 => 20],
'台湾' => [1 => 20],
'台灣' => [1 => 20],
];
/** @var null|false|string */
protected $tld;
/**
* Options for the hostname validator
*
* @var array
*/
protected $options = [
'allow' => self::ALLOW_DNS, // Allow these hostnames
'useIdnCheck' => true, // Check IDN domains
'useTldCheck' => true, // Check TLD elements
'ipValidator' => null, // IP validator to use
];
// phpcs:disable Squiz.Commenting.FunctionComment.ExtraParamComment
/**
* Sets validator options.
*
* @see http://www.iana.org/cctld/specifications-policies-cctlds-01apr02.htm Technical Specifications for ccTLDs
*
* @param array $options OPTIONAL Array of validator options; see Hostname::$options
* @param int $allow OPTIONAL Set what types of hostname to allow (default ALLOW_DNS)
* @param bool $useIdnCheck OPTIONAL Set whether IDN domains are validated (default true)
* @param bool $useTldCheck Set whether the TLD element of a hostname is validated (default true)
* @param Ip $ipValidator OPTIONAL
*/
public function __construct($options = [])
{
// phpcs:enable
if (! is_array($options)) {
$options = func_get_args();
$temp['allow'] = array_shift($options);
if (! empty($options)) {
$temp['useIdnCheck'] = array_shift($options);
}
if (! empty($options)) {
$temp['useTldCheck'] = array_shift($options);
}
if (! empty($options)) {
$temp['ipValidator'] = array_shift($options);
}
$options = $temp;
}
if (! array_key_exists('ipValidator', $options)) {
$options['ipValidator'] = null;
}
parent::__construct($options);
}
/**
* Returns the set ip validator
*
* @return Ip
*/
public function getIpValidator()
{
return $this->options['ipValidator'];
}
/**
* @param Ip $ipValidator OPTIONAL
* @return self
*/
public function setIpValidator(?Ip $ipValidator = null)
{
if ($ipValidator === null) {
$ipValidator = new Ip();
}
$this->options['ipValidator'] = $ipValidator;
return $this;
}
/**
* Returns the allow option
*
* @return int
*/
public function getAllow()
{
return $this->options['allow'];
}
/**
* Sets the allow option
*
* @param int $allow
* @return $this Provides a fluent interface
*/
public function setAllow($allow)
{
$this->options['allow'] = $allow;
return $this;
}
/**
* Returns the set idn option
*
* @return bool
*/
public function getIdnCheck()
{
return $this->options['useIdnCheck'];
}
/**
* Set whether IDN domains are validated
*
* This only applies when DNS hostnames are validated
*
* @param bool $useIdnCheck Set to true to validate IDN domains
* @return $this
*/
public function useIdnCheck($useIdnCheck)
{
$this->options['useIdnCheck'] = (bool) $useIdnCheck;
return $this;
}
/**
* Returns the set tld option
*
* @return bool
*/
public function getTldCheck()
{
return $this->options['useTldCheck'];
}
/**
* Set whether the TLD element of a hostname is validated
*
* This only applies when DNS hostnames are validated
*
* @param bool $useTldCheck Set to true to validate TLD elements
* @return $this
*/
public function useTldCheck($useTldCheck)
{
$this->options['useTldCheck'] = (bool) $useTldCheck;
return $this;
}
/**
* Defined by Interface
*
* Returns true if and only if the $value is a valid hostname with respect to the current allow option
*
* @param string $value
* @return bool
*/
public function isValid($value)
{
if (! is_string($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
// Check input against IP address schema
if (
((preg_match('/^[0-9.]*$/', $value) && str_contains($value, '.'))
|| (preg_match('/^[0-9a-f:.]*$/i', $value) && str_contains($value, ':')))
&& $this->getIpValidator()->setTranslator($this->getTranslator())->isValid($value)
) {
if (! ($this->getAllow() & self::ALLOW_IP)) {
$this->error(self::IP_ADDRESS_NOT_ALLOWED);
return false;
}
return true;
}
// Handle Regex compilation failure that may happen on .biz domain with has @ character, eg: tapi4457@hsoqvf.biz
// Technically, hostname with '@' character is invalid, so mark as invalid immediately
// @see https://github.com/laminas/laminas-validator/issues/8
if (str_contains($value, '@')) {
$this->error(self::INVALID_HOSTNAME);
return false;
}
// Local hostnames are allowed to be partial (ending '.')
if ($this->getAllow() & self::ALLOW_LOCAL) {
if (str_ends_with($value, '.')) {
$value = substr($value, 0, -1);
if (str_ends_with($value, '.')) {
// Empty hostnames (ending '..') are not allowed
$this->error(self::INVALID_LOCAL_NAME);
return false;
}
}
}
$domainParts = explode('.', $value);
// Prevent partial IP V4 addresses (ending '.')
if (
count($domainParts) === 4 && preg_match('/^[0-9.a-e:.]*$/i', $value)
&& $this->getIpValidator()->setTranslator($this->getTranslator())->isValid($value)
) {
$this->error(self::INVALID_LOCAL_NAME);
}
$utf8StrWrapper = StringUtils::getWrapper('UTF-8');
// Check input against DNS hostname schema
if (
count($domainParts) > 1
&& $utf8StrWrapper->strlen($value) >= 4
&& $utf8StrWrapper->strlen($value) <= 254
) {
$status = false;
do {
// First check TLD
$matches = [];
if (
preg_match('/([^.]{2,63})$/u', end($domainParts), $matches)
|| (array_key_exists(end($domainParts), $this->validIdns))
) {
reset($domainParts);
// Hostname characters are: *(label dot)(label dot label); max 254 chars
// label: id-prefix [*ldh{61} id-prefix]; max 63 chars
// id-prefix: alpha / digit
// ldh: alpha / digit / dash
$this->tld = $matches[1];
// Decode Punycode TLD to IDN
if (str_starts_with($this->tld, 'xn--')) {
$this->tld = $this->decodePunycode(substr($this->tld, 4));
if ($this->tld === false) {
return false;
}
} else {
$this->tld = strtoupper($this->tld);
}
// Match TLD against known list
$removedTld = false;
if ($this->getTldCheck()) {
if (
! in_array(strtolower($this->tld), $this->validTlds)
&& ! in_array($this->tld, $this->validTlds)
) {
$this->error(self::UNKNOWN_TLD);
$status = false;
break;
}
// We have already validated that the TLD is fine. We don't want it to go through the below
// checks as new UTF-8 TLDs will incorrectly fail if there is no IDN regex for it.
array_pop($domainParts);
$removedTld = true;
}
/**
* Match against IDN hostnames
* Note: Keep label regex short to avoid issues with long patterns when matching IDN hostnames
*
* @see Hostname\Interface
*/
$regexChars = [0 => '/^[a-z0-9\x2d]{1,63}$/i'];
if ($this->getIdnCheck() && isset($this->validIdns[$this->tld])) {
if (is_string($this->validIdns[$this->tld])) {
$regexChars += include __DIR__ . '/' . $this->validIdns[$this->tld];
} else {
$regexChars += $this->validIdns[$this->tld];
}
}
// Check each hostname part
$check = 0;
$lastDomainPart = end($domainParts);
if (! $removedTld) {
$lastDomainPart = prev($domainParts);
}
foreach ($domainParts as $domainPart) {
// Decode Punycode domain names to IDN
if (str_starts_with($domainPart, 'xn--')) {
$domainPart = $this->decodePunycode(substr($domainPart, 4));
if ($domainPart === false) {
return false;
}
}
// Skip following checks if domain part is empty, as it definitely is not a valid hostname then
if ($domainPart === '') {
$this->error(self::INVALID_HOSTNAME);
$status = false;
break 2;
}
// Check dash (-) does not start, end or appear in 3rd and 4th positions
if (
$utf8StrWrapper->strpos($domainPart, '-') === 0
|| ($utf8StrWrapper->strlen($domainPart) > 2
&& $utf8StrWrapper->strpos($domainPart, '-', 2) === 2
&& $utf8StrWrapper->strpos($domainPart, '-', 3) === 3
)
|| $utf8StrWrapper->substr($domainPart, -1) === '-'
) {
$this->error(self::INVALID_DASH);
$status = false;
break 2;
}
// Check each domain part
$checked = false;
$isSubDomain = $domainPart !== $lastDomainPart;
$partRegexChars = $isSubDomain ? ['/^[a-z0-9_\x2d]{1,63}$/i'] + $regexChars : $regexChars;
foreach ($partRegexChars as $regexKey => $regexChar) {
$status = preg_match($regexChar, $domainPart);
if ($status > 0) {
$length = 63;
if (
array_key_exists($this->tld, $this->idnLength)
&& array_key_exists($regexKey, $this->idnLength[$this->tld])
) {
$length = $this->idnLength[$this->tld];
}
if ($utf8StrWrapper->strlen($domainPart) > $length) {
$this->error(self::INVALID_HOSTNAME);
$status = false;
} else {
$checked = true;
break;
}
}
}
if ($checked) {
++$check;
}
}
// If one of the labels doesn't match, the hostname is invalid
if ($check !== count($domainParts)) {
$this->error(self::INVALID_HOSTNAME_SCHEMA);
$status = false;
}
} else {
// Hostname not long enough
$this->error(self::UNDECIPHERABLE_TLD);
$status = false;
}
} while (false);
// If the input passes as an Internet domain name, and domain names are allowed, then the hostname
// passes validation
if ($status && ($this->getAllow() & self::ALLOW_DNS)) {
return true;
}
} elseif ($this->getAllow() & self::ALLOW_DNS) {
$this->error(self::INVALID_HOSTNAME);
}
// Check for URI Syntax (RFC3986)
if ($this->getAllow() & self::ALLOW_URI) {
if (preg_match("/^([a-zA-Z0-9-._~!$&\'()*+,;=]|%[[:xdigit:]]{2}){1,254}$/i", $value)) {
return true;
}
$this->error(self::INVALID_URI);
}
// Check input against local network name schema; last chance to pass validation
$regexLocal = '/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}[\x2e]{0,1}){1,254}$/';
$status = preg_match($regexLocal, $value);
// If the input passes as a local network name, and local network names are allowed, then the
// hostname passes validation
$allowLocal = $this->getAllow() & self::ALLOW_LOCAL;
if ($status && $allowLocal) {
return true;
}
// If the input does not pass as a local network name, add a message
if (! $status) {
$this->error(self::INVALID_LOCAL_NAME);
}
// If local network names are not allowed, add a message
if ($status && ! $allowLocal) {
$this->error(self::LOCAL_NAME_NOT_ALLOWED);
}
return false;
}
/**
* Decodes a punycode encoded string to it's original utf8 string
* Returns false in case of a decoding failure.
*
* @param string $encoded Punycode encoded string to decode
* @return string|false
*/
protected function decodePunycode($encoded)
{
if (! preg_match('/^[a-z0-9-]+$/i', $encoded)) {
// no punycode encoded string
$this->error(self::CANNOT_DECODE_PUNYCODE);
return false;
}
$decoded = [];
$separator = strrpos($encoded, '-');
if ($separator > 0) {
for ($x = 0; $x < $separator; ++$x) {
// prepare decoding matrix
$decoded[] = ord($encoded[$x]);
}
}
$lengthd = count($decoded);
$lengthe = strlen($encoded);
// decoding
$init = true;
$base = 72;
$index = 0;
$char = 0x80;
for ($indexe = $separator ? $separator + 1 : 0; $indexe < $lengthe; ++$lengthd) {
for ($oldIndex = $index, $pos = 1, $key = 36; 1; $key += 36) {
$hex = ord($encoded[$indexe++]);
$digit = $hex - 48 < 10 ? $hex - 22
: ($hex - 65 < 26 ? $hex - 65
: ($hex - 97 < 26 ? $hex - 97
: 36));
$index += $digit * $pos;
$tag = $key <= $base ? 1 : ($key >= $base + 26 ? 26 : $key - $base);
if ($digit < $tag) {
break;
}
$pos = (int) ($pos * (36 - $tag));
}
$delta = intval($init ? ($index - $oldIndex) / 700 : ($index - $oldIndex) / 2);
$delta += intval($delta / ($lengthd + 1));
for ($key = 0; $delta > 910 / 2; $key += 36) {
$delta = intval($delta / 35);
}
$base = intval($key + 36 * $delta / ($delta + 38));
$init = false;
$char += (int) ($index / ($lengthd + 1));
$index %= $lengthd + 1;
if ($lengthd > 0) {
for ($i = $lengthd; $i > $index; $i--) {
$decoded[$i] = $decoded[$i - 1];
}
}
$decoded[$index++] = $char;
}
// convert decoded ucs4 to utf8 string
foreach ($decoded as $key => $value) {
if ($value < 128) {
$decoded[$key] = chr($value);
} elseif ($value < 1 << 11) {
$decoded[$key] = chr(192 + ($value >> 6));
$decoded[$key] .= chr(128 + ($value & 63));
} elseif ($value < 1 << 16) {
$decoded[$key] = chr(224 + ($value >> 12));
$decoded[$key] .= chr(128 + (($value >> 6) & 63));
$decoded[$key] .= chr(128 + ($value & 63));
} elseif ($value < 1 << 21) {
$decoded[$key] = chr(240 + ($value >> 18));
$decoded[$key] .= chr(128 + (($value >> 12) & 63));
$decoded[$key] .= chr(128 + (($value >> 6) & 63));
$decoded[$key] .= chr(128 + ($value & 63));
} else {
$this->error(self::CANNOT_DECODE_PUNYCODE);
return false;
}
}
return implode($decoded);
}
}
laminas-validator/src/NotEmpty.php 0000644 00000017713 15240152637 0013250 0 ustar 00 <?php
namespace Laminas\Validator;
use Countable;
use Laminas\Stdlib\ArrayUtils;
use Traversable;
use function array_search;
use function array_shift;
use function count;
use function func_get_args;
use function in_array;
use function is_array;
use function is_bool;
use function is_float;
use function is_int;
use function is_object;
use function is_string;
use function method_exists;
use function preg_match;
class NotEmpty extends AbstractValidator
{
public const BOOLEAN = 0b000000000001;
public const INTEGER = 0b000000000010;
public const FLOAT = 0b000000000100;
public const STRING = 0b000000001000;
public const ZERO = 0b000000010000;
public const EMPTY_ARRAY = 0b000000100000;
public const NULL = 0b000001000000;
public const PHP = 0b000001111111;
public const SPACE = 0b000010000000;
public const OBJECT = 0b000100000000;
public const OBJECT_STRING = 0b001000000000;
public const OBJECT_COUNT = 0b010000000000;
public const ALL = 0b011111111111;
public const INVALID = 'notEmptyInvalid';
public const IS_EMPTY = 'isEmpty';
/** @var array<int, string> */
protected $constants = [
self::BOOLEAN => 'boolean',
self::INTEGER => 'integer',
self::FLOAT => 'float',
self::STRING => 'string',
self::ZERO => 'zero',
self::EMPTY_ARRAY => 'array',
self::NULL => 'null',
self::PHP => 'php',
self::SPACE => 'space',
self::OBJECT => 'object',
self::OBJECT_STRING => 'objectstring',
self::OBJECT_COUNT => 'objectcount',
self::ALL => 'all',
];
/**
* Default value for types; value = 0b000111101001
*
* @var array
*/
protected $defaultType = [
self::OBJECT,
self::SPACE,
self::NULL,
self::EMPTY_ARRAY,
self::STRING,
self::BOOLEAN,
];
/** @var array */
protected $messageTemplates = [
self::IS_EMPTY => "Value is required and can't be empty",
self::INVALID => 'Invalid type given. String, integer, float, boolean or array expected',
];
/**
* Options for this validator
*
* @var array
*/
protected $options = [];
/**
* Constructor
*
* @param array|Traversable|int $options OPTIONAL
*/
public function __construct($options = null)
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (! is_array($options)) {
$options = func_get_args();
$temp = [];
if (! empty($options)) {
$temp['type'] = array_shift($options);
}
$options = $temp;
}
if (! isset($options['type'])) {
if (($type = $this->calculateTypeValue($options)) !== 0) {
$options['type'] = $type;
} else {
$options['type'] = $this->defaultType;
}
}
parent::__construct($options);
}
/**
* Returns the set types
*
* @return int
*/
public function getType()
{
return $this->options['type'];
}
/**
* @return false|int|string
*/
public function getDefaultType()
{
return $this->calculateTypeValue($this->defaultType);
}
/**
* @param array|int|string $type
* @return false|int|string
*/
protected function calculateTypeValue($type)
{
if (is_array($type)) {
$detected = 0;
foreach ($type as $value) {
if (is_int($value)) {
$detected |= $value;
} elseif (in_array($value, $this->constants, true)) {
$detected |= (int) array_search($value, $this->constants, true);
}
}
$type = $detected;
} elseif (is_string($type) && in_array($type, $this->constants, true)) {
$type = array_search($type, $this->constants, true);
}
return $type;
}
/**
* Set the types
*
* @param int|int[] $type
* @throws Exception\InvalidArgumentException
* @return $this
*/
public function setType($type = null)
{
$type = $this->calculateTypeValue($type);
if (! is_int($type) || ($type < 0) || ($type > self::ALL)) {
throw new Exception\InvalidArgumentException('Unknown type');
}
$this->options['type'] = $type;
return $this;
}
/**
* Returns true if and only if $value is not an empty value.
*
* @param mixed $value
* @return bool
*/
public function isValid($value)
{
if (
$value !== null
&& ! is_string($value)
&& ! is_int($value)
&& ! is_float($value)
&& ! is_bool($value)
&& ! is_array($value)
&& ! is_object($value)
) {
$this->error(self::INVALID);
return false;
}
$type = $this->getType();
$this->setValue($value);
$object = false;
// OBJECT_COUNT (countable object)
if ($type & self::OBJECT_COUNT) {
$object = true;
if (is_object($value) && $value instanceof Countable && (count($value) === 0)) {
$this->error(self::IS_EMPTY);
return false;
}
}
// OBJECT_STRING (object's toString)
if ($type & self::OBJECT_STRING) {
$object = true;
if (
(is_object($value) && ! method_exists($value, '__toString'))
|| (is_object($value) && method_exists($value, '__toString') && (string) $value === '')
) {
$this->error(self::IS_EMPTY);
return false;
}
}
// OBJECT (object)
// phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedIf
if ($type & self::OBJECT) {
// fall through, objects are always not empty
} elseif ($object === false) {
// object not allowed but object given -> return false
if (is_object($value)) {
$this->error(self::IS_EMPTY);
return false;
}
}
// SPACE (' ')
if ($type & self::SPACE) {
if (is_string($value) && (preg_match('/^\s+$/s', $value))) {
$this->error(self::IS_EMPTY);
return false;
}
}
// NULL (null)
if ($type & self::NULL) {
if ($value === null) {
$this->error(self::IS_EMPTY);
return false;
}
}
// EMPTY_ARRAY (array())
if ($type & self::EMPTY_ARRAY) {
if ($value === []) {
$this->error(self::IS_EMPTY);
return false;
}
}
// ZERO ('0')
if ($type & self::ZERO) {
if ($value === '0') {
$this->error(self::IS_EMPTY);
return false;
}
}
// STRING ('')
if ($type & self::STRING) {
if ($value === '') {
$this->error(self::IS_EMPTY);
return false;
}
}
// FLOAT (0.0)
if ($type & self::FLOAT) {
if ($value === 0.0) {
$this->error(self::IS_EMPTY);
return false;
}
}
// INTEGER (0)
if ($type & self::INTEGER) {
if ($value === 0) {
$this->error(self::IS_EMPTY);
return false;
}
}
// BOOLEAN (false)
if ($type & self::BOOLEAN) {
if ($value === false) {
$this->error(self::IS_EMPTY);
return false;
}
}
return true;
}
}
laminas-validator/src/Identical.php 0000644 00000012207 15240152637 0013356 0 ustar 00 <?php
namespace Laminas\Validator;
use ArrayAccess;
use Laminas\Stdlib\ArrayUtils;
use Traversable;
use function array_key_exists;
use function get_debug_type;
use function is_array;
use function is_int;
use function is_string;
use function key;
use function sprintf;
use function var_export;
class Identical extends AbstractValidator
{
/**
* Error codes
*
* @const string
*/
public const NOT_SAME = 'notSame';
public const MISSING_TOKEN = 'missingToken';
/**
* Error messages
*
* @var array
*/
protected $messageTemplates = [
self::NOT_SAME => 'The two given tokens do not match',
self::MISSING_TOKEN => 'No token was provided to match against',
];
/** @var array */
protected $messageVariables = [
'token' => 'tokenString',
];
/**
* Original token against which to validate
*
* @var null|string
*/
protected $tokenString;
/** @var null|string */
protected $token;
/** @var bool */
protected $strict = true;
/** @var bool */
protected $literal = false;
/**
* Sets validator options
*
* @param mixed $token
*/
public function __construct($token = null)
{
if ($token instanceof Traversable) {
$token = ArrayUtils::iteratorToArray($token);
}
if (is_array($token) && array_key_exists('token', $token)) {
if (array_key_exists('strict', $token)) {
$this->setStrict($token['strict']);
}
if (array_key_exists('literal', $token)) {
$this->setLiteral($token['literal']);
}
$this->setToken($token['token']);
} elseif (null !== $token) {
$this->setToken($token);
}
parent::__construct(is_array($token) ? $token : null);
}
/**
* Retrieve token
*
* @return mixed
*/
public function getToken()
{
return $this->token;
}
/**
* Set token against which to compare
*
* @return $this
*/
public function setToken(mixed $token)
{
$this->tokenString = is_array($token) ? var_export($token, true) : (string) $token;
$this->token = $token;
return $this;
}
/**
* Returns the strict parameter
*
* @return bool
*/
public function getStrict()
{
return $this->strict;
}
/**
* Sets the strict parameter
*
* @param bool $strict
* @return $this
*/
public function setStrict($strict)
{
$this->strict = (bool) $strict;
return $this;
}
/**
* Returns the literal parameter
*
* @return bool
*/
public function getLiteral()
{
return $this->literal;
}
/**
* Sets the literal parameter
*
* @param bool $literal
* @return $this
*/
public function setLiteral($literal)
{
$this->literal = (bool) $literal;
return $this;
}
/**
* Returns true if and only if a token has been set and the provided value
* matches that token.
*
* @param mixed $value
* @param null|array|ArrayAccess $context
* @throws Exception\InvalidArgumentException If context is not array or ArrayObject.
* @return bool
*/
public function isValid($value, $context = null)
{
$this->setValue($value);
$token = $this->getToken();
if (! $this->getLiteral() && $context !== null) {
if (! is_array($context) && ! $context instanceof ArrayAccess) {
throw new Exception\InvalidArgumentException(sprintf(
'Context passed to %s must be array, ArrayObject or null; received "%s"',
__METHOD__,
get_debug_type($context)
));
}
if (is_array($token)) {
while (is_array($token)) {
$key = key($token);
if (! isset($context[$key])) {
break;
}
$context = $context[$key];
$token = $token[$key];
}
}
// if $token is an array it means the above loop didn't went all the way down to the leaf,
// so the $token structure doesn't match the $context structure
if (
is_array($token)
|| (! is_int($token) && ! is_string($token))
|| ! isset($context[$token])
) {
$token = $this->getToken();
} else {
$token = $context[$token];
}
}
if ($token === null) {
$this->error(self::MISSING_TOKEN);
return false;
}
$strict = $this->getStrict();
if (
($strict && ($value !== $token))
// phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedNotEqualOperator
|| (! $strict && ($value != $token))
) {
$this->error(self::NOT_SAME);
return false;
}
return true;
}
}
laminas-validator/src/CreditCard.php 0000644 00000026662 15240152637 0013500 0 ustar 00 <?php
namespace Laminas\Validator;
use Exception;
use Laminas\Stdlib\ArrayUtils;
use Laminas\Validator\Exception\InvalidArgumentException;
use Traversable;
use function array_key_exists;
use function array_keys;
use function array_shift;
use function constant;
use function ctype_digit;
use function defined;
use function floor;
use function func_get_args;
use function in_array;
use function is_array;
use function is_callable;
use function is_string;
use function str_starts_with;
use function strlen;
use function strtoupper;
class CreditCard extends AbstractValidator
{
/**
* Detected CCI list
*
* @var string
*/
public const ALL = 'All';
public const AMERICAN_EXPRESS = 'American_Express';
public const UNIONPAY = 'Unionpay';
public const DINERS_CLUB = 'Diners_Club';
public const DINERS_CLUB_US = 'Diners_Club_US';
public const DISCOVER = 'Discover';
public const JCB = 'JCB';
public const LASER = 'Laser';
public const MAESTRO = 'Maestro';
public const MASTERCARD = 'Mastercard';
public const SOLO = 'Solo';
public const VISA = 'Visa';
public const MIR = 'Mir';
public const CHECKSUM = 'creditcardChecksum';
public const CONTENT = 'creditcardContent';
public const INVALID = 'creditcardInvalid';
public const LENGTH = 'creditcardLength';
public const PREFIX = 'creditcardPrefix';
public const SERVICE = 'creditcardService';
public const SERVICEFAILURE = 'creditcardServiceFailure';
/**
* Validation failure message template definitions
*
* @var array
*/
protected $messageTemplates = [
self::CHECKSUM => 'The input seems to contain an invalid checksum',
self::CONTENT => 'The input must contain only digits',
self::INVALID => 'Invalid type given. String expected',
self::LENGTH => 'The input contains an invalid amount of digits',
self::PREFIX => 'The input is not from an allowed institute',
self::SERVICE => 'The input seems to be an invalid credit card number',
self::SERVICEFAILURE => 'An exception has been raised while validating the input',
];
/**
* List of CCV names
*
* @var array
*/
protected $cardName = [
0 => self::AMERICAN_EXPRESS,
1 => self::DINERS_CLUB,
2 => self::DINERS_CLUB_US,
3 => self::DISCOVER,
4 => self::JCB,
5 => self::LASER,
6 => self::MAESTRO,
7 => self::MASTERCARD,
8 => self::SOLO,
9 => self::UNIONPAY,
10 => self::VISA,
11 => self::MIR,
];
/**
* List of allowed CCV lengths
*
* @var array
*/
protected $cardLength = [
self::AMERICAN_EXPRESS => [15],
self::DINERS_CLUB => [14],
self::DINERS_CLUB_US => [16],
self::DISCOVER => [16, 19],
self::JCB => [15, 16],
self::LASER => [16, 17, 18, 19],
self::MAESTRO => [12, 13, 14, 15, 16, 17, 18, 19],
self::MASTERCARD => [16],
self::SOLO => [16, 18, 19],
self::UNIONPAY => [16, 17, 18, 19],
self::VISA => [13, 16, 19],
self::MIR => [13, 16],
];
/**
* List of accepted CCV provider tags
*
* @var array
*/
protected $cardType = [
self::AMERICAN_EXPRESS => ['34', '37'],
self::DINERS_CLUB => ['300', '301', '302', '303', '304', '305', '36'],
self::DINERS_CLUB_US => ['54', '55'],
self::DISCOVER => [
'6011',
'622126',
'622127',
'622128',
'622129',
'62213',
'62214',
'62215',
'62216',
'62217',
'62218',
'62219',
'6222',
'6223',
'6224',
'6225',
'6226',
'6227',
'6228',
'62290',
'62291',
'622920',
'622921',
'622922',
'622923',
'622924',
'622925',
'644',
'645',
'646',
'647',
'648',
'649',
'65',
],
self::JCB => ['1800', '2131', '3528', '3529', '353', '354', '355', '356', '357', '358'],
self::LASER => ['6304', '6706', '6771', '6709'],
self::MAESTRO => [
'5018',
'5020',
'5038',
'6304',
'6759',
'6761',
'6762',
'6763',
'6764',
'6765',
'6766',
'6772',
],
self::MASTERCARD => [
'2221',
'2222',
'2223',
'2224',
'2225',
'2226',
'2227',
'2228',
'2229',
'223',
'224',
'225',
'226',
'227',
'228',
'229',
'23',
'24',
'25',
'26',
'271',
'2720',
'51',
'52',
'53',
'54',
'55',
],
self::SOLO => ['6334', '6767'],
self::UNIONPAY => [
'622126',
'622127',
'622128',
'622129',
'62213',
'62214',
'62215',
'62216',
'62217',
'62218',
'62219',
'6222',
'6223',
'6224',
'6225',
'6226',
'6227',
'6228',
'62290',
'62291',
'622920',
'622921',
'622922',
'622923',
'622924',
'622925',
],
self::VISA => ['4'],
self::MIR => ['2200', '2201', '2202', '2203', '2204'],
];
/**
* Options for this validator
*
* @var array
*/
protected $options = [
'service' => null, // Service callback for additional validation
'type' => [], // CCIs which are accepted by validation
];
/**
* Constructor
*
* @param string|array|Traversable $options OPTIONAL Type of CCI to allow
*/
public function __construct($options = [])
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
} elseif (! is_array($options)) {
$options = func_get_args();
$temp['type'] = array_shift($options);
if (! empty($options)) {
$temp['service'] = array_shift($options);
}
$options = $temp;
}
if (! array_key_exists('type', $options)) {
$options['type'] = self::ALL;
}
$this->setType($options['type']);
unset($options['type']);
if (array_key_exists('service', $options)) {
$this->setService($options['service']);
unset($options['service']);
}
parent::__construct($options);
}
/**
* Returns a list of accepted CCIs
*
* @return array
*/
public function getType()
{
return $this->options['type'];
}
/**
* Sets CCIs which are accepted by validation
*
* @param string|array $type Type to allow for validation
* @return CreditCard Provides a fluid interface
*/
public function setType($type)
{
$this->options['type'] = [];
return $this->addType($type);
}
/**
* Adds a CCI to be accepted by validation
*
* @param string|array $type Type to allow for validation
* @return $this Provides a fluid interface
*/
public function addType($type)
{
if (is_string($type)) {
$type = [$type];
}
foreach ($type as $typ) {
if ($typ === self::ALL) {
$this->options['type'] = array_keys($this->cardLength);
continue;
}
if (in_array($typ, $this->options['type'])) {
continue;
}
$constant = 'static::' . strtoupper($typ);
if (! defined($constant) || in_array(constant($constant), $this->options['type'])) {
continue;
}
$this->options['type'][] = constant($constant);
}
return $this;
}
/**
* Returns the actual set service
*
* @return callable
*/
public function getService()
{
return $this->options['service'];
}
/**
* Sets a new callback for service validation
*
* @param callable $service
* @return $this
* @throws InvalidArgumentException On invalid service callback.
*/
public function setService($service)
{
if (! is_callable($service)) {
throw new InvalidArgumentException('Invalid callback given');
}
$this->options['service'] = $service;
return $this;
}
/**
* Returns true if and only if $value follows the Luhn algorithm (mod-10 checksum)
*
* @param string $value
* @return bool
*/
public function isValid($value)
{
$this->setValue($value);
if (! is_string($value)) {
$this->error(self::INVALID, $value);
return false;
}
if (! ctype_digit($value)) {
$this->error(self::CONTENT, $value);
return false;
}
$length = strlen($value);
$types = $this->getType();
$foundp = false;
$foundl = false;
foreach ($types as $type) {
foreach ($this->cardType[$type] as $prefix) {
if (str_starts_with($value, (string) $prefix)) {
$foundp = true;
if (in_array($length, $this->cardLength[$type])) {
$foundl = true;
break 2;
}
}
}
}
if ($foundp === false) {
$this->error(self::PREFIX, $value);
return false;
}
if ($foundl === false) {
$this->error(self::LENGTH, $value);
return false;
}
$sum = 0;
$weight = 2;
for ($i = $length - 2; $i >= 0; $i--) {
$digit = $weight * $value[$i];
$sum += floor($digit / 10) + $digit % 10;
$weight = $weight % 2 + 1;
}
$checksum = (10 - $sum % 10) % 10;
if ((string) $checksum !== $value[$length - 1]) {
$this->error(self::CHECKSUM, $value);
return false;
}
$service = $this->getService();
if (! empty($service)) {
try {
$callback = new Callback($service);
$callback->setOptions($this->getType());
if (! $callback->isValid($value)) {
$this->error(self::SERVICE, $value);
return false;
}
} catch (Exception) {
$this->error(self::SERVICEFAILURE, $value);
return false;
}
}
return true;
}
}
laminas-validator/src/ValidatorPluginManagerFactory.php 0000644 00000004655 15240152637 0017421 0 ustar 00 <?php
namespace Laminas\Validator;
use Laminas\ServiceManager\Config;
use Laminas\ServiceManager\FactoryInterface;
use Laminas\ServiceManager\ServiceLocatorInterface;
use Laminas\ServiceManager\ServiceManager;
use Psr\Container\ContainerInterface;
use function is_array;
/**
* @link ServiceManager
*
* @psalm-import-type ServiceManagerConfiguration from ServiceManager
*/
class ValidatorPluginManagerFactory implements FactoryInterface
{
/**
* laminas-servicemanager v2 support for invocation options.
*
* @var null|ServiceManagerConfiguration
*/
protected $creationOptions;
/**
* {@inheritDoc}
*
* @param string $name
* @param ServiceManagerConfiguration|null $options
* @return ValidatorPluginManager
* @psalm-suppress MoreSpecificImplementedParamType
*/
public function __invoke(ContainerInterface $container, $name, ?array $options = null)
{
$pluginManager = new ValidatorPluginManager($container, $options ?: []);
// If this is in a laminas-mvc application, the ServiceListener will inject
// merged configuration during bootstrap.
if ($container->has('ServiceListener')) {
return $pluginManager;
}
// If we do not have a config service, nothing more to do
if (! $container->has('config')) {
return $pluginManager;
}
$config = $container->get('config');
// If we do not have validators configuration, nothing more to do
if (! isset($config['validators']) || ! is_array($config['validators'])) {
return $pluginManager;
}
// Wire service configuration for validators
(new Config($config['validators']))->configureServiceManager($pluginManager);
return $pluginManager;
}
/**
* {@inheritDoc}
*
* @param string|null $name
* @param string|null $requestedName
* @return ValidatorPluginManager
*/
public function createService(ServiceLocatorInterface $container, $name = null, $requestedName = null)
{
return $this($container, $requestedName ?: ValidatorPluginManager::class, $this->creationOptions);
}
/**
* laminas-servicemanager v2 support for invocation options.
*
* @param ServiceManagerConfiguration $options
* @return void
*/
public function setCreationOptions(array $options)
{
$this->creationOptions = $options;
}
}
laminas-validator/src/Digits.php 0000644 00000003117 15240152637 0012705 0 ustar 00 <?php
namespace Laminas\Validator;
use Laminas\Filter\Digits as DigitsFilter;
use function is_float;
use function is_int;
use function is_string;
class Digits extends AbstractValidator
{
public const NOT_DIGITS = 'notDigits';
public const STRING_EMPTY = 'digitsStringEmpty';
public const INVALID = 'digitsInvalid';
/**
* Digits filter used for validation
*
* @var DigitsFilter
*/
protected static $filter;
/**
* Validation failure message template definitions
*
* @var array
*/
protected $messageTemplates = [
self::NOT_DIGITS => 'The input must contain only digits',
self::STRING_EMPTY => 'The input is an empty string',
self::INVALID => 'Invalid type given. String, integer or float expected',
];
/**
* Returns true if and only if $value only contains digit characters
*
* @param string $value
* @return bool
*/
public function isValid($value)
{
if (! is_string($value) && ! is_int($value) && ! is_float($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue((string) $value);
if ('' === $this->getValue()) {
$this->error(self::STRING_EMPTY);
return false;
}
if (null === static::$filter) {
static::$filter = new DigitsFilter();
}
if ($this->getValue() !== static::$filter->filter($this->getValue())) {
$this->error(self::NOT_DIGITS);
return false;
}
return true;
}
}
laminas-validator/src/Timezone.php 0000644 00000011020 15240152637 0013244 0 ustar 00 <?php
namespace Laminas\Validator;
use DateTimeZone;
use function array_key_exists;
use function array_search;
use function gettype;
use function in_array;
use function is_array;
use function is_int;
use function is_string;
use function sprintf;
class Timezone extends AbstractValidator
{
public const INVALID = 'invalidTimezone';
public const INVALID_TIMEZONE_LOCATION = 'invalidTimezoneLocation';
public const INVALID_TIMEZONE_ABBREVIATION = 'invalidTimezoneAbbreviation';
public const LOCATION = 0b01;
public const ABBREVIATION = 0b10;
public const ALL = 0b11;
/** @var array */
protected $constants = [
self::LOCATION => 'location',
self::ABBREVIATION => 'abbreviation',
];
/**
* Default value for types; value = 3
*
* @var array
*/
protected $defaultType = [
self::LOCATION,
self::ABBREVIATION,
];
/** @var array */
protected $messageTemplates = [
self::INVALID => 'Invalid timezone given.',
self::INVALID_TIMEZONE_LOCATION => 'Invalid timezone location given.',
self::INVALID_TIMEZONE_ABBREVIATION => 'Invalid timezone abbreviation given.',
];
/**
* Options for this validator
*
* @var array
*/
protected $options = [];
/**
* Constructor
*
* @param array|int $options OPTIONAL
*/
public function __construct($options = [])
{
$opts['type'] = $this->defaultType;
if (is_array($options)) {
if (array_key_exists('type', $options)) {
$opts['type'] = $options['type'];
}
} elseif (! empty($options)) {
$opts['type'] = $options;
}
// setType called by parent constructor then setOptions method
parent::__construct($opts);
}
/**
* Set the types
*
* @param int|array $type
* @return void
* @throws Exception\InvalidArgumentException
*/
public function setType($type = null)
{
$type = $this->calculateTypeValue($type);
if (! is_int($type) || ($type < 1) || ($type > self::ALL)) {
throw new Exception\InvalidArgumentException(sprintf(
'Unknown type "%s" provided',
is_string($type) || is_int($type)
? $type : gettype($type)
));
}
$this->options['type'] = $type;
}
/**
* Returns true if timezone location or timezone abbreviations is correct.
*
* @param mixed $value
* @return bool
*/
public function isValid($value)
{
if ($value !== null && ! is_string($value)) {
$this->error(self::INVALID);
return false;
}
$type = $this->options['type'];
$this->setValue($value);
switch (true) {
// Check in locations and abbreviations
case ($type & self::LOCATION) && ($type & self::ABBREVIATION):
$abbrs = DateTimeZone::listAbbreviations();
$locations = DateTimeZone::listIdentifiers();
if (! array_key_exists($value, $abbrs) && ! in_array($value, $locations)) {
$this->error(self::INVALID);
return false;
}
break;
// Check only in locations
case $type & self::LOCATION:
$locations = DateTimeZone::listIdentifiers();
if (! in_array($value, $locations)) {
$this->error(self::INVALID_TIMEZONE_LOCATION);
return false;
}
break;
// Check only in abbreviations
case $type & self::ABBREVIATION:
$abbrs = DateTimeZone::listAbbreviations();
if (! array_key_exists($value, $abbrs)) {
$this->error(self::INVALID_TIMEZONE_ABBREVIATION);
return false;
}
break;
}
return true;
}
/**
* @param array|int|string $type
* @return float|int
*/
protected function calculateTypeValue($type)
{
$types = (array) $type;
$detected = 0;
foreach ($types as $value) {
if (is_int($value)) {
$detected |= $value;
} elseif (false !== array_search($value, $this->constants)) {
$detected |= array_search($value, $this->constants);
}
}
return $detected;
}
}
laminas-validator/src/Sitemap/Lastmod.php 0000644 00000003433 15240152637 0014470 0 ustar 00 <?php
namespace Laminas\Validator\Sitemap;
use Laminas\Stdlib\ErrorHandler;
use Laminas\Validator\AbstractValidator;
use function is_string;
use function preg_match;
/**
* Validates whether a given value is valid as a sitemap <lastmod> value
*
* @link http://www.sitemaps.org/protocol.php Sitemaps XML format
*/
class Lastmod extends AbstractValidator
{
// phpcs:disable Generic.Files.LineLength.TooLong
/**
* Regular expression to use when validating
*/
public const LASTMOD_REGEX = '/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])(T([0-1][0-9]|2[0-3])(:[0-5][0-9])(:[0-5][0-9])?(\\+|-)([0-1][0-9]|2[0-3]):[0-5][0-9])?$/';
// phpcs:enable
/**
* Validation key for not valid
*/
public const NOT_VALID = 'sitemapLastmodNotValid';
public const INVALID = 'sitemapLastmodInvalid';
/**
* Validation failure message template definitions
*
* @var array<string, string>
*/
protected $messageTemplates = [
self::NOT_VALID => 'The input is not a valid sitemap lastmod',
self::INVALID => 'Invalid type given. String expected',
];
/**
* Validates if a string is valid as a sitemap lastmod
*
* @link http://www.sitemaps.org/protocol.php#lastmoddef <lastmod>
*
* @param string $value value to validate
* @return bool
*/
public function isValid($value)
{
if (! is_string($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
ErrorHandler::start();
$result = preg_match(self::LASTMOD_REGEX, $value);
ErrorHandler::stop();
if ($result !== 1) {
$this->error(self::NOT_VALID);
return false;
}
return true;
}
}
laminas-validator/src/Sitemap/Loc.php 0000644 00000002546 15240152637 0013606 0 ustar 00 <?php
namespace Laminas\Validator\Sitemap;
use Laminas\Uri;
use Laminas\Validator\AbstractValidator;
use function is_string;
/**
* Validates whether a given value is valid as a sitemap <loc> value
*
* @link http://www.sitemaps.org/protocol.php Sitemaps XML format
* @see Laminas\Uri\Uri
*/
class Loc extends AbstractValidator
{
/**
* Validation key for not valid
*/
public const NOT_VALID = 'sitemapLocNotValid';
public const INVALID = 'sitemapLocInvalid';
/**
* Validation failure message template definitions
*
* @var array
*/
protected $messageTemplates = [
self::NOT_VALID => 'The input is not a valid sitemap location',
self::INVALID => 'Invalid type given. String expected',
];
/**
* Validates if a string is valid as a sitemap location
*
* @link http://www.sitemaps.org/protocol.php#locdef <loc>
*
* @param string $value value to validate
* @return bool
*/
public function isValid($value)
{
if (! is_string($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
$uri = Uri\UriFactory::factory($value);
if (! $uri->isValid()) {
$this->error(self::NOT_VALID);
return false;
}
return true;
}
}
laminas-validator/src/Sitemap/Changefreq.php 0000644 00000003124 15240152637 0015125 0 ustar 00 <?php
namespace Laminas\Validator\Sitemap;
use Laminas\Validator\AbstractValidator;
use function in_array;
use function is_string;
/**
* Validates whether a given value is valid as a sitemap <changefreq> value
*
* @link http://www.sitemaps.org/protocol.php Sitemaps XML format
*/
class Changefreq extends AbstractValidator
{
/**
* Validation key for not valid
*/
public const NOT_VALID = 'sitemapChangefreqNotValid';
public const INVALID = 'sitemapChangefreqInvalid';
/**
* Validation failure message template definitions
*
* @var array
*/
protected $messageTemplates = [
self::NOT_VALID => 'The input is not a valid sitemap changefreq',
self::INVALID => 'Invalid type given. String expected',
];
/**
* Valid change frequencies
*
* @var array
*/
protected $changeFreqs = [
'always',
'hourly',
'daily',
'weekly',
'monthly',
'yearly',
'never',
];
/**
* Validates if a string is valid as a sitemap changefreq
*
* @link http://www.sitemaps.org/protocol.php#changefreqdef <changefreq>
*
* @param string $value value to validate
* @return bool
*/
public function isValid($value)
{
if (! is_string($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
if (! in_array($value, $this->changeFreqs, true)) {
$this->error(self::NOT_VALID);
return false;
}
return true;
}
}
laminas-validator/src/Sitemap/Priority.php 0000644 00000002550 15240152637 0014705 0 ustar 00 <?php
namespace Laminas\Validator\Sitemap;
use Laminas\Validator\AbstractValidator;
use function is_numeric;
/**
* Validates whether a given value is valid as a sitemap <priority> value
*
* @link http://www.sitemaps.org/protocol.php Sitemaps XML format
*/
class Priority extends AbstractValidator
{
/**
* Validation key for not valid
*/
public const NOT_VALID = 'sitemapPriorityNotValid';
public const INVALID = 'sitemapPriorityInvalid';
/**
* Validation failure message template definitions
*
* @var array
*/
protected $messageTemplates = [
self::NOT_VALID => 'The input is not a valid sitemap priority',
self::INVALID => 'Invalid type given. Numeric string, integer or float expected',
];
/**
* Validates if a string is valid as a sitemap priority
*
* @link http://www.sitemaps.org/protocol.php#prioritydef <priority>
*
* @param string $value value to validate
* @return bool
*/
public function isValid($value)
{
if (! is_numeric($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
$value = (float) $value;
if ($value < 0 || $value > 1) {
$this->error(self::NOT_VALID);
return false;
}
return true;
}
}
laminas-validator/src/Uri.php 0000644 00000011433 15240152637 0012221 0 ustar 00 <?php
namespace Laminas\Validator;
use Laminas\Uri\Exception\ExceptionInterface as UriException;
use Laminas\Uri\Uri as UriHandler;
use Laminas\Validator\Exception\InvalidArgumentException;
use Traversable;
use function array_shift;
use function class_exists;
use function func_get_args;
use function is_a;
use function is_array;
use function is_string;
use function iterator_to_array;
use function sprintf;
class Uri extends AbstractValidator
{
public const INVALID = 'uriInvalid';
public const NOT_URI = 'notUri';
/** @var array<string, string> */
protected $messageTemplates = [
self::INVALID => 'Invalid type given. String expected',
self::NOT_URI => 'The input does not appear to be a valid Uri',
];
/** @var UriHandler */
protected $uriHandler;
/** @var bool */
protected $allowRelative = true;
/** @var bool */
protected $allowAbsolute = true;
/**
* Sets default option values for this instance
*
* @param array|Traversable $options
*/
public function __construct($options = [])
{
if ($options instanceof Traversable) {
$options = iterator_to_array($options);
} elseif (! is_array($options)) {
$options = func_get_args();
$temp['uriHandler'] = array_shift($options);
if (! empty($options)) {
$temp['allowRelative'] = array_shift($options);
}
if (! empty($options)) {
$temp['allowAbsolute'] = array_shift($options);
}
$options = $temp;
}
if (isset($options['uriHandler'])) {
$this->setUriHandler($options['uriHandler']);
}
if (isset($options['allowRelative'])) {
$this->setAllowRelative($options['allowRelative']);
}
if (isset($options['allowAbsolute'])) {
$this->setAllowAbsolute($options['allowAbsolute']);
}
parent::__construct($options);
}
/**
* @throws InvalidArgumentException
* @return UriHandler
*/
public function getUriHandler()
{
if (null === $this->uriHandler) {
// Lazy load the base Uri handler
$this->uriHandler = new UriHandler();
} elseif (is_string($this->uriHandler) && class_exists($this->uriHandler)) {
// Instantiate string Uri handler that references a class
$this->uriHandler = new $this->uriHandler();
}
return $this->uriHandler;
}
/**
* @param UriHandler|string $uriHandler
* @throws InvalidArgumentException
* @return $this
*/
public function setUriHandler($uriHandler)
{
if (! is_a($uriHandler, UriHandler::class, true)) {
throw new InvalidArgumentException(sprintf(
'Expecting a subclass name or instance of %s as $uriHandler',
UriHandler::class
));
}
$this->uriHandler = $uriHandler;
return $this;
}
/**
* Returns the allowAbsolute option
*
* @return bool
*/
public function getAllowAbsolute()
{
return $this->allowAbsolute;
}
/**
* Sets the allowAbsolute option
*
* @param bool $allowAbsolute
* @return $this
*/
public function setAllowAbsolute($allowAbsolute)
{
$this->allowAbsolute = (bool) $allowAbsolute;
return $this;
}
/**
* Returns the allowRelative option
*
* @return bool
*/
public function getAllowRelative()
{
return $this->allowRelative;
}
/**
* Sets the allowRelative option
*
* @param bool $allowRelative
* @return $this
*/
public function setAllowRelative($allowRelative)
{
$this->allowRelative = (bool) $allowRelative;
return $this;
}
/**
* Returns true if and only if $value validates as a Uri
*
* @param string $value
* @return bool
*/
public function isValid($value)
{
if (! is_string($value)) {
$this->error(self::INVALID);
return false;
}
$uriHandler = $this->getUriHandler();
try {
$uriHandler->parse($value);
if ($uriHandler->isValid()) {
// It will either be a valid absolute or relative URI
if (
($this->allowRelative && $this->allowAbsolute)
|| ($this->allowAbsolute && $uriHandler->isAbsolute())
|| ($this->allowRelative && $uriHandler->isValidRelative())
) {
return true;
}
}
} catch (UriException) {
// Error parsing URI, it must be invalid
}
$this->error(self::NOT_URI);
return false;
}
}
laminas-validator/src/StaticValidator.php 0000644 00000004316 15240152637 0014561 0 ustar 00 <?php
namespace Laminas\Validator;
use Laminas\ServiceManager\ServiceManager;
use function array_values;
use function method_exists;
class StaticValidator
{
/** @var ValidatorPluginManager|null */
protected static $plugins;
/**
* Set plugin manager to use for locating validators
*
* @return void
*/
public static function setPluginManager(?ValidatorPluginManager $plugins = null)
{
// Don't share by default to allow different arguments on subsequent calls
if ($plugins instanceof ValidatorPluginManager) {
// Vary how the share by default flag is set based on laminas-servicemanager version
if (method_exists($plugins, 'configure')) {
$plugins->configure(['shared_by_default' => false]);
} else {
$plugins->setShareByDefault(false);
}
}
static::$plugins = $plugins;
}
/**
* Get plugin manager for locating validators
*
* @return ValidatorPluginManager
*/
public static function getPluginManager()
{
if (! static::$plugins instanceof ValidatorPluginManager) {
$plugins = new ValidatorPluginManager(new ServiceManager());
static::setPluginManager($plugins);
return $plugins;
}
return static::$plugins;
}
/**
* @param class-string<ValidatorInterface> $classBaseName
* @param array $options OPTIONAL associative array of options to pass as
* the sole argument to the validator constructor.
* @return bool
* @throws Exception\InvalidArgumentException For an invalid $options argument.
*/
public static function execute(mixed $value, $classBaseName, array $options = [])
{
if ($options && array_values($options) === $options) {
throw new Exception\InvalidArgumentException(
'Invalid options provided via $options argument; must be an associative array'
);
}
$plugins = static::getPluginManager();
$validator = $plugins->get($classBaseName, $options);
return $validator->isValid($value);
}
}
laminas-validator/src/Barcode.php 0000644 00000013063 15240152637 0013022 0 ustar 00 <?php
namespace Laminas\Validator;
use Traversable;
use function array_key_exists;
use function class_exists;
use function get_debug_type;
use function is_array;
use function is_string;
use function property_exists;
use function sprintf;
use function strtolower;
use function substr;
use function ucfirst;
class Barcode extends AbstractValidator
{
public const INVALID = 'barcodeInvalid';
public const FAILED = 'barcodeFailed';
public const INVALID_CHARS = 'barcodeInvalidChars';
public const INVALID_LENGTH = 'barcodeInvalidLength';
/** @var array<string, string> */
protected $messageTemplates = [
self::FAILED => 'The input failed checksum validation',
self::INVALID_CHARS => 'The input contains invalid characters',
self::INVALID_LENGTH => 'The input should have a length of %length% characters',
self::INVALID => 'Invalid type given. String expected',
];
/**
* Additional variables available for validation failure messages
*
* @var array<string, array<string, string>>
*/
protected $messageVariables = [
'length' => ['options' => 'length'],
];
/** @var array<string, mixed> */
protected $options = [
'adapter' => null, // Barcode adapter Laminas\Validator\Barcode\AbstractAdapter
'options' => null, // Options for this adapter
'length' => null,
'useChecksum' => null,
];
/**
* Constructor for barcodes
*
* @param array|string $options Options to use
*/
public function __construct($options = null)
{
if ($options === null) {
$options = [];
}
if (is_array($options)) {
if (array_key_exists('options', $options)) {
$options['options'] = ['options' => $options['options']];
}
} elseif ($options instanceof Traversable) {
if (property_exists($options, 'options')) {
$options['options'] = ['options' => $options['options']];
}
} else {
$options = ['adapter' => $options];
}
parent::__construct($options);
}
/**
* Returns the set adapter
*
* @return Barcode\AbstractAdapter
*/
public function getAdapter()
{
if (! $this->options['adapter'] instanceof Barcode\AdapterInterface) {
$this->setAdapter('Ean13');
}
return $this->options['adapter'];
}
/**
* Sets a new barcode adapter
*
* @param string|Barcode\AbstractAdapter $adapter Barcode adapter to use
* @param array $options Options for this adapter
* @return $this
* @throws Exception\InvalidArgumentException
*/
public function setAdapter($adapter, $options = null)
{
if (is_string($adapter)) {
$adapter = ucfirst(strtolower($adapter));
$adapter = 'Laminas\\Validator\\Barcode\\' . $adapter;
if (! class_exists($adapter)) {
throw new Exception\InvalidArgumentException('Barcode adapter matching "' . $adapter . '" not found');
}
$adapter = new $adapter($options);
}
if (! $adapter instanceof Barcode\AdapterInterface) {
throw new Exception\InvalidArgumentException(
sprintf(
'Adapter %s does not implement Laminas\\Validator\\Barcode\\AdapterInterface',
get_debug_type($adapter)
)
);
}
$this->options['adapter'] = $adapter;
return $this;
}
/**
* Returns the checksum option
*
* @return string
*/
public function getChecksum()
{
return $this->getAdapter()->getChecksum();
}
/**
* Sets if checksum should be validated, if no value is given the actual setting is returned
*
* @param null|bool $checksum
* @return Barcode\AbstractAdapter|bool
*/
public function useChecksum($checksum = null)
{
return $this->getAdapter()->useChecksum($checksum);
}
/**
* Defined by Laminas\Validator\ValidatorInterface
*
* Returns true if and only if $value contains a valid barcode
*
* @param string $value
* @return bool
*/
public function isValid($value)
{
if (! is_string($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
$adapter = $this->getAdapter();
$this->options['length'] = $adapter->getLength();
$result = $adapter->hasValidLength($value);
if (! $result) {
if (is_array($this->options['length'])) {
$temp = $this->options['length'];
$this->options['length'] = '';
foreach ($temp as $length) {
$this->options['length'] .= '/';
$this->options['length'] .= $length;
}
$this->options['length'] = substr($this->options['length'], 1);
}
$this->error(self::INVALID_LENGTH);
return false;
}
$result = $adapter->hasValidCharacters($value);
if (! $result) {
$this->error(self::INVALID_CHARS);
return false;
}
if ($this->useChecksum(null)) {
$result = $adapter->hasValidChecksum($value);
if (! $result) {
$this->error(self::FAILED);
return false;
}
}
return true;
}
}
laminas-validator/src/Callback.php 0000644 00000007012 15240152637 0013154 0 ustar 00 <?php
namespace Laminas\Validator;
use Exception;
use Laminas\Validator\Exception\InvalidArgumentException;
use function array_merge;
use function call_user_func_array;
use function is_callable;
class Callback extends AbstractValidator
{
/**
* Invalid callback
*/
public const INVALID_CALLBACK = 'callbackInvalid';
/**
* Invalid value
*/
public const INVALID_VALUE = 'callbackValue';
/**
* Validation failure message template definitions
*
* @var array
*/
protected $messageTemplates = [
self::INVALID_VALUE => 'The input is not valid',
self::INVALID_CALLBACK => 'An exception has been raised within the callback',
];
/**
* Default options to set for the validator
*
* @var mixed
*/
protected $options = [
'callback' => null, // Callback in a call_user_func format, string || array
'callbackOptions' => [], // Options for the callback
];
/**
* Constructor
*
* @param array|callable $options
*/
public function __construct($options = null)
{
if (is_callable($options)) {
$options = ['callback' => $options];
}
parent::__construct($options);
}
/**
* Returns the set callback
*
* @return mixed
*/
public function getCallback()
{
return $this->options['callback'];
}
/**
* Sets the callback
*
* @param string|array|callable $callback
* @return $this Provides a fluent interface
* @throws InvalidArgumentException
*/
public function setCallback($callback)
{
if (! is_callable($callback)) {
throw new InvalidArgumentException('Invalid callback given');
}
$this->options['callback'] = $callback;
return $this;
}
/**
* Returns the set options for the callback
*
* @return mixed
*/
public function getCallbackOptions()
{
return $this->options['callbackOptions'];
}
/**
* Sets options for the callback
*
* @return $this Provides a fluent interface
*/
public function setCallbackOptions(mixed $options)
{
$this->options['callbackOptions'] = (array) $options;
return $this;
}
/**
* Returns true if and only if the set callback returns
* for the provided $value
*
* @param mixed $value
* @param mixed $context Additional context to provide to the callback
* @return bool
* @throws InvalidArgumentException
*/
public function isValid($value, $context = null)
{
$this->setValue($value);
$options = $this->getCallbackOptions();
$callback = $this->getCallback();
if (empty($callback)) {
throw new InvalidArgumentException('No callback given');
}
$args = [$value];
if (empty($options) && ! empty($context)) {
$args[] = $context;
}
if (! empty($options) && empty($context)) {
$args = array_merge($args, $options);
}
if (! empty($options) && ! empty($context)) {
$args[] = $context;
$args = array_merge($args, $options);
}
try {
if (! call_user_func_array($callback, $args)) {
$this->error(self::INVALID_VALUE);
return false;
}
} catch (Exception) {
$this->error(self::INVALID_CALLBACK);
return false;
}
return true;
}
}
laminas-validator/src/UndisclosedPassword.php 0000644 00000007702 15240152637 0015465 0 ustar 00 <?php
namespace Laminas\Validator;
use Psr\Http\Client\ClientExceptionInterface;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestFactoryInterface;
use function array_filter;
use function explode;
use function is_string;
use function sha1;
use function strcmp;
use function strtoupper;
use function substr;
final class UndisclosedPassword extends AbstractValidator
{
// phpcs:disable SlevomatCodingStandard.Classes.UnusedPrivateElements.UnusedConstant
private const HIBP_API_URI = 'https://api.pwnedpasswords.com';
private const HIBP_API_REQUEST_TIMEOUT = 300;
private const HIBP_CLIENT_USER_AGENT_STRING = 'laminas-validator';
private const HIBP_CLIENT_ACCEPT_HEADER = 'application/vnd.haveibeenpwned.v2+json';
private const HIBP_K_ANONYMITY_HASH_RANGE_LENGTH = 5;
private const HIBP_K_ANONYMITY_HASH_RANGE_BASE = 0;
private const SHA1_STRING_LENGTH = 40;
// phpcs:enable
private const PASSWORD_BREACHED = 'passwordBreached';
private const NOT_A_STRING = 'wrongInput';
// phpcs:disable Generic.Files.LineLength.TooLong
/** @var array<string, string> */
protected $messageTemplates = [
self::PASSWORD_BREACHED => 'The provided password was found in previous breaches, please create another password',
self::NOT_A_STRING => 'The provided password is not a string, please provide a correct password',
];
// phpcs:enable
public function __construct(private ClientInterface $httpClient, private RequestFactoryInterface $makeHttpRequest)
{
parent::__construct();
}
/** {@inheritDoc} */
public function isValid($value): bool
{
if (! is_string($value)) {
$this->error(self::NOT_A_STRING);
return false;
}
if ($this->isPwnedPassword($value)) {
$this->error(self::PASSWORD_BREACHED);
return false;
}
return true;
}
private function isPwnedPassword(string $password): bool
{
$sha1Hash = $this->hashPassword($password);
$rangeHash = $this->getRangeHash($sha1Hash);
$hashList = $this->retrieveHashList($rangeHash);
return $this->hashInResponse($sha1Hash, $hashList);
}
/**
* We use a SHA1 hashed password for checking it against
* the breached data set of HIBP.
*/
private function hashPassword(string $password): string
{
$hashedPassword = sha1($password);
return strtoupper($hashedPassword);
}
/**
* Creates a hash range that will be send to HIBP API
* applying K-Anonymity
*
* @see https://www.troyhunt.com/enhancing-pwned-passwords-privacy-by-exclusively-supporting-anonymity/
*/
private function getRangeHash(string $passwordHash): string
{
return substr($passwordHash, self::HIBP_K_ANONYMITY_HASH_RANGE_BASE, self::HIBP_K_ANONYMITY_HASH_RANGE_LENGTH);
}
/**
* Making a connection to the HIBP API to retrieve a
* list of hashes that all have the same range as we
* provided.
*
* @throws ClientExceptionInterface
*/
private function retrieveHashList(string $passwordRange): string
{
$request = $this->makeHttpRequest->createRequest(
'GET',
self::HIBP_API_URI . '/range/' . $passwordRange
);
$response = $this->httpClient->sendRequest($request);
return (string) $response->getBody();
}
/**
* Checks if the password is in the response from HIBP
*/
private function hashInResponse(string $sha1Hash, string $resultStream): bool
{
$data = explode("\r\n", $resultStream);
$hashes = array_filter($data, static function ($value) use ($sha1Hash): bool {
[$hash] = explode(':', $value);
return strcmp($hash, substr($sha1Hash, self::HIBP_K_ANONYMITY_HASH_RANGE_LENGTH)) === 0;
});
return $hashes !== [];
}
}
laminas-validator/src/Hex.php 0000644 00000002000 15240152637 0012174 0 ustar 00 <?php
namespace Laminas\Validator;
use function ctype_xdigit;
use function is_int;
use function is_string;
class Hex extends AbstractValidator
{
public const INVALID = 'hexInvalid';
public const NOT_HEX = 'notHex';
/**
* Validation failure message template definitions
*
* @var array
*/
protected $messageTemplates = [
self::INVALID => 'Invalid type given. String expected',
self::NOT_HEX => 'The input contains non-hexadecimal characters',
];
/**
* Returns true if and only if $value contains only hexadecimal digit characters
*
* @param string $value
* @return bool
*/
public function isValid($value)
{
if (! is_string($value) && ! is_int($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
if (! ctype_xdigit((string) $value)) {
$this->error(self::NOT_HEX);
return false;
}
return true;
}
}
laminas-validator/src/Isbn.php 0000644 00000011610 15240152637 0012352 0 ustar 00 <?php
namespace Laminas\Validator;
use function in_array;
use function is_int;
use function is_string;
use function preg_match;
use function quotemeta;
use function str_replace;
use function strlen;
use function substr;
class Isbn extends AbstractValidator
{
public const AUTO = 'auto';
public const ISBN10 = '10';
public const ISBN13 = '13';
public const INVALID = 'isbnInvalid';
public const NO_ISBN = 'isbnNoIsbn';
/**
* Validation failure message template definitions.
*
* @var array
*/
protected $messageTemplates = [
self::INVALID => 'Invalid type given. String or integer expected',
self::NO_ISBN => 'The input is not a valid ISBN number',
];
/** @var array<string, mixed> */
protected $options = [
'type' => self::AUTO, // Allowed type
'separator' => '', // Separator character
];
/**
* Detect input format.
*
* @return null|string
*/
protected function detectFormat()
{
// prepare separator and pattern list
$sep = quotemeta($this->getSeparator());
$patterns = [];
$lengths = [];
$type = $this->getType();
// check for ISBN-10
if ($type === self::ISBN10 || $type === self::AUTO) {
if (empty($sep)) {
$pattern = '/^[0-9]{9}[0-9X]{1}$/';
$length = 10;
} else {
$pattern = "/^[0-9]{1,7}[{$sep}]{1}[0-9]{1,7}[{$sep}]{1}[0-9]{1,7}[{$sep}]{1}[0-9X]{1}$/";
$length = 13;
}
$patterns[$pattern] = self::ISBN10;
$lengths[$pattern] = $length;
}
// check for ISBN-13
if ($type === self::ISBN13 || $type === self::AUTO) {
if (empty($sep)) {
$pattern = '/^[0-9]{13}$/';
$length = 13;
} else {
// @codingStandardsIgnoreStart
$pattern = "/^[0-9]{1,9}[{$sep}]{1}[0-9]{1,5}[{$sep}]{1}[0-9]{1,9}[{$sep}]{1}[0-9]{1,9}[{$sep}]{1}[0-9]{1}$/";
// @codingStandardsIgnoreEnd
$length = 17;
}
$patterns[$pattern] = self::ISBN13;
$lengths[$pattern] = $length;
}
// check pattern list
foreach ($patterns as $pattern => $type) {
if ((strlen($this->getValue()) === $lengths[$pattern]) && preg_match($pattern, $this->getValue())) {
return $type;
}
}
return null;
}
/**
* Returns true if and only if $value is a valid ISBN.
*
* @param string $value
* @return bool
*/
public function isValid($value)
{
if (! is_string($value) && ! is_int($value)) {
$this->error(self::INVALID);
return false;
}
$value = (string) $value;
$this->setValue($value);
switch ($this->detectFormat()) {
case self::ISBN10:
$isbn = new Isbn\Isbn10();
break;
case self::ISBN13:
$isbn = new Isbn\Isbn13();
break;
default:
$this->error(self::NO_ISBN);
return false;
}
$value = str_replace($this->getSeparator(), '', $value);
$checksum = $isbn->getChecksum($value);
// validate
if (substr($this->getValue(), -1) !== (string) $checksum) {
$this->error(self::NO_ISBN);
return false;
}
return true;
}
/**
* Set separator characters.
*
* It is allowed only empty string, hyphen and space.
*
* @param string $separator
* @throws Exception\InvalidArgumentException When $separator is not valid.
* @return $this Provides a fluent interface
*/
public function setSeparator($separator)
{
// check separator
if (! in_array($separator, ['-', ' ', ''])) {
throw new Exception\InvalidArgumentException('Invalid ISBN separator.');
}
$this->options['separator'] = $separator;
return $this;
}
/**
* Get separator characters.
*
* @return string
*/
public function getSeparator()
{
return $this->options['separator'];
}
/**
* Set allowed ISBN type.
*
* @param string $type
* @throws Exception\InvalidArgumentException When $type is not valid.
* @return $this Provides a fluent interface
*/
public function setType($type)
{
// check type
if (! in_array($type, [self::AUTO, self::ISBN10, self::ISBN13])) {
throw new Exception\InvalidArgumentException('Invalid ISBN type');
}
$this->options['type'] = $type;
return $this;
}
/**
* Get allowed ISBN type.
*
* @return string
*/
public function getType()
{
return $this->options['type'];
}
}
laminas-validator/src/StringLength.php 0000644 00000013420 15240152637 0014070 0 ustar 00 <?php
namespace Laminas\Validator;
use Laminas\Stdlib\StringUtils;
use Laminas\Stdlib\StringWrapper\StringWrapperInterface as StringWrapper;
use Laminas\Stdlib\StringWrapper\StringWrapperInterface;
use Traversable;
use function array_shift;
use function func_get_args;
use function is_array;
use function is_string;
use function max;
class StringLength extends AbstractValidator
{
public const INVALID = 'stringLengthInvalid';
public const TOO_SHORT = 'stringLengthTooShort';
public const TOO_LONG = 'stringLengthTooLong';
/** @var array<string, string> */
protected $messageTemplates = [
self::INVALID => 'Invalid type given. String expected',
self::TOO_SHORT => 'The input is less than %min% characters long',
self::TOO_LONG => 'The input is more than %max% characters long',
];
/** @var array<string, array<string, string>> */
protected $messageVariables = [
'min' => ['options' => 'min'],
'max' => ['options' => 'max'],
'length' => ['options' => 'length'],
];
/** @var array<string, mixed> */
protected $options = [
'min' => 0, // Minimum length
'max' => null, // Maximum length, null if there is no length limitation
'encoding' => 'UTF-8', // Encoding to use
'length' => 0, // Actual length
];
/** @var null|StringWrapperInterface */
protected $stringWrapper;
/**
* Sets validator options
*
* @param int|array|Traversable $options
*/
public function __construct($options = [])
{
if (! is_array($options)) {
$options = func_get_args();
$temp['min'] = array_shift($options);
if (! empty($options)) {
$temp['max'] = array_shift($options);
}
if (! empty($options)) {
$temp['encoding'] = array_shift($options);
}
$options = $temp;
}
parent::__construct($options);
}
/**
* Returns the min option
*
* @return int
*/
public function getMin()
{
return $this->options['min'];
}
/**
* Sets the min option
*
* @param int $min
* @throws Exception\InvalidArgumentException
* @return $this Provides a fluent interface
*/
public function setMin($min)
{
if (null !== $this->getMax() && $min > $this->getMax()) {
throw new Exception\InvalidArgumentException(
"The minimum must be less than or equal to the maximum length, but {$min} > {$this->getMax()}"
);
}
$this->options['min'] = max(0, (int) $min);
return $this;
}
/**
* Returns the max option
*
* @return int|null
*/
public function getMax()
{
return $this->options['max'];
}
/**
* Sets the max option
*
* @param int|null $max
* @throws Exception\InvalidArgumentException
* @return $this Provides a fluent interface
*/
public function setMax($max)
{
if (null === $max) {
$this->options['max'] = null;
} elseif ($max < $this->getMin()) {
throw new Exception\InvalidArgumentException(
"The maximum must be greater than or equal to the minimum length, but {$max} < {$this->getMin()}"
);
} else {
$this->options['max'] = (int) $max;
}
return $this;
}
/**
* Get the string wrapper to detect the string length
*
* @return StringWrapper
*/
public function getStringWrapper()
{
if (! $this->stringWrapper) {
$this->stringWrapper = StringUtils::getWrapper($this->getEncoding());
}
return $this->stringWrapper;
}
/**
* Set the string wrapper to detect the string length
*
* @return void
*/
public function setStringWrapper(StringWrapper $stringWrapper)
{
$stringWrapper->setEncoding($this->getEncoding());
$this->stringWrapper = $stringWrapper;
}
/**
* Returns the actual encoding
*
* @return string
*/
public function getEncoding()
{
return $this->options['encoding'];
}
/**
* Sets a new encoding to use
*
* @param string $encoding
* @return $this
* @throws Exception\InvalidArgumentException
*/
public function setEncoding($encoding)
{
$this->stringWrapper = StringUtils::getWrapper($encoding);
$this->options['encoding'] = $encoding;
return $this;
}
/**
* Returns the length option
*
* @return int
*/
private function getLength()
{
return $this->options['length'];
}
/**
* Sets the length option
*
* @param int $length
* @return $this Provides a fluent interface
*/
private function setLength($length)
{
$this->options['length'] = (int) $length;
return $this;
}
/**
* Returns true if and only if the string length of $value is at least the min option and
* no greater than the max option (when the max option is not null).
*
* @param string $value
* @return bool
*/
public function isValid($value)
{
if (! is_string($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
$this->setLength($this->getStringWrapper()->strlen($value));
if ($this->getLength() < $this->getMin()) {
$this->error(self::TOO_SHORT);
}
if (null !== $this->getMax() && $this->getMax() < $this->getLength()) {
$this->error(self::TOO_LONG);
}
if ($this->getMessages()) {
return false;
}
return true;
}
}
laminas-validator/src/GpsPoint.php 0000644 00000006400 15240152637 0013223 0 ustar 00 <?php
namespace Laminas\Validator;
use function explode;
use function preg_match;
use function preg_match_all;
use function preg_replace;
use function str_contains;
use function str_replace;
final class GpsPoint extends AbstractValidator
{
public const OUT_OF_BOUNDS = 'gpsPointOutOfBounds';
public const CONVERT_ERROR = 'gpsPointConvertError';
public const INCOMPLETE_COORDINATE = 'gpsPointIncompleteCoordinate';
/** @var array */
protected $messageTemplates = [
'gpsPointOutOfBounds' => '%value% is out of Bounds.',
'gpsPointConvertError' => '%value% can not converted into a Decimal Degree Value.',
'gpsPointIncompleteCoordinate' => '%value% did not provided a complete Coordinate',
];
/**
* Returns true if and only if $value meets the validation requirements
*
* If $value fails validation, then this method returns false, and
* getMessages() will return an array of messages that explain why the
* validation failed.
*
* @param mixed $value
* @return bool
* @throws Exception\RuntimeException If validation of $value is impossible.
*/
public function isValid($value)
{
if (! str_contains($value, ',')) {
$this->error(self::INCOMPLETE_COORDINATE, $value);
return false;
}
[$lat, $long] = explode(',', $value);
if ($this->isValidCoordinate($lat, 90.0000) && $this->isValidCoordinate($long, 180.000)) {
return true;
}
return false;
}
/**
* @param string $value
*/
private function isValidCoordinate($value, float $maxBoundary): bool
{
$this->value = $value;
$value = $this->removeWhiteSpace($value);
if ($this->isDMSValue($value)) {
$value = $this->convertValue($value);
} else {
$value = $this->removeDegreeSign($value);
}
if ($value === false || $value === null) {
$this->error(self::CONVERT_ERROR);
return false;
}
$doubleLatitude = (double) $value;
if ($doubleLatitude <= $maxBoundary && $doubleLatitude >= $maxBoundary * -1) {
return true;
}
$this->error(self::OUT_OF_BOUNDS);
return false;
}
/**
* Determines if the give value is a Degrees Minutes Second Definition
*/
private function isDMSValue(string $value): bool
{
return preg_match('/([°\'"]+[NESW])/', $value) > 0;
}
/**
* @param string $value
* @return false|float
*/
private function convertValue($value)
{
$matches = [];
$result = preg_match_all('/(\d{1,3})°(\d{1,2})\'(\d{1,2}[\.\d]{0,6})"[NESW]/i', $value, $matches);
if ($result === false || $result === 0) {
return false;
}
return $matches[1][0] + $matches[2][0] / 60 + ((double) $matches[3][0]) / 3600;
}
/**
* @param string $value
* @return string
*/
private function removeWhiteSpace($value)
{
return preg_replace('/\s/', '', $value);
}
/**
* @param string $value
* @return string
*/
private function removeDegreeSign($value)
{
return str_replace('°', '', $value);
}
}
laminas-validator/src/Ip.php 0000644 00000014101 15240152637 0012025 0 ustar 00 <?php
namespace Laminas\Validator;
use Traversable;
use function bindec;
use function hexdec;
use function ip2long;
use function is_string;
use function long2ip;
use function preg_match;
use function str_contains;
use function strlen;
use function strpos;
use function strrpos;
use function substr;
use function substr_count;
class Ip extends AbstractValidator
{
public const INVALID = 'ipInvalid';
public const NOT_IP_ADDRESS = 'notIpAddress';
/** @var array */
protected $messageTemplates = [
self::INVALID => 'Invalid type given. String expected',
self::NOT_IP_ADDRESS => 'The input does not appear to be a valid IP address',
];
/**
* Internal options
*
* @var array
*/
protected $options = [
'allowipv4' => true, // Enable IPv4 Validation
'allowipv6' => true, // Enable IPv6 Validation
'allowipvfuture' => false, // Enable IPvFuture Validation
'allowliteral' => true, // Enable IPs in literal format (only IPv6 and IPvFuture)
];
/**
* Sets the options for this validator
*
* @param array|Traversable $options
* @throws Exception\InvalidArgumentException If there is any kind of IP allowed or $options is not an array
* or Traversable.
* @return AbstractValidator
*/
public function setOptions($options = [])
{
parent::setOptions($options);
if (! $this->options['allowipv4'] && ! $this->options['allowipv6'] && ! $this->options['allowipvfuture']) {
throw new Exception\InvalidArgumentException('Nothing to validate. Check your options');
}
return $this;
}
/**
* Returns true if and only if $value is a valid IP address
*
* @param mixed $value
* @return bool
*/
public function isValid($value)
{
if (! is_string($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
if ($this->options['allowipv4'] && $this->validateIPv4($value)) {
return true;
} else {
if ((bool) $this->options['allowliteral']) {
static $regex = '/^\[(.*)\]$/';
if ((bool) preg_match($regex, $value, $matches)) {
$value = $matches[1];
}
}
if (
($this->options['allowipv6'] && $this->validateIPv6($value)) ||
($this->options['allowipvfuture'] && $this->validateIPvFuture($value))
) {
return true;
}
}
$this->error(self::NOT_IP_ADDRESS);
return false;
}
/**
* Validates an IPv4 address
*
* @param string $value
* @return bool
*/
protected function validateIPv4($value)
{
if (preg_match('/^([01]{8}\.){3}[01]{8}\z/i', $value)) {
// binary format 00000000.00000000.00000000.00000000
$value = bindec(substr($value, 0, 8)) . '.' . bindec(substr($value, 9, 8)) . '.'
. bindec(substr($value, 18, 8)) . '.' . bindec(substr($value, 27, 8));
} elseif (preg_match('/^([0-9]{3}\.){3}[0-9]{3}\z/i', $value)) {
// octet format 777.777.777.777
$value = (int) substr($value, 0, 3) . '.' . (int) substr($value, 4, 3) . '.'
. (int) substr($value, 8, 3) . '.' . (int) substr($value, 12, 3);
} elseif (preg_match('/^([0-9a-f]{2}\.){3}[0-9a-f]{2}\z/i', $value)) {
// hex format ff.ff.ff.ff
$value = hexdec(substr($value, 0, 2)) . '.' . hexdec(substr($value, 3, 2)) . '.'
. hexdec(substr($value, 6, 2)) . '.' . hexdec(substr($value, 9, 2));
}
$ip2long = ip2long($value);
if ($ip2long === false) {
return false;
}
return $value === long2ip($ip2long);
}
/**
* Validates an IPv6 address
*
* @param string $value Value to check against
* @return bool|int True when $value is a valid ipv6 address False otherwise
*/
protected function validateIPv6($value)
{
if (strlen($value) < 3) {
return $value === '::';
}
if (strpos($value, '.')) {
$lastcolon = strrpos($value, ':');
if (! ($lastcolon && $this->validateIPv4(substr($value, $lastcolon + 1)))) {
return false;
}
$value = substr($value, 0, $lastcolon) . ':0:0';
}
if (! str_contains($value, '::')) {
return preg_match('/\A(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}\z/i', $value);
}
$colonCount = substr_count($value, ':');
if ($colonCount < 8) {
return preg_match('/\A(?::|(?:[a-f0-9]{1,4}:)+):(?:(?:[a-f0-9]{1,4}:)*[a-f0-9]{1,4})?\z/i', $value);
}
// special case with ending or starting double colon
if ($colonCount === 8) {
return preg_match('/\A(?:::)?(?:[a-f0-9]{1,4}:){6}[a-f0-9]{1,4}(?:::)?\z/i', $value);
}
return false;
}
/**
* Validates an IPvFuture address.
*
* IPvFuture is loosely defined in the Section 3.2.2 of RFC 3986
*
* @param string $value Value to check against
* @return bool True when $value is a valid IPvFuture address
* False otherwise
*/
protected function validateIPvFuture($value)
{
/*
* ABNF:
* IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / ","
* / ";" / "="
*/
static $regex = '/^v([[:xdigit:]]+)\.[[:alnum:]\-\._~!\$&\'\(\)\*\+,;=:]+$/';
$result = (bool) preg_match($regex, $value, $matches);
/*
* "As such, implementations must not provide the version flag for the
* existing IPv4 and IPv6 literal address forms described below."
*/
return $result && $matches[1] !== '4' && $matches[1] !== '6';
}
}
laminas-validator/src/IsInstanceOf.php 0000644 00000004350 15240152637 0014007 0 ustar 00 <?php
namespace Laminas\Validator;
use Traversable;
use function array_key_exists;
use function array_shift;
use function func_get_args;
use function is_array;
use function iterator_to_array;
class IsInstanceOf extends AbstractValidator
{
public const NOT_INSTANCE_OF = 'notInstanceOf';
/**
* Validation failure message template definitions
*
* @var array
*/
protected $messageTemplates = [
self::NOT_INSTANCE_OF => "The input is not an instance of '%className%'",
];
/**
* Additional variables available for validation failure messages
*
* @var array
*/
protected $messageVariables = [
'className' => 'className',
];
/** @var string */
protected $className;
/**
* Sets validator options
*
* @param array|Traversable $options
* @throws Exception\InvalidArgumentException
*/
public function __construct($options = null)
{
if ($options instanceof Traversable) {
$options = iterator_to_array($options);
}
// If argument is not an array, consider first argument as class name
if (! is_array($options)) {
$options = func_get_args();
$tmpOptions = [];
$tmpOptions['className'] = array_shift($options);
$options = $tmpOptions;
}
if (! array_key_exists('className', $options)) {
throw new Exception\InvalidArgumentException('Missing option "className"');
}
parent::__construct($options);
}
/**
* Get class name
*
* @return string
*/
public function getClassName()
{
return $this->className;
}
/**
* Set class name
*
* @param string $className
* @return $this
*/
public function setClassName($className)
{
$this->className = $className;
return $this;
}
/**
* Returns true if $value is instance of $this->className
*
* @param mixed $value
* @return bool
*/
public function isValid($value)
{
if ($value instanceof $this->className) {
return true;
}
$this->error(self::NOT_INSTANCE_OF);
return false;
}
}
laminas-validator/src/Translator/TranslatorInterface.php 0000644 00000000451 15240152637 0017563 0 ustar 00 <?php
namespace Laminas\Validator\Translator;
interface TranslatorInterface
{
/**
* @param string $message
* @param string $textDomain
* @param string $locale
* @return string
*/
public function translate($message, $textDomain = 'default', $locale = null);
}
laminas-validator/src/Translator/TranslatorAwareInterface.php 0000644 00000003036 15240152637 0020545 0 ustar 00 <?php
namespace Laminas\Validator\Translator;
interface TranslatorAwareInterface
{
/**
* Sets translator to use in helper
*
* @param TranslatorInterface $translator [optional] translator.
* Default is null, which sets no translator.
* @param string $textDomain [optional] text domain
* Default is null, which skips setTranslatorTextDomain
* @return self
*/
public function setTranslator(?TranslatorInterface $translator = null, $textDomain = null);
/**
* Returns translator used in object
*
* @return TranslatorInterface|null
*/
public function getTranslator();
/**
* Checks if the object has a translator
*
* @return bool
*/
public function hasTranslator();
/**
* Sets whether translator is enabled and should be used
*
* @param bool $enabled [optional] whether translator should be used.
* Default is true.
* @return self
*/
public function setTranslatorEnabled($enabled = true);
/**
* Returns whether translator is enabled and should be used
*
* @return bool
*/
public function isTranslatorEnabled();
/**
* Set translation text domain
*
* @param string $textDomain
* @return TranslatorAwareInterface
*/
public function setTranslatorTextDomain($textDomain = 'default');
/**
* Return the translation text domain
*
* @return string
*/
public function getTranslatorTextDomain();
}
laminas-validator/src/AbstractValidator.php 0000644 00000043643 15240152637 0015103 0 ustar 00 <?php
namespace Laminas\Validator;
use Laminas\Stdlib\ArrayUtils;
use Traversable;
use function array_key_exists;
use function array_keys;
use function array_unique;
use function current;
use function implode;
use function is_array;
use function is_object;
use function is_string;
use function key;
use function method_exists;
use function str_repeat;
use function str_replace;
use function strlen;
use function substr;
use function ucfirst;
use function var_export;
use const SORT_REGULAR;
/**
* @psalm-type AbstractOptions = array{
* messages: array<string, string>,
* messageTemplates: array<string, string>,
* messageVariables: array<string, mixed>,
* translator: Translator\TranslatorInterface|null,
* translatorTextDomain: string|null,
* translatorEnabled: bool,
* valueObscured: bool,
* }
* @property array<string, mixed> $options
* @property array<string, string> $messageTemplates
* @property array<string, mixed> $messageVariables
*/
abstract class AbstractValidator implements
Translator\TranslatorAwareInterface,
ValidatorInterface
{
/**
* The value to be validated
*
* @var mixed
*/
protected $value;
/**
* Default translation object for all validate objects
*
* @var Translator\TranslatorInterface
*/
protected static $defaultTranslator;
/**
* Default text domain to be used with translator
*
* @var string
*/
protected static $defaultTranslatorTextDomain = 'default';
/**
* Limits the maximum returned length of an error message
*
* @var int
*/
protected static $messageLength = -1;
/** @var AbstractOptions&array<string, mixed> */
protected $abstractOptions = [
'messages' => [], // Array of validation failure messages
'messageTemplates' => [], // Array of validation failure message templates
'messageVariables' => [], // Array of additional variables available for validation failure messages
'translator' => null, // Translation object to used -> Translator\TranslatorInterface
'translatorTextDomain' => null, // Translation text domain
'translatorEnabled' => true, // Is translation enabled?
'valueObscured' => false, // Flag indicating whether value should be obfuscated in error messages
];
/**
* Abstract constructor for all validators
* A validator should accept following parameters:
* - nothing f.e. Validator()
* - one or multiple scalar values f.e. Validator($first, $second, $third)
* - an array f.e. Validator(array($first => 'first', $second => 'second', $third => 'third'))
* - an instance of Traversable f.e. Validator($config_instance)
*
* @param array<string, mixed>|Traversable<string, mixed> $options
*/
public function __construct($options = null)
{
// The abstract constructor allows no scalar values
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
/** @psalm-suppress RedundantConditionGivenDocblockType */
if (isset($this->messageTemplates) && is_array($this->messageTemplates)) {
$this->abstractOptions['messageTemplates'] = $this->messageTemplates;
}
/** @psalm-suppress RedundantConditionGivenDocblockType */
if (isset($this->messageVariables) && is_array($this->messageVariables)) {
$this->abstractOptions['messageVariables'] = $this->messageVariables;
}
if (is_array($options)) {
$this->setOptions($options);
}
}
/**
* Returns an option
*
* @param string $option Option to be returned
* @return mixed Returned option
* @throws Exception\InvalidArgumentException
*/
public function getOption($option)
{
if (array_key_exists($option, $this->abstractOptions)) {
return $this->abstractOptions[$option];
}
/** @psalm-suppress RedundantConditionGivenDocblockType */
if (isset($this->options) && array_key_exists($option, $this->options)) {
return $this->options[$option];
}
throw new Exception\InvalidArgumentException("Invalid option '$option'");
}
/**
* Returns all available options
*
* @return array<string, mixed> Array with all available options
*/
public function getOptions()
{
$result = $this->abstractOptions;
/** @psalm-suppress RedundantConditionGivenDocblockType */
if (isset($this->options) && is_array($this->options)) {
$result += $this->options;
}
return $result;
}
/**
* Sets one or multiple options
*
* @param array<string, mixed>|Traversable<string, mixed> $options Options to set
* @return $this Provides fluid interface
* @throws Exception\InvalidArgumentException If $options is not an array or Traversable.
*/
public function setOptions($options = [])
{
/** @psalm-suppress DocblockTypeContradiction */
if (! is_array($options) && ! $options instanceof Traversable) {
throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable');
}
/**
* @psalm-suppress RedundantConditionGivenDocblockType
* @psalm-var mixed $option
*/
foreach ($options as $name => $option) {
$fname = 'set' . ucfirst($name);
$fname2 = 'is' . ucfirst($name);
if (($name !== 'setOptions') && method_exists($this, $name)) {
$this->{$name}($option);
} elseif (($fname !== 'setOptions') && method_exists($this, $fname)) {
$this->{$fname}($option);
} elseif (method_exists($this, $fname2)) {
$this->{$fname2}($option);
} elseif (isset($this->options) && is_array($this->options)) {
$this->options[$name] = $option;
} else {
$this->abstractOptions[$name] = $option;
}
}
return $this;
}
/**
* Returns array of validation failure messages
*
* @return array<string, string>
*/
public function getMessages()
{
return array_unique($this->abstractOptions['messages'], SORT_REGULAR);
}
/**
* Invoke as command
*
* @return bool
*/
public function __invoke(mixed $value)
{
return $this->isValid($value);
}
/**
* Returns an array of the names of variables that are used in constructing validation failure messages
*
* @return list<string>
*/
public function getMessageVariables()
{
return array_keys($this->abstractOptions['messageVariables']);
}
/**
* Returns the message templates from the validator
*
* @return array<string, string>
*/
public function getMessageTemplates()
{
return $this->abstractOptions['messageTemplates'];
}
/**
* Sets the validation failure message template for a particular key
*
* @param string $messageString
* @param string|null $messageKey OPTIONAL
* @return $this Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setMessage($messageString, $messageKey = null)
{
if ($messageKey === null) {
$keys = array_keys($this->abstractOptions['messageTemplates']);
foreach ($keys as $key) {
$this->setMessage($messageString, $key);
}
return $this;
}
if (! isset($this->abstractOptions['messageTemplates'][$messageKey])) {
throw new Exception\InvalidArgumentException("No message template exists for key '$messageKey'");
}
$this->abstractOptions['messageTemplates'][$messageKey] = $messageString;
return $this;
}
/**
* Sets validation failure message templates given as an array, where the array keys are the message keys,
* and the array values are the message template strings.
*
* @param array<string, string> $messages
* @return $this
*/
public function setMessages(array $messages)
{
foreach ($messages as $key => $message) {
$this->setMessage($message, $key);
}
return $this;
}
/**
* Magic function returns the value of the requested property, if and only if it is the value or a
* message variable.
*
* @param string $property
* @return mixed
* @throws Exception\InvalidArgumentException
*/
public function __get($property)
{
if ($property === 'value') {
return $this->value;
}
if (array_key_exists($property, $this->abstractOptions['messageVariables'])) {
/** @psalm-var mixed $result */
$result = $this->abstractOptions['messageVariables'][$property];
if (is_array($result)) {
return $this->{key($result)}[current($result)];
}
return $this->{$result};
}
/** @psalm-suppress RedundantConditionGivenDocblockType */
if (isset($this->messageVariables) && array_key_exists($property, $this->messageVariables)) {
/** @psalm-var mixed $result */
$result = $this->{$this->messageVariables[$property]};
if (is_array($result)) {
return $this->{key($result)}[current($result)];
}
return $this->{$result};
}
throw new Exception\InvalidArgumentException("No property exists by the name '$property'");
}
/**
* Constructs and returns a validation failure message with the given message key and value.
*
* Returns null if and only if $messageKey does not correspond to an existing template.
*
* If a translator is available and a translation exists for $messageKey,
* the translation will be used.
*
* @param string $messageKey
* @param string|array|object $value
* @return null|string
*/
protected function createMessage($messageKey, $value)
{
if (! isset($this->abstractOptions['messageTemplates'][$messageKey])) {
return null;
}
$message = $this->abstractOptions['messageTemplates'][$messageKey];
$message = $this->translateMessage($messageKey, $message);
if (is_object($value)) {
$value = method_exists($value, '__toString')
? (string) $value
: $value::class . ' object';
} elseif (is_array($value)) {
$value = var_export($value, true);
} else {
/** @psalm-suppress RedundantCastGivenDocblockType $value */
$value = (string) $value;
}
if ($this->isValueObscured()) {
$value = str_repeat('*', strlen($value));
}
$message = str_replace('%value%', $value, $message);
foreach ($this->abstractOptions['messageVariables'] as $ident => $property) {
if (is_array($property)) {
$value = $this->{key($property)}[current($property)];
if (is_array($value)) {
$value = '[' . implode(', ', $value) . ']';
}
} else {
$value = $this->$property;
}
$message = str_replace("%$ident%", (string) $value, $message);
}
$length = self::getMessageLength();
if (($length > -1) && (strlen($message) > $length)) {
$message = substr($message, 0, $length - 3) . '...';
}
return $message;
}
/**
* @param string|null $messageKey
* @param null|string|array|object $value OPTIONAL
* @return void
*/
protected function error($messageKey, $value = null)
{
if ($messageKey === null) {
$keys = array_keys($this->abstractOptions['messageTemplates']);
$messageKey = current($keys);
}
if ($value === null) {
/** @psalm-var string|array|object $value */
$value = $this->value;
}
$message = $this->createMessage($messageKey, $value);
if (! is_string($message)) {
return;
}
$this->abstractOptions['messages'][$messageKey] = $message;
}
/**
* Returns the validation value
*
* @return mixed Value to be validated
*/
protected function getValue()
{
return $this->value;
}
/**
* Sets the value to be validated and clears the messages and errors arrays
*
* @return void
*/
protected function setValue(mixed $value)
{
$this->value = $value;
$this->abstractOptions['messages'] = [];
}
/**
* Set flag indicating whether or not value should be obfuscated in messages
*
* @param bool $flag
* @return $this
*/
public function setValueObscured($flag)
{
/** @psalm-suppress RedundantCastGivenDocblockType */
$this->abstractOptions['valueObscured'] = (bool) $flag;
return $this;
}
/**
* Retrieve flag indicating whether or not value should be obfuscated in
* messages
*
* @return bool
*/
public function isValueObscured()
{
return $this->abstractOptions['valueObscured'];
}
/**
* Set translation object
*
* @param string $textDomain (optional)
* @return $this
* @throws Exception\InvalidArgumentException
*/
public function setTranslator(?Translator\TranslatorInterface $translator = null, $textDomain = null)
{
$this->abstractOptions['translator'] = $translator;
if (null !== $textDomain) {
$this->setTranslatorTextDomain($textDomain);
}
return $this;
}
/**
* Return translation object
*
* @return Translator\TranslatorInterface|null
*/
public function getTranslator()
{
if (! $this->isTranslatorEnabled()) {
return null;
}
if (null === $this->abstractOptions['translator']) {
$this->abstractOptions['translator'] = self::getDefaultTranslator();
}
return $this->abstractOptions['translator'];
}
/**
* Does this validator have its own specific translator?
*
* @return bool
*/
public function hasTranslator()
{
return (bool) $this->abstractOptions['translator'];
}
/**
* Set translation text domain
*
* @param string $textDomain
* @return $this
*/
public function setTranslatorTextDomain($textDomain = 'default')
{
$this->abstractOptions['translatorTextDomain'] = $textDomain;
return $this;
}
/**
* Return the translation text domain
*
* @return string
*/
public function getTranslatorTextDomain()
{
if (null === $this->abstractOptions['translatorTextDomain']) {
$this->abstractOptions['translatorTextDomain'] =
self::getDefaultTranslatorTextDomain();
}
return $this->abstractOptions['translatorTextDomain'];
}
/**
* Set default translation object for all validate objects
*
* @param string $textDomain (optional)
* @return void
* @throws Exception\InvalidArgumentException
*/
public static function setDefaultTranslator(?Translator\TranslatorInterface $translator = null, $textDomain = null)
{
static::$defaultTranslator = $translator;
if (null !== $textDomain) {
self::setDefaultTranslatorTextDomain($textDomain);
}
}
/**
* Get default translation object for all validate objects
*
* @return Translator\TranslatorInterface|null
*/
public static function getDefaultTranslator()
{
return static::$defaultTranslator;
}
/**
* Is there a default translation object set?
*
* @return bool
*/
public static function hasDefaultTranslator()
{
return (bool) static::$defaultTranslator;
}
/**
* Set default translation text domain for all validate objects
*
* @param string $textDomain
* @return void
*/
public static function setDefaultTranslatorTextDomain($textDomain = 'default')
{
static::$defaultTranslatorTextDomain = $textDomain;
}
/**
* Get default translation text domain for all validate objects
*
* @return string
*/
public static function getDefaultTranslatorTextDomain()
{
return static::$defaultTranslatorTextDomain;
}
/**
* Indicate whether or not translation should be enabled
*
* @param bool $enabled
* @return $this
*/
public function setTranslatorEnabled($enabled = true)
{
/** @psalm-suppress RedundantCastGivenDocblockType */
$this->abstractOptions['translatorEnabled'] = (bool) $enabled;
return $this;
}
/**
* Is translation enabled?
*
* @return bool
*/
public function isTranslatorEnabled()
{
return $this->abstractOptions['translatorEnabled'];
}
/**
* Returns the maximum allowed message length
*
* @return int
*/
public static function getMessageLength()
{
return static::$messageLength;
}
/**
* Sets the maximum allowed message length
*
* @param int $length
* @return void
*/
public static function setMessageLength($length = -1)
{
static::$messageLength = $length;
}
/**
* Translate a validation message
*
* @param string $messageKey
* @param string $message
* @return string
*/
protected function translateMessage($messageKey, $message)
{
$translator = $this->getTranslator();
if (! $translator) {
return $message;
}
return $translator->translate($message, $this->getTranslatorTextDomain());
}
}
laminas-validator/src/GreaterThan.php 0000644 00000006547 15240152637 0013700 0 ustar 00 <?php
namespace Laminas\Validator;
use Laminas\Stdlib\ArrayUtils;
use Traversable;
use function array_key_exists;
use function array_shift;
use function func_get_args;
use function is_array;
class GreaterThan extends AbstractValidator
{
public const NOT_GREATER = 'notGreaterThan';
public const NOT_GREATER_INCLUSIVE = 'notGreaterThanInclusive';
/**
* Validation failure message template definitions
*
* @var array
*/
protected $messageTemplates = [
self::NOT_GREATER => "The input is not greater than '%min%'",
self::NOT_GREATER_INCLUSIVE => "The input is not greater than or equal to '%min%'",
];
/** @var array */
protected $messageVariables = [
'min' => 'min',
];
/**
* Minimum value
*
* @var mixed
*/
protected $min;
/**
* Whether to do inclusive comparisons, allowing equivalence to max
*
* If false, then strict comparisons are done, and the value may equal
* the min option
*
* @var bool
*/
protected $inclusive;
/**
* Sets validator options
*
* @param array|Traversable $options
* @throws Exception\InvalidArgumentException
*/
public function __construct($options = null)
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (! is_array($options)) {
$options = func_get_args();
$temp['min'] = array_shift($options);
if (! empty($options)) {
$temp['inclusive'] = array_shift($options);
}
$options = $temp;
}
if (! array_key_exists('min', $options)) {
throw new Exception\InvalidArgumentException("Missing option 'min'");
}
if (! array_key_exists('inclusive', $options)) {
$options['inclusive'] = false;
}
$this->setMin($options['min'])
->setInclusive($options['inclusive']);
parent::__construct($options);
}
/**
* Returns the min option
*
* @return mixed
*/
public function getMin()
{
return $this->min;
}
/**
* Sets the min option
*
* @return $this Provides a fluent interface
*/
public function setMin(mixed $min)
{
$this->min = $min;
return $this;
}
/**
* Returns the inclusive option
*
* @return bool
*/
public function getInclusive()
{
return $this->inclusive;
}
/**
* Sets the inclusive option
*
* @param bool $inclusive
* @return $this Provides a fluent interface
*/
public function setInclusive($inclusive)
{
$this->inclusive = $inclusive;
return $this;
}
/**
* Returns true if and only if $value is greater than min option
*
* @param mixed $value
* @return bool
*/
public function isValid($value)
{
$this->setValue($value);
if ($this->inclusive) {
if ($this->min > $value) {
$this->error(self::NOT_GREATER_INCLUSIVE);
return false;
}
} else {
if ($this->min >= $value) {
$this->error(self::NOT_GREATER);
return false;
}
}
return true;
}
}
laminas-validator/src/ValidatorInterface.php 0000644 00000002300 15240152637 0015221 0 ustar 00 <?php
namespace Laminas\Validator;
/**
* @psalm-type ValidatorSpecification = array{
* name: string|class-string<ValidatorInterface>,
* priority?: int,
* break_chain_on_failure?: bool,
* options?: array<string, mixed>,
* }
*/
interface ValidatorInterface
{
/**
* Returns true if and only if $value meets the validation requirements
*
* If $value fails validation, then this method returns false, and
* getMessages() will return an array of messages that explain why the
* validation failed.
*
* @param mixed $value
* @return bool
* @throws Exception\RuntimeException If validation of $value is impossible.
*/
public function isValid($value);
/**
* Returns an array of messages that explain why the most recent isValid()
* call returned false. The array keys are validation failure message identifiers,
* and the array values are the corresponding human-readable message strings.
*
* If isValid() was never called or if the most recent isValid() call
* returned true, then this method returns an empty array.
*
* @return array<string, string>
*/
public function getMessages();
}
laminas-validator/src/LessThan.php 0000644 00000006717 15240152637 0013214 0 ustar 00 <?php
namespace Laminas\Validator;
use Laminas\Stdlib\ArrayUtils;
use Traversable;
use function array_key_exists;
use function array_shift;
use function func_get_args;
use function is_array;
class LessThan extends AbstractValidator
{
public const NOT_LESS = 'notLessThan';
public const NOT_LESS_INCLUSIVE = 'notLessThanInclusive';
/**
* Validation failure message template definitions
*
* @var array
*/
protected $messageTemplates = [
self::NOT_LESS => "The input is not less than '%max%'",
self::NOT_LESS_INCLUSIVE => "The input is not less or equal than '%max%'",
];
/**
* Additional variables available for validation failure messages
*
* @var array
*/
protected $messageVariables = [
'max' => 'max',
];
/**
* Maximum value
*
* @var mixed
*/
protected $max;
/**
* Whether to do inclusive comparisons, allowing equivalence to max
*
* If false, then strict comparisons are done, and the value may equal
* the max option
*
* @var bool
*/
protected $inclusive;
/**
* Sets validator options
*
* @param array|Traversable $options
* @throws Exception\InvalidArgumentException
*/
public function __construct($options = null)
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (! is_array($options)) {
$options = func_get_args();
$temp['max'] = array_shift($options);
if (! empty($options)) {
$temp['inclusive'] = array_shift($options);
}
$options = $temp;
}
if (! array_key_exists('max', $options)) {
throw new Exception\InvalidArgumentException("Missing option 'max'");
}
if (! array_key_exists('inclusive', $options)) {
$options['inclusive'] = false;
}
$this->setMax($options['max'])
->setInclusive($options['inclusive']);
parent::__construct($options);
}
/**
* Returns the max option
*
* @return mixed
*/
public function getMax()
{
return $this->max;
}
/**
* Sets the max option
*
* @return $this Provides a fluent interface
*/
public function setMax(mixed $max)
{
$this->max = $max;
return $this;
}
/**
* Returns the inclusive option
*
* @return bool
*/
public function getInclusive()
{
return $this->inclusive;
}
/**
* Sets the inclusive option
*
* @param bool $inclusive
* @return $this Provides a fluent interface
*/
public function setInclusive($inclusive)
{
$this->inclusive = $inclusive;
return $this;
}
/**
* Returns true if and only if $value is less than max option, inclusively
* when the inclusive option is true
*
* @param mixed $value
* @return bool
*/
public function isValid($value)
{
$this->setValue($value);
if ($this->inclusive) {
if ($value > $this->max) {
$this->error(self::NOT_LESS_INCLUSIVE);
return false;
}
} else {
if ($value >= $this->max) {
$this->error(self::NOT_LESS);
return false;
}
}
return true;
}
}
laminas-validator/README.md 0000644 00000006644 15240152637 0011451 0 ustar 00 # laminas-validator
[](https://github.com/laminas/laminas-validator/actions/workflows/continuous-integration.yml)
> ## 🇷🇺 Русским гражданам
>
> Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм.
>
> У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую.
>
> Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!"
>
> ## 🇺🇸 To Citizens of Russia
>
> We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism.
>
> One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences.
>
> You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!"
laminas-validator provides a set of commonly needed validators. It also provides a
simple validator chaining mechanism by which multiple validators may be applied
to a single datum in a user-defined order.
## Installation
Run the following to install this library:
```bash
$ composer require laminas/laminas-validator
```
## Documentation
Browse the documentation online at https://docs.laminas.dev/laminas-validator/
## Support
* [Issues](https://github.com/laminas/laminas-validator/issues/)
* [Chat](https://laminas.dev/chat/)
* [Forum](https://discourse.laminas.dev/)
laminas-validator/composer.json 0000644 00000006525 15240152637 0012712 0 ustar 00 {
"name": "laminas/laminas-validator",
"description": "Validation classes for a wide range of domains, and the ability to chain validators to create complex validation criteria",
"license": "BSD-3-Clause",
"keywords": [
"laminas",
"validator"
],
"homepage": "https://laminas.dev",
"support": {
"docs": "https://docs.laminas.dev/laminas-validator/",
"issues": "https://github.com/laminas/laminas-validator/issues",
"source": "https://github.com/laminas/laminas-validator",
"rss": "https://github.com/laminas/laminas-validator/releases.atom",
"chat": "https://laminas.dev/chat",
"forum": "https://discourse.laminas.dev"
},
"config": {
"sort-packages": true,
"platform": {
"php": "8.0.99"
},
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"extra": {
"laminas": {
"component": "Laminas\\Validator",
"config-provider": "Laminas\\Validator\\ConfigProvider"
}
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"laminas/laminas-servicemanager": "^3.12.0",
"laminas/laminas-stdlib": "^3.13",
"psr/http-message": "^1.0.1"
},
"require-dev": {
"laminas/laminas-coding-standard": "^2.4.0",
"laminas/laminas-db": "^2.15.0",
"laminas/laminas-filter": "^2.23.0",
"laminas/laminas-http": "^2.17.0",
"laminas/laminas-i18n": "^2.19",
"laminas/laminas-session": "^2.13.0",
"laminas/laminas-uri": "^2.10.0",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.18.0",
"psr/http-client": "^1.0.1",
"psr/http-factory": "^1.0.1",
"vimeo/psalm": "^4.28"
},
"suggest": {
"laminas/laminas-db": "Laminas\\Db component, required by the (No)RecordExists validator",
"laminas/laminas-filter": "Laminas\\Filter component, required by the Digits validator",
"laminas/laminas-i18n": "Laminas\\I18n component to allow translation of validation error messages",
"laminas/laminas-i18n-resources": "Translations of validator messages",
"laminas/laminas-servicemanager": "Laminas\\ServiceManager component to allow using the ValidatorPluginManager and validator chains",
"laminas/laminas-session": "Laminas\\Session component, ^2.8; required by the Csrf validator",
"laminas/laminas-uri": "Laminas\\Uri component, required by the Uri and Sitemap\\Loc validators",
"psr/http-message": "psr/http-message, required when validating PSR-7 UploadedFileInterface instances via the Upload and UploadFile validators"
},
"autoload": {
"psr-4": {
"Laminas\\Validator\\": "src/"
}
},
"autoload-dev": {
"files": [
"test/autoload.php"
],
"psr-4": {
"LaminasTest\\Validator\\": "test/"
}
},
"scripts": {
"check": [
"@cs-check",
"@test"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml",
"static-analysis": "psalm --shepherd --stats"
},
"conflict": {
"zendframework/zend-validator": "*"
}
}
laminas-validator/COPYRIGHT.md 0000644 00000000133 15240152637 0012047 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/)
laminas-validator/composer.lock 0000644 00000551721 15240152637 0012674 0 ustar 00 {
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "6e7995bf6995ad1fed5a115c0fcfc0b6",
"packages": [
{
"name": "laminas/laminas-servicemanager",
"version": "3.19.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-servicemanager.git",
"reference": "ed160729bb8721127efdaac799f9a298963345b1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/ed160729bb8721127efdaac799f9a298963345b1",
"reference": "ed160729bb8721127efdaac799f9a298963345b1",
"shasum": ""
},
"require": {
"laminas/laminas-stdlib": "^3.2.1",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"psr/container": "^1.0"
},
"conflict": {
"ext-psr": "*",
"laminas/laminas-code": "<3.3.1",
"zendframework/zend-code": "<3.3.1",
"zendframework/zend-servicemanager": "*"
},
"provide": {
"psr/container-implementation": "^1.0"
},
"replace": {
"container-interop/container-interop": "^1.2.0"
},
"require-dev": {
"composer/package-versions-deprecated": "^1.11.99.5",
"laminas/laminas-coding-standard": "~2.4.0",
"laminas/laminas-container-config-test": "^0.7",
"laminas/laminas-dependency-plugin": "^2.2",
"mikey179/vfsstream": "^1.6.11@alpha",
"ocramius/proxy-manager": "^2.14.1",
"phpbench/phpbench": "^1.2.6",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.28"
},
"suggest": {
"ocramius/proxy-manager": "ProxyManager ^2.1.1 to handle lazy initialization of services"
},
"bin": [
"bin/generate-deps-for-config-factory",
"bin/generate-factory-for-class"
],
"type": "library",
"autoload": {
"files": [
"src/autoload.php"
],
"psr-4": {
"Laminas\\ServiceManager\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Factory-Driven Dependency Injection Container",
"homepage": "https://laminas.dev",
"keywords": [
"PSR-11",
"dependency-injection",
"di",
"dic",
"laminas",
"service-manager",
"servicemanager"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-servicemanager/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-servicemanager/issues",
"rss": "https://github.com/laminas/laminas-servicemanager/releases.atom",
"source": "https://github.com/laminas/laminas-servicemanager"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-10T20:59:22+00:00"
},
{
"name": "laminas/laminas-stdlib",
"version": "3.15.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-stdlib.git",
"reference": "63b66bd4b696f024f42616b9d95cdb10e5109c27"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/63b66bd4b696f024f42616b9d95cdb10e5109c27",
"reference": "63b66bd4b696f024f42616b9d95cdb10e5109c27",
"shasum": ""
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-stdlib": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "^2.4.0",
"phpbench/phpbench": "^1.2.6",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.28"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Stdlib\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "SPL extensions, array utilities, error handlers, and more",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"stdlib"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-stdlib/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-stdlib/issues",
"rss": "https://github.com/laminas/laminas-stdlib/releases.atom",
"source": "https://github.com/laminas/laminas-stdlib"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-10T19:10:24+00:00"
},
{
"name": "psr/container",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
"shasum": ""
},
"require": {
"php": ">=7.4.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
"homepage": "https://github.com/php-fig/container",
"keywords": [
"PSR-11",
"container",
"container-interface",
"container-interop",
"psr"
],
"support": {
"issues": "https://github.com/php-fig/container/issues",
"source": "https://github.com/php-fig/container/tree/1.1.2"
},
"time": "2021-11-05T16:50:12+00:00"
}
],
"packages-dev": [
{
"name": "amphp/amp",
"version": "v2.6.2",
"source": {
"type": "git",
"url": "https://github.com/amphp/amp.git",
"reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb",
"reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"amphp/php-cs-fixer-config": "dev-master",
"amphp/phpunit-util": "^1",
"ext-json": "*",
"jetbrains/phpstorm-stubs": "^2019.3",
"phpunit/phpunit": "^7 | ^8 | ^9",
"psalm/phar": "^3.11@dev",
"react/promise": "^2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
},
"autoload": {
"files": [
"lib/functions.php",
"lib/Internal/functions.php"
],
"psr-4": {
"Amp\\": "lib"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Daniel Lowrey",
"email": "rdlowrey@php.net"
},
{
"name": "Aaron Piotrowski",
"email": "aaron@trowski.com"
},
{
"name": "Bob Weinand",
"email": "bobwei9@hotmail.com"
},
{
"name": "Niklas Keller",
"email": "me@kelunik.com"
}
],
"description": "A non-blocking concurrency framework for PHP applications.",
"homepage": "https://amphp.org/amp",
"keywords": [
"async",
"asynchronous",
"awaitable",
"concurrency",
"event",
"event-loop",
"future",
"non-blocking",
"promise"
],
"support": {
"irc": "irc://irc.freenode.org/amphp",
"issues": "https://github.com/amphp/amp/issues",
"source": "https://github.com/amphp/amp/tree/v2.6.2"
},
"funding": [
{
"url": "https://github.com/amphp",
"type": "github"
}
],
"time": "2022-02-20T17:52:18+00:00"
},
{
"name": "amphp/byte-stream",
"version": "v1.8.1",
"source": {
"type": "git",
"url": "https://github.com/amphp/byte-stream.git",
"reference": "acbd8002b3536485c997c4e019206b3f10ca15bd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd",
"reference": "acbd8002b3536485c997c4e019206b3f10ca15bd",
"shasum": ""
},
"require": {
"amphp/amp": "^2",
"php": ">=7.1"
},
"require-dev": {
"amphp/php-cs-fixer-config": "dev-master",
"amphp/phpunit-util": "^1.4",
"friendsofphp/php-cs-fixer": "^2.3",
"jetbrains/phpstorm-stubs": "^2019.3",
"phpunit/phpunit": "^6 || ^7 || ^8",
"psalm/phar": "^3.11.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"files": [
"lib/functions.php"
],
"psr-4": {
"Amp\\ByteStream\\": "lib"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Aaron Piotrowski",
"email": "aaron@trowski.com"
},
{
"name": "Niklas Keller",
"email": "me@kelunik.com"
}
],
"description": "A stream abstraction to make working with non-blocking I/O simple.",
"homepage": "http://amphp.org/byte-stream",
"keywords": [
"amp",
"amphp",
"async",
"io",
"non-blocking",
"stream"
],
"support": {
"irc": "irc://irc.freenode.org/amphp",
"issues": "https://github.com/amphp/byte-stream/issues",
"source": "https://github.com/amphp/byte-stream/tree/v1.8.1"
},
"funding": [
{
"url": "https://github.com/amphp",
"type": "github"
}
],
"time": "2021-03-30T17:13:30+00:00"
},
{
"name": "composer/package-versions-deprecated",
"version": "1.11.99.5",
"source": {
"type": "git",
"url": "https://github.com/composer/package-versions-deprecated.git",
"reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d",
"reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.1.0 || ^2.0",
"php": "^7 || ^8"
},
"replace": {
"ocramius/package-versions": "1.11.99"
},
"require-dev": {
"composer/composer": "^1.9.3 || ^2.0@dev",
"ext-zip": "^1.13",
"phpunit/phpunit": "^6.5 || ^7"
},
"type": "composer-plugin",
"extra": {
"class": "PackageVersions\\Installer",
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"PackageVersions\\": "src/PackageVersions"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be"
}
],
"description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
"support": {
"issues": "https://github.com/composer/package-versions-deprecated/issues",
"source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-01-17T14:14:24+00:00"
},
{
"name": "composer/pcre",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
"reference": "4482b6409ca6bfc2af043a5711cd21ac3e7a8dfb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/4482b6409ca6bfc2af043a5711cd21ac3e7a8dfb",
"reference": "4482b6409ca6bfc2af043a5711cd21ac3e7a8dfb",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1.3",
"phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Pcre\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "PCRE wrapping library that offers type-safe preg_* replacements.",
"keywords": [
"PCRE",
"preg",
"regex",
"regular expression"
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.0.2"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-11-03T20:24:16+00:00"
},
{
"name": "composer/semver",
"version": "3.3.2",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1.4",
"symfony/phpunit-bridge": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Semver\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
},
{
"name": "Rob Bast",
"email": "rob.bast@gmail.com",
"homepage": "http://robbast.nl"
}
],
"description": "Semver library that offers utilities, version constraint parsing and validation.",
"keywords": [
"semantic",
"semver",
"validation",
"versioning"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.3.2"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-04-01T19:23:25+00:00"
},
{
"name": "composer/xdebug-handler",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
"reference": "ced299686f41dce890debac69273b47ffe98a40c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c",
"reference": "ced299686f41dce890debac69273b47ffe98a40c",
"shasum": ""
},
"require": {
"composer/pcre": "^1 || ^2 || ^3",
"php": "^7.2.5 || ^8.0",
"psr/log": "^1 || ^2 || ^3"
},
"require-dev": {
"phpstan/phpstan": "^1.0",
"phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Composer\\XdebugHandler\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "John Stevenson",
"email": "john-stevenson@blueyonder.co.uk"
}
],
"description": "Restarts a process without Xdebug.",
"keywords": [
"Xdebug",
"performance"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/xdebug-handler/issues",
"source": "https://github.com/composer/xdebug-handler/tree/3.0.3"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-02-25T21:32:43+00:00"
},
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
"version": "v0.7.2",
"source": {
"type": "git",
"url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
"phpcompatibility/php-compatibility": "^9.0"
},
"type": "composer-plugin",
"extra": {
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
"Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Franck Nijhof",
"email": "franck.nijhof@dealerdirect.com",
"homepage": "http://www.frenck.nl",
"role": "Developer / IT Manager"
},
{
"name": "Contributors",
"homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
"homepage": "http://www.dealerdirect.com",
"keywords": [
"PHPCodeSniffer",
"PHP_CodeSniffer",
"code quality",
"codesniffer",
"composer",
"installer",
"phpcbf",
"phpcs",
"plugin",
"qa",
"quality",
"standard",
"standards",
"style guide",
"stylecheck",
"tests"
],
"support": {
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
"time": "2022-02-04T12:51:07+00:00"
},
{
"name": "dnoegel/php-xdg-base-dir",
"version": "v0.1.1",
"source": {
"type": "git",
"url": "https://github.com/dnoegel/php-xdg-base-dir.git",
"reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd",
"reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"require-dev": {
"phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35"
},
"type": "library",
"autoload": {
"psr-4": {
"XdgBaseDir\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "implementation of xdg base directory specification for php",
"support": {
"issues": "https://github.com/dnoegel/php-xdg-base-dir/issues",
"source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1"
},
"time": "2019-12-04T15:06:13+00:00"
},
{
"name": "doctrine/instantiator",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9",
"ext-pdo": "*",
"ext-phar": "*",
"phpbench/phpbench": "^0.16 || ^1",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-phpunit": "^1",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"vimeo/psalm": "^4.22"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "https://ocramius.github.io/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://www.doctrine-project.org/projects/instantiator.html",
"keywords": [
"constructor",
"instantiate"
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/1.4.1"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
"type": "tidelift"
}
],
"time": "2022-03-03T08:28:38+00:00"
},
{
"name": "felixfbecker/advanced-json-rpc",
"version": "v3.2.1",
"source": {
"type": "git",
"url": "https://github.com/felixfbecker/php-advanced-json-rpc.git",
"reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447",
"reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447",
"shasum": ""
},
"require": {
"netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0",
"php": "^7.1 || ^8.0",
"phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0"
},
"require-dev": {
"phpunit/phpunit": "^7.0 || ^8.0"
},
"type": "library",
"autoload": {
"psr-4": {
"AdvancedJsonRpc\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"ISC"
],
"authors": [
{
"name": "Felix Becker",
"email": "felix.b@outlook.com"
}
],
"description": "A more advanced JSONRPC implementation",
"support": {
"issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues",
"source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1"
},
"time": "2021-06-11T22:34:44+00:00"
},
{
"name": "felixfbecker/language-server-protocol",
"version": "v1.5.2",
"source": {
"type": "git",
"url": "https://github.com/felixfbecker/php-language-server-protocol.git",
"reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842",
"reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"phpstan/phpstan": "*",
"squizlabs/php_codesniffer": "^3.1",
"vimeo/psalm": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"LanguageServerProtocol\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"ISC"
],
"authors": [
{
"name": "Felix Becker",
"email": "felix.b@outlook.com"
}
],
"description": "PHP classes for the Language Server Protocol",
"keywords": [
"language",
"microsoft",
"php",
"server"
],
"support": {
"issues": "https://github.com/felixfbecker/php-language-server-protocol/issues",
"source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2"
},
"time": "2022-03-02T22:36:06+00:00"
},
{
"name": "laminas/laminas-coding-standard",
"version": "2.4.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-coding-standard.git",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7",
"php": "^7.4 || ^8.0",
"slevomat/coding-standard": "^7.0",
"squizlabs/php_codesniffer": "^3.6",
"webimpress/coding-standard": "^1.2"
},
"conflict": {
"phpstan/phpdoc-parser": ">=1.6.0"
},
"type": "phpcodesniffer-standard",
"autoload": {
"psr-4": {
"LaminasCodingStandard\\": "src/LaminasCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Laminas Coding Standard",
"homepage": "https://laminas.dev",
"keywords": [
"Coding Standard",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-coding-standard/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-coding-standard/issues",
"rss": "https://github.com/laminas/laminas-coding-standard/releases.atom",
"source": "https://github.com/laminas/laminas-coding-standard"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-08-24T17:45:47+00:00"
},
{
"name": "laminas/laminas-db",
"version": "2.15.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-db.git",
"reference": "1125ef2e55108bdfcc1f0030d3a0f9b895e09606"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-db/zipball/1125ef2e55108bdfcc1f0030d3a0f9b895e09606",
"reference": "1125ef2e55108bdfcc1f0030d3a0f9b895e09606",
"shasum": ""
},
"require": {
"laminas/laminas-stdlib": "^3.7.1",
"php": "^7.3 || ~8.0.0 || ~8.1.0"
},
"conflict": {
"zendframework/zend-db": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.2.1",
"laminas/laminas-eventmanager": "^3.4.0",
"laminas/laminas-hydrator": "^3.2 || ^4.3",
"laminas/laminas-servicemanager": "^3.7.0",
"phpunit/phpunit": "^9.5.19"
},
"suggest": {
"laminas/laminas-eventmanager": "Laminas\\EventManager component",
"laminas/laminas-hydrator": "(^3.2 || ^4.3) Laminas\\Hydrator component for using HydratingResultSets",
"laminas/laminas-servicemanager": "Laminas\\ServiceManager component"
},
"type": "library",
"extra": {
"laminas": {
"component": "Laminas\\Db",
"config-provider": "Laminas\\Db\\ConfigProvider"
}
},
"autoload": {
"psr-4": {
"Laminas\\Db\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Database abstraction layer, SQL abstraction, result set abstraction, and RowDataGateway and TableDataGateway implementations",
"homepage": "https://laminas.dev",
"keywords": [
"db",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-db/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-db/issues",
"rss": "https://github.com/laminas/laminas-db/releases.atom",
"source": "https://github.com/laminas/laminas-db"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-04-11T13:26:20+00:00"
},
{
"name": "laminas/laminas-escaper",
"version": "2.12.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-escaper.git",
"reference": "ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490",
"reference": "ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-mbstring": "*",
"php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-escaper": "*"
},
"require-dev": {
"infection/infection": "^0.26.6",
"laminas/laminas-coding-standard": "~2.4.0",
"maglnet/composer-require-checker": "^3.8.0",
"phpunit/phpunit": "^9.5.18",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.22.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Escaper\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs",
"homepage": "https://laminas.dev",
"keywords": [
"escaper",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-escaper/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-escaper/issues",
"rss": "https://github.com/laminas/laminas-escaper/releases.atom",
"source": "https://github.com/laminas/laminas-escaper"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-10T10:11:09+00:00"
},
{
"name": "laminas/laminas-eventmanager",
"version": "3.6.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-eventmanager.git",
"reference": "3f1afbad86cd34a431fdc069f265cfe6f8fc8308"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-eventmanager/zipball/3f1afbad86cd34a431fdc069f265cfe6f8fc8308",
"reference": "3f1afbad86cd34a431fdc069f265cfe6f8fc8308",
"shasum": ""
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"container-interop/container-interop": "<1.2",
"zendframework/zend-eventmanager": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"laminas/laminas-stdlib": "^3.15",
"phpbench/phpbench": "^1.2.6",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"psr/container": "^1.1.2 || ^2.0.2",
"vimeo/psalm": "^4.28"
},
"suggest": {
"laminas/laminas-stdlib": "^2.7.3 || ^3.0, to use the FilterChain feature",
"psr/container": "^1.1.2 || ^2.0.2, to use the lazy listeners feature"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\EventManager\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Trigger and listen to events within a PHP application",
"homepage": "https://laminas.dev",
"keywords": [
"event",
"eventmanager",
"events",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-eventmanager/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-eventmanager/issues",
"rss": "https://github.com/laminas/laminas-eventmanager/releases.atom",
"source": "https://github.com/laminas/laminas-eventmanager"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-11T12:46:13+00:00"
},
{
"name": "laminas/laminas-filter",
"version": "2.28.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-filter.git",
"reference": "b0290636e88083acb42dba7b883aeaa16a60244f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-filter/zipball/b0290636e88083acb42dba7b883aeaa16a60244f",
"reference": "b0290636e88083acb42dba7b883aeaa16a60244f",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"laminas/laminas-servicemanager": "^3.14.0",
"laminas/laminas-stdlib": "^3.13.0",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"laminas/laminas-validator": "<2.10.1",
"zendframework/zend-filter": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"laminas/laminas-crypt": "^3.9",
"laminas/laminas-uri": "^2.10",
"pear/archive_tar": "^1.4.14",
"phpunit/phpunit": "^9.5.26",
"psalm/plugin-phpunit": "^0.18.3",
"psr/http-factory": "^1.0.1",
"vimeo/psalm": "^4.30"
},
"suggest": {
"laminas/laminas-crypt": "Laminas\\Crypt component, for encryption filters",
"laminas/laminas-i18n": "Laminas\\I18n component for filters depending on i18n functionality",
"laminas/laminas-uri": "Laminas\\Uri component, for the UriNormalize filter",
"psr/http-factory-implementation": "psr/http-factory-implementation, for creating file upload instances when consuming PSR-7 in file upload filters"
},
"type": "library",
"extra": {
"laminas": {
"component": "Laminas\\Filter",
"config-provider": "Laminas\\Filter\\ConfigProvider"
}
},
"autoload": {
"psr-4": {
"Laminas\\Filter\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Programmatically filter and normalize data and files",
"homepage": "https://laminas.dev",
"keywords": [
"filter",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-filter/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-filter/issues",
"rss": "https://github.com/laminas/laminas-filter/releases.atom",
"source": "https://github.com/laminas/laminas-filter"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-11-07T20:46:55+00:00"
},
{
"name": "laminas/laminas-http",
"version": "2.17.1",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-http.git",
"reference": "324e5895235fe40bfd5a4e2a0337bd7bf9a97a50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-http/zipball/324e5895235fe40bfd5a4e2a0337bd7bf9a97a50",
"reference": "324e5895235fe40bfd5a4e2a0337bd7bf9a97a50",
"shasum": ""
},
"require": {
"laminas/laminas-loader": "^2.8",
"laminas/laminas-stdlib": "^3.6",
"laminas/laminas-uri": "^2.9.1",
"laminas/laminas-validator": "^2.15",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-http": "*"
},
"require-dev": {
"ext-curl": "*",
"laminas/laminas-coding-standard": "~2.4.0",
"phpunit/phpunit": "^9.5.25"
},
"suggest": {
"paragonie/certainty": "For automated management of cacert.pem"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Http\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Provides an easy interface for performing Hyper-Text Transfer Protocol (HTTP) requests",
"homepage": "https://laminas.dev",
"keywords": [
"http",
"http client",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-http/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-http/issues",
"rss": "https://github.com/laminas/laminas-http/releases.atom",
"source": "https://github.com/laminas/laminas-http"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-11-11T09:16:23+00:00"
},
{
"name": "laminas/laminas-i18n",
"version": "2.19.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-i18n.git",
"reference": "ebabca3a6398fc872127bc69a51bda5afc720d67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-i18n/zipball/ebabca3a6398fc872127bc69a51bda5afc720d67",
"reference": "ebabca3a6398fc872127bc69a51bda5afc720d67",
"shasum": ""
},
"require": {
"ext-intl": "*",
"laminas/laminas-servicemanager": "^3.14.0",
"laminas/laminas-stdlib": "^2.7 || ^3.0",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"laminas/laminas-view": "<2.20.0",
"phpspec/prophecy": "<1.9.0",
"zendframework/zend-i18n": "*"
},
"require-dev": {
"laminas/laminas-cache": "^3.6",
"laminas/laminas-cache-storage-adapter-memory": "^2.1",
"laminas/laminas-cache-storage-deprecated-factory": "^1.0.1",
"laminas/laminas-coding-standard": "~2.4.0",
"laminas/laminas-config": "^3.7",
"laminas/laminas-eventmanager": "^3.5.0",
"laminas/laminas-filter": "^2.21",
"laminas/laminas-validator": "^2.25",
"laminas/laminas-view": "^2.23",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.28"
},
"suggest": {
"laminas/laminas-cache": "You should install this package to cache the translations",
"laminas/laminas-config": "You should install this package to use the INI translation format",
"laminas/laminas-eventmanager": "You should install this package to use the events in the translator",
"laminas/laminas-filter": "You should install this package to use the provided filters",
"laminas/laminas-i18n-resources": "This package provides validator and captcha translations",
"laminas/laminas-validator": "You should install this package to use the provided validators",
"laminas/laminas-view": "You should install this package to use the provided view helpers"
},
"type": "library",
"extra": {
"laminas": {
"component": "Laminas\\I18n",
"config-provider": "Laminas\\I18n\\ConfigProvider"
}
},
"autoload": {
"psr-4": {
"Laminas\\I18n\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Provide translations for your application, and filter and validate internationalized values",
"homepage": "https://laminas.dev",
"keywords": [
"i18n",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-i18n/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-i18n/issues",
"rss": "https://github.com/laminas/laminas-i18n/releases.atom",
"source": "https://github.com/laminas/laminas-i18n"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-10T15:48:56+00:00"
},
{
"name": "laminas/laminas-loader",
"version": "2.9.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-loader.git",
"reference": "51ed9c3fa42d1098a9997571730c0cbf42d078d3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-loader/zipball/51ed9c3fa42d1098a9997571730c0cbf42d078d3",
"reference": "51ed9c3fa42d1098a9997571730c0cbf42d078d3",
"shasum": ""
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-loader": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"phpunit/phpunit": "~9.5.25"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Loader\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Autoloading and plugin loading strategies",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"loader"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-loader/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-loader/issues",
"rss": "https://github.com/laminas/laminas-loader/releases.atom",
"source": "https://github.com/laminas/laminas-loader"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-16T12:50:49+00:00"
},
{
"name": "laminas/laminas-session",
"version": "2.13.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-session.git",
"reference": "9f8a6077dd22b3b253583b1be84ddd5bf6fa1ef4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-session/zipball/9f8a6077dd22b3b253583b1be84ddd5bf6fa1ef4",
"reference": "9f8a6077dd22b3b253583b1be84ddd5bf6fa1ef4",
"shasum": ""
},
"require": {
"laminas/laminas-eventmanager": "^3.5",
"laminas/laminas-servicemanager": "^3.15.1",
"laminas/laminas-stdlib": "^3.10.1",
"php": "^7.4 || ~8.0.0 || ~8.1.0"
},
"conflict": {
"zendframework/zend-session": "*"
},
"require-dev": {
"laminas/laminas-cache": "^3.1.3",
"laminas/laminas-cache-storage-adapter-memory": "^2.0.0",
"laminas/laminas-coding-standard": "~2.3.0",
"laminas/laminas-db": "^2.13.4",
"laminas/laminas-http": "^2.15",
"laminas/laminas-validator": "^2.15",
"mongodb/mongodb": "~1.12.0",
"php-mock/php-mock-phpunit": "^1.1.2 || ^2.0",
"phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.5.9",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.24.0"
},
"suggest": {
"laminas/laminas-cache": "Laminas\\Cache component",
"laminas/laminas-db": "Laminas\\Db component",
"laminas/laminas-http": "Laminas\\Http component",
"laminas/laminas-servicemanager": "Laminas\\ServiceManager component",
"laminas/laminas-validator": "Laminas\\Validator component",
"mongodb/mongodb": "If you want to use the MongoDB session save handler"
},
"type": "library",
"extra": {
"laminas": {
"component": "Laminas\\Session",
"config-provider": "Laminas\\Session\\ConfigProvider"
}
},
"autoload": {
"psr-4": {
"Laminas\\Session\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Object-oriented interface to PHP sessions and storage",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"session"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-session/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-session/issues",
"rss": "https://github.com/laminas/laminas-session/releases.atom",
"source": "https://github.com/laminas/laminas-session"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-07-22T10:26:33+00:00"
},
{
"name": "laminas/laminas-uri",
"version": "2.10.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-uri.git",
"reference": "663b050294945c7345cc3a61f3ca661d5f9e1f80"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-uri/zipball/663b050294945c7345cc3a61f3ca661d5f9e1f80",
"reference": "663b050294945c7345cc3a61f3ca661d5f9e1f80",
"shasum": ""
},
"require": {
"laminas/laminas-escaper": "^2.9",
"laminas/laminas-validator": "^2.15",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-uri": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"phpunit/phpunit": "^9.5.25"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Uri\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "A component that aids in manipulating and validating » Uniform Resource Identifiers (URIs)",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"uri"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-uri/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-uri/issues",
"rss": "https://github.com/laminas/laminas-uri/releases.atom",
"source": "https://github.com/laminas/laminas-uri"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-16T15:02:45+00:00"
},
{
"name": "myclabs/deep-copy",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"conflict": {
"doctrine/collections": "<1.6.8",
"doctrine/common": "<2.13.3 || >=3,<3.2.2"
},
"require-dev": {
"doctrine/collections": "^1.6.8",
"doctrine/common": "^2.13.3 || ^3.2.2",
"phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
},
"type": "library",
"autoload": {
"files": [
"src/DeepCopy/deep_copy.php"
],
"psr-4": {
"DeepCopy\\": "src/DeepCopy/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Create deep copies (clones) of your objects",
"keywords": [
"clone",
"copy",
"duplicate",
"object",
"object graph"
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
},
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
"type": "tidelift"
}
],
"time": "2022-03-03T13:19:32+00:00"
},
{
"name": "netresearch/jsonmapper",
"version": "v4.0.0",
"source": {
"type": "git",
"url": "https://github.com/cweiske/jsonmapper.git",
"reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
"reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-pcre": "*",
"ext-reflection": "*",
"ext-spl": "*",
"php": ">=7.1"
},
"require-dev": {
"phpunit/phpunit": "~7.5 || ~8.0 || ~9.0",
"squizlabs/php_codesniffer": "~3.5"
},
"type": "library",
"autoload": {
"psr-0": {
"JsonMapper": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"OSL-3.0"
],
"authors": [
{
"name": "Christian Weiske",
"email": "cweiske@cweiske.de",
"homepage": "http://github.com/cweiske/jsonmapper/",
"role": "Developer"
}
],
"description": "Map nested JSON structures onto PHP classes",
"support": {
"email": "cweiske@cweiske.de",
"issues": "https://github.com/cweiske/jsonmapper/issues",
"source": "https://github.com/cweiske/jsonmapper/tree/v4.0.0"
},
"time": "2020-12-01T19:48:11+00:00"
},
{
"name": "nikic/php-parser",
"version": "v4.15.2",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
"reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=7.0"
},
"require-dev": {
"ircmaxell/php-yacc": "^0.0.7",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
},
"bin": [
"bin/php-parse"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.9-dev"
}
},
"autoload": {
"psr-4": {
"PhpParser\\": "lib/PhpParser"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov"
}
],
"description": "A PHP parser written in PHP",
"keywords": [
"parser",
"php"
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.2"
},
"time": "2022-11-12T15:38:23+00:00"
},
{
"name": "openlss/lib-array2xml",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/nullivex/lib-array2xml.git",
"reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90",
"reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"type": "library",
"autoload": {
"psr-0": {
"LSS": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Bryan Tong",
"email": "bryan@nullivex.com",
"homepage": "https://www.nullivex.com"
},
{
"name": "Tony Butler",
"email": "spudz76@gmail.com",
"homepage": "https://www.nullivex.com"
}
],
"description": "Array2XML conversion library credit to lalit.org",
"homepage": "https://www.nullivex.com",
"keywords": [
"array",
"array conversion",
"xml",
"xml conversion"
],
"support": {
"issues": "https://github.com/nullivex/lib-array2xml/issues",
"source": "https://github.com/nullivex/lib-array2xml/tree/master"
},
"time": "2019-03-29T20:06:56+00:00"
},
{
"name": "phar-io/manifest",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-phar": "*",
"ext-xmlwriter": "*",
"phar-io/version": "^3.0.1",
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
"support": {
"issues": "https://github.com/phar-io/manifest/issues",
"source": "https://github.com/phar-io/manifest/tree/2.0.3"
},
"time": "2021-07-20T11:28:43+00:00"
},
{
"name": "phar-io/version",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/phar-io/version.git",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Library for handling version information and constraints",
"support": {
"issues": "https://github.com/phar-io/version/issues",
"source": "https://github.com/phar-io/version/tree/3.2.1"
},
"time": "2022-02-21T01:04:05+00:00"
},
{
"name": "phpdocumentor/reflection-common",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-2.x": "2.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jaap van Otterdijk",
"email": "opensource@ijaap.nl"
}
],
"description": "Common reflection classes used by phpdocumentor to reflect the code structure",
"homepage": "http://www.phpdoc.org",
"keywords": [
"FQSEN",
"phpDocumentor",
"phpdoc",
"reflection",
"static analysis"
],
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
"source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x"
},
"time": "2020-06-27T09:03:43+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "5.3.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "622548b623e81ca6d78b721c5e029f4ce664f170"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170",
"reference": "622548b623e81ca6d78b721c5e029f4ce664f170",
"shasum": ""
},
"require": {
"ext-filter": "*",
"php": "^7.2 || ^8.0",
"phpdocumentor/reflection-common": "^2.2",
"phpdocumentor/type-resolver": "^1.3",
"webmozart/assert": "^1.9.1"
},
"require-dev": {
"mockery/mockery": "~1.3.2",
"psalm/phar": "^4.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
},
{
"name": "Jaap van Otterdijk",
"email": "account@ijaap.nl"
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0"
},
"time": "2021-10-19T17:43:47+00:00"
},
{
"name": "phpdocumentor/type-resolver",
"version": "1.6.2",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/48f445a408c131e38cab1c235aa6d2bb7a0bb20d",
"reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0",
"phpdocumentor/reflection-common": "^2.0"
},
"require-dev": {
"ext-tokenizer": "*",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpunit/phpunit": "^9.5",
"rector/rector": "^0.13.9",
"vimeo/psalm": "^4.25"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-1.x": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
}
],
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"support": {
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.2"
},
"time": "2022-10-14T12:47:21+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "981cc368a216c988e862a75e526b6076987d1b50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/981cc368a216c988e862a75e526b6076987d1b50",
"reference": "981cc368a216c988e862a75e526b6076987d1b50",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.5.1"
},
"time": "2022-05-05T11:32:40+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.18",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/12fddc491826940cf9b7e88ad9664cf51f0f6d0a",
"reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
"nikic/php-parser": "^4.14",
"php": ">=7.3",
"phpunit/php-file-iterator": "^3.0.3",
"phpunit/php-text-template": "^2.0.2",
"sebastian/code-unit-reverse-lookup": "^2.0.2",
"sebastian/complexity": "^2.0",
"sebastian/environment": "^5.1.2",
"sebastian/lines-of-code": "^1.0.3",
"sebastian/version": "^3.0.1",
"theseer/tokenizer": "^1.2.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcov": "*",
"ext-xdebug": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.18"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-10-27T13:35:33+00:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "3.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2021-12-02T12:48:52+00:00"
},
{
"name": "phpunit/php-invoker",
"version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-invoker.git",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"ext-pcntl": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcntl": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Invoke callables with a timeout",
"homepage": "https://github.com/sebastianbergmann/php-invoker/",
"keywords": [
"process"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-invoker/issues",
"source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:58:55+00:00"
},
{
"name": "phpunit/php-text-template",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
"source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T05:33:50+00:00"
},
{
"name": "phpunit/php-timer",
"version": "5.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-timer/issues",
"source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:16:10+00:00"
},
{
"name": "phpunit/phpunit",
"version": "9.5.26",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/851867efcbb6a1b992ec515c71cdcf20d895e9d2",
"reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.3.1",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
"myclabs/deep-copy": "^1.10.1",
"phar-io/manifest": "^2.0.3",
"phar-io/version": "^3.0.2",
"php": ">=7.3",
"phpunit/php-code-coverage": "^9.2.13",
"phpunit/php-file-iterator": "^3.0.5",
"phpunit/php-invoker": "^3.1.1",
"phpunit/php-text-template": "^2.0.3",
"phpunit/php-timer": "^5.0.2",
"sebastian/cli-parser": "^1.0.1",
"sebastian/code-unit": "^1.0.6",
"sebastian/comparator": "^4.0.8",
"sebastian/diff": "^4.0.3",
"sebastian/environment": "^5.1.3",
"sebastian/exporter": "^4.0.5",
"sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3",
"sebastian/type": "^3.2",
"sebastian/version": "^3.0.2"
},
"suggest": {
"ext-soap": "*",
"ext-xdebug": "*"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.5-dev"
}
},
"autoload": {
"files": [
"src/Framework/Assert/Functions.php"
],
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.26"
},
"funding": [
{
"url": "https://phpunit.de/sponsors.html",
"type": "custom"
},
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
"type": "tidelift"
}
],
"time": "2022-10-28T06:00:21+00:00"
},
{
"name": "psalm/plugin-phpunit",
"version": "0.18.3",
"source": {
"type": "git",
"url": "https://github.com/psalm/psalm-plugin-phpunit.git",
"reference": "057c1cdf7546c1e427f6fd83b635d0cc18c252bf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/psalm/psalm-plugin-phpunit/zipball/057c1cdf7546c1e427f6fd83b635d0cc18c252bf",
"reference": "057c1cdf7546c1e427f6fd83b635d0cc18c252bf",
"shasum": ""
},
"require": {
"composer/package-versions-deprecated": "^1.10",
"composer/semver": "^1.4 || ^2.0 || ^3.0",
"ext-simplexml": "*",
"php": "^7.1 || ^8.0",
"vimeo/psalm": "dev-master || dev-4.x || ^4.5 || ^5@beta"
},
"conflict": {
"phpunit/phpunit": "<7.5"
},
"require-dev": {
"codeception/codeception": "^4.0.3",
"php": "^7.3 || ^8.0",
"phpunit/phpunit": "^7.5 || ^8.0 || ^9.0",
"squizlabs/php_codesniffer": "^3.3.1",
"weirdan/codeception-psalm-module": "^0.11.0",
"weirdan/prophecy-shim": "^1.0 || ^2.0"
},
"type": "psalm-plugin",
"extra": {
"psalm": {
"pluginClass": "Psalm\\PhpUnitPlugin\\Plugin"
}
},
"autoload": {
"psr-4": {
"Psalm\\PhpUnitPlugin\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Matt Brown",
"email": "github@muglug.com"
}
],
"description": "Psalm plugin for PHPUnit",
"support": {
"issues": "https://github.com/psalm/psalm-plugin-phpunit/issues",
"source": "https://github.com/psalm/psalm-plugin-phpunit/tree/0.18.3"
},
"time": "2022-11-03T18:17:28+00:00"
},
{
"name": "psr/http-client",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
"shasum": ""
},
"require": {
"php": "^7.0 || ^8.0",
"psr/http-message": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP clients",
"homepage": "https://github.com/php-fig/http-client",
"keywords": [
"http",
"http-client",
"psr",
"psr-18"
],
"support": {
"source": "https://github.com/php-fig/http-client/tree/master"
},
"time": "2020-06-29T06:28:15+00:00"
},
{
"name": "psr/http-factory",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-factory.git",
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
"shasum": ""
},
"require": {
"php": ">=7.0.0",
"psr/http-message": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interfaces for PSR-7 HTTP message factories",
"keywords": [
"factory",
"http",
"message",
"psr",
"psr-17",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-factory/tree/master"
},
"time": "2019-04-30T12:38:16+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-message/tree/master"
},
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "psr/log",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"support": {
"source": "https://github.com/php-fig/log/tree/3.0.0"
},
"time": "2021-07-14T16:46:02+00:00"
},
{
"name": "sebastian/cli-parser",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for parsing CLI options",
"homepage": "https://github.com/sebastianbergmann/cli-parser",
"support": {
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
"source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:08:49+00:00"
},
{
"name": "sebastian/code-unit",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit.git",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the PHP code units",
"homepage": "https://github.com/sebastianbergmann/code-unit",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit/issues",
"source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:08:54+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
"source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:30:19+00:00"
},
{
"name": "sebastian/comparator",
"version": "4.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/diff": "^4.0",
"sebastian/exporter": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "https://github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
"source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T12:41:17+00:00"
},
{
"name": "sebastian/complexity",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.7",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for calculating the complexity of PHP code units",
"homepage": "https://github.com/sebastianbergmann/complexity",
"support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues",
"source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T15:52:27+00:00"
},
{
"name": "sebastian/diff",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3",
"symfony/process": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
}
],
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
"diff",
"udiff",
"unidiff",
"unified diff"
],
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:10:38+00:00"
},
{
"name": "sebastian/environment",
"version": "5.1.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-posix": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"support": {
"issues": "https://github.com/sebastianbergmann/environment/issues",
"source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-04-03T09:37:03+00:00"
},
{
"name": "sebastian/exporter",
"version": "4.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-mbstring": "*",
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "https://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T06:03:37+00:00"
},
{
"name": "sebastian/global-state",
"version": "5.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-dom": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-uopz": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-02-14T08:28:10+00:00"
},
{
"name": "sebastian/lines-of-code",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.6",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for counting the lines of code in PHP source code",
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
"support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-11-28T06:42:11+00:00"
},
{
"name": "sebastian/object-enumerator",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
"source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:12:34+00:00"
},
{
"name": "sebastian/object-reflector",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Allows reflection of object attributes, including inherited and non-public ones",
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-reflector/issues",
"source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:14:26+00:00"
},
{
"name": "sebastian/recursion-context",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
"source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:17:30+00:00"
},
{
"name": "sebastian/resource-operations",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"support": {
"issues": "https://github.com/sebastianbergmann/resource-operations/issues",
"source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:45:17+00:00"
},
{
"name": "sebastian/type",
"version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the types of the PHP type system",
"homepage": "https://github.com/sebastianbergmann/type",
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
"source": "https://github.com/sebastianbergmann/type/tree/3.2.0"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-12T14:47:03+00:00"
},
{
"name": "sebastian/version",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "c6c1022351a901512170118436c764e473f6de8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
"reference": "c6c1022351a901512170118436c764e473f6de8c",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"support": {
"issues": "https://github.com/sebastianbergmann/version/issues",
"source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:39:44+00:00"
},
{
"name": "slevomat/coding-standard",
"version": "7.2.1",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
"php": "^7.2 || ^8.0",
"phpstan/phpdoc-parser": "^1.5.1",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phing/phing": "2.17.3",
"php-parallel-lint/php-parallel-lint": "1.3.2",
"phpstan/phpstan": "1.4.10|1.7.1",
"phpstan/phpstan-deprecation-rules": "1.0.0",
"phpstan/phpstan-phpunit": "1.0.0|1.1.1",
"phpstan/phpstan-strict-rules": "1.2.3",
"phpunit/phpunit": "7.5.20|8.5.21|9.5.20"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "7.x-dev"
}
},
"autoload": {
"psr-4": {
"SlevomatCodingStandard\\": "SlevomatCodingStandard"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
"source": "https://github.com/slevomat/coding-standard/tree/7.2.1"
},
"funding": [
{
"url": "https://github.com/kukulich",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
"type": "tidelift"
}
],
"time": "2022-05-25T10:58:12+00:00"
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.7.1",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"bin/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2022-06-18T07:21:10+00:00"
},
{
"name": "symfony/console",
"version": "v6.0.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "b0b910724a0a0326b4481e4f8a30abb2dd442efb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/b0b910724a0a0326b4481e4f8a30abb2dd442efb",
"reference": "b0b910724a0a0326b4481e4f8a30abb2dd442efb",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^1.1|^2|^3",
"symfony/string": "^5.4|^6.0"
},
"conflict": {
"symfony/dependency-injection": "<5.4",
"symfony/dotenv": "<5.4",
"symfony/event-dispatcher": "<5.4",
"symfony/lock": "<5.4",
"symfony/process": "<5.4"
},
"provide": {
"psr/log-implementation": "1.0|2.0|3.0"
},
"require-dev": {
"psr/log": "^1|^2|^3",
"symfony/config": "^5.4|^6.0",
"symfony/dependency-injection": "^5.4|^6.0",
"symfony/event-dispatcher": "^5.4|^6.0",
"symfony/lock": "^5.4|^6.0",
"symfony/process": "^5.4|^6.0",
"symfony/var-dumper": "^5.4|^6.0"
},
"suggest": {
"psr/log": "For using the console logger",
"symfony/event-dispatcher": "",
"symfony/lock": "",
"symfony/process": ""
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Eases the creation of beautiful and testable command line interfaces",
"homepage": "https://symfony.com",
"keywords": [
"cli",
"command line",
"console",
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v6.0.15"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-10-26T21:42:20+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.0.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c",
"reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c",
"shasum": ""
},
"require": {
"php": ">=8.0.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.0-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-01-02T09:55:41+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-ctype": "*"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Grapheme\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's grapheme_* functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"grapheme",
"intl",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's Normalizer class and related functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"intl",
"normalizer",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-mbstring": "*"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php80\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ion Bazan",
"email": "ion.bazan@gmail.com"
},
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/service-contracts",
"version": "v2.5.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
"reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1",
"symfony/deprecation-contracts": "^2.1|^3"
},
"conflict": {
"ext-psr": "<1.1|>=2"
},
"suggest": {
"symfony/service-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\Service\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to writing services",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v2.5.2"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-30T19:17:29+00:00"
},
{
"name": "symfony/string",
"version": "v6.0.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "51ac0fa0ccf132a00519b87c97e8f775fa14e771"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/51ac0fa0ccf132a00519b87c97e8f775fa14e771",
"reference": "51ac0fa0ccf132a00519b87c97e8f775fa14e771",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
"symfony/translation-contracts": "<2.0"
},
"require-dev": {
"symfony/error-handler": "^5.4|^6.0",
"symfony/http-client": "^5.4|^6.0",
"symfony/translation-contracts": "^2.0|^3.0",
"symfony/var-exporter": "^5.4|^6.0"
},
"type": "library",
"autoload": {
"files": [
"Resources/functions.php"
],
"psr-4": {
"Symfony\\Component\\String\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
"homepage": "https://symfony.com",
"keywords": [
"grapheme",
"i18n",
"string",
"unicode",
"utf-8",
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v6.0.15"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-10-10T09:34:08+00:00"
},
{
"name": "theseer/tokenizer",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
}
],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/1.2.1"
},
"funding": [
{
"url": "https://github.com/theseer",
"type": "github"
}
],
"time": "2021-07-28T10:34:58+00:00"
},
{
"name": "vimeo/psalm",
"version": "4.30.0",
"source": {
"type": "git",
"url": "https://github.com/vimeo/psalm.git",
"reference": "d0bc6e25d89f649e4f36a534f330f8bb4643dd69"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/vimeo/psalm/zipball/d0bc6e25d89f649e4f36a534f330f8bb4643dd69",
"reference": "d0bc6e25d89f649e4f36a534f330f8bb4643dd69",
"shasum": ""
},
"require": {
"amphp/amp": "^2.4.2",
"amphp/byte-stream": "^1.5",
"composer/package-versions-deprecated": "^1.8.0",
"composer/semver": "^1.4 || ^2.0 || ^3.0",
"composer/xdebug-handler": "^1.1 || ^2.0 || ^3.0",
"dnoegel/php-xdg-base-dir": "^0.1.1",
"ext-ctype": "*",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-simplexml": "*",
"ext-tokenizer": "*",
"felixfbecker/advanced-json-rpc": "^3.0.3",
"felixfbecker/language-server-protocol": "^1.5",
"netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0",
"nikic/php-parser": "^4.13",
"openlss/lib-array2xml": "^1.0",
"php": "^7.1|^8",
"sebastian/diff": "^3.0 || ^4.0",
"symfony/console": "^3.4.17 || ^4.1.6 || ^5.0 || ^6.0",
"symfony/polyfill-php80": "^1.25",
"webmozart/path-util": "^2.3"
},
"provide": {
"psalm/psalm": "self.version"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.2",
"brianium/paratest": "^4.0||^6.0",
"ext-curl": "*",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpdocumentor/reflection-docblock": "^5",
"phpmyadmin/sql-parser": "5.1.0||dev-master",
"phpspec/prophecy": ">=1.9.0",
"phpstan/phpdoc-parser": "1.2.* || 1.6.4",
"phpunit/phpunit": "^9.0",
"psalm/plugin-phpunit": "^0.16",
"slevomat/coding-standard": "^7.0",
"squizlabs/php_codesniffer": "^3.5",
"symfony/process": "^4.3 || ^5.0 || ^6.0",
"weirdan/prophecy-shim": "^1.0 || ^2.0"
},
"suggest": {
"ext-curl": "In order to send data to shepherd",
"ext-igbinary": "^2.0.5 is required, used to serialize caching data"
},
"bin": [
"psalm",
"psalm-language-server",
"psalm-plugin",
"psalm-refactor",
"psalter"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.x-dev",
"dev-3.x": "3.x-dev",
"dev-2.x": "2.x-dev",
"dev-1.x": "1.x-dev"
}
},
"autoload": {
"files": [
"src/functions.php",
"src/spl_object_id.php"
],
"psr-4": {
"Psalm\\": "src/Psalm/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Matthew Brown"
}
],
"description": "A static analysis tool for finding errors in PHP applications",
"keywords": [
"code",
"inspection",
"php"
],
"support": {
"issues": "https://github.com/vimeo/psalm/issues",
"source": "https://github.com/vimeo/psalm/tree/4.30.0"
},
"time": "2022-11-06T20:37:08+00:00"
},
{
"name": "webimpress/coding-standard",
"version": "1.2.4",
"source": {
"type": "git",
"url": "https://github.com/webimpress/coding-standard.git",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webimpress/coding-standard/zipball/cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"shasum": ""
},
"require": {
"php": "^7.3 || ^8.0",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phpunit/phpunit": "^9.5.13"
},
"type": "phpcodesniffer-standard",
"extra": {
"dev-master": "1.2.x-dev",
"dev-develop": "1.3.x-dev"
},
"autoload": {
"psr-4": {
"WebimpressCodingStandard\\": "src/WebimpressCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-2-Clause"
],
"description": "Webimpress Coding Standard",
"keywords": [
"Coding Standard",
"PSR-2",
"phpcs",
"psr-12",
"webimpress"
],
"support": {
"issues": "https://github.com/webimpress/coding-standard/issues",
"source": "https://github.com/webimpress/coding-standard/tree/1.2.4"
},
"funding": [
{
"url": "https://github.com/michalbundyra",
"type": "github"
}
],
"time": "2022-02-15T19:52:12+00:00"
},
{
"name": "webmozart/assert",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/webmozarts/assert.git",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"php": "^7.2 || ^8.0"
},
"conflict": {
"phpstan/phpstan": "<0.12.20",
"vimeo/psalm": "<4.6.1 || 4.6.2"
},
"require-dev": {
"phpunit/phpunit": "^8.5.13"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.10-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\Assert\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Assertions to validate method input/output with nice error messages.",
"keywords": [
"assert",
"check",
"validate"
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.11.0"
},
"time": "2022-06-03T18:03:27+00:00"
},
{
"name": "webmozart/path-util",
"version": "2.3.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/path-util.git",
"reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
"reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"webmozart/assert": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.6",
"sebastian/version": "^1.0.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.3-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\PathUtil\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.",
"support": {
"issues": "https://github.com/webmozart/path-util/issues",
"source": "https://github.com/webmozart/path-util/tree/2.3.0"
},
"abandoned": "symfony/filesystem",
"time": "2015-12-17T08:42:14+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"platform-dev": [],
"platform-overrides": {
"php": "8.0.99"
},
"plugin-api-version": "2.3.0"
}
laminas-validator/bin/update_hostname_validator.php 0000644 00000013032 15240152637 0016665 0 ustar 00 <?php
/**
* @see https://github.com/laminas/laminas-validator for the canonical source repository
* @copyright https://github.com/laminas/laminas-validator/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-validator/blob/master/LICENSE.md New BSD License
*/
use Laminas\Http\Client;
use Laminas\Validator\Hostname;
require __DIR__ . '/../vendor/autoload.php';
define('IANA_URL', 'https://data.iana.org/TLD/tlds-alpha-by-domain.txt');
define('LAMINAS_HOSTNAME_VALIDATOR_FILE', __DIR__.'/../src/Hostname.php');
if (! file_exists(LAMINAS_HOSTNAME_VALIDATOR_FILE) || ! is_readable(LAMINAS_HOSTNAME_VALIDATOR_FILE)) {
printf("Error: cannot read file '%s'%s", LAMINAS_HOSTNAME_VALIDATOR_FILE, PHP_EOL);
exit(1);
}
if (! is_writable(LAMINAS_HOSTNAME_VALIDATOR_FILE)) {
printf("Error: cannot update file '%s'%s", LAMINAS_HOSTNAME_VALIDATOR_FILE, PHP_EOL);
exit(1);
}
/** @psalm-var list<string> $newFileContent */
$newFileContent = []; // new file content
$insertDone = false; // becomes 'true' when we find start of $validTlds declaration
$insertFinish = false; // becomes 'true' when we find end of $validTlds declaration
$checkOnly = isset($argv[1]) ? $argv[1] === '--check-only' : false;
$response = getOfficialTLDs();
$ianaVersion = getVersionFromString('Version', strtok($response->getBody(), "\n"));
$validatorVersion = getVersionFromString('IanaVersion', file_get_contents(LAMINAS_HOSTNAME_VALIDATOR_FILE));
if ($checkOnly && $ianaVersion > $validatorVersion) {
printf(
'TLDs must be updated, please run `php bin/update_hostname_validator.php` and push your changes%s',
PHP_EOL
);
exit(1);
}
if ($checkOnly) {
printf('TLDs are up-to-date%s', PHP_EOL);
exit(0);
}
foreach (file(LAMINAS_HOSTNAME_VALIDATOR_FILE) as $line) {
// Replace old version number with new one
if (preg_match('/\*\s+IanaVersion\s+\d+/', $line, $matches)) {
$newFileContent[] = sprintf(" * IanaVersion %s\n", $ianaVersion);
continue;
}
if ($insertDone === $insertFinish) {
// Outside of $validTlds definition; keep line as-is
$newFileContent[] = $line;
}
if ($insertFinish) {
continue;
}
if ($insertDone) {
// Detect where the $validTlds declaration ends
if (preg_match('/^\s+\];\s*$/', $line)) {
$newFileContent[] = $line;
$insertFinish = true;
}
continue;
}
// Detect where the $validTlds declaration begins
if (preg_match('/^\s+protected\s+\$validTlds\s+=\s+\[\s*$/', $line)) {
$newFileContent = array_merge($newFileContent, getNewValidTlds($response->getBody()));
$insertDone = true;
}
}
if (! $insertDone) {
printf('Error: cannot find line with "protected $validTlds"%s', PHP_EOL);
exit(1);
}
if (!$insertFinish) {
printf('Error: cannot find end of $validTlds declaration%s', PHP_EOL);
exit(1);
}
if (false === @file_put_contents(LAMINAS_HOSTNAME_VALIDATOR_FILE, $newFileContent)) {
printf('Error: cannot write info file "%s"%s', LAMINAS_HOSTNAME_VALIDATOR_FILE, PHP_EOL);
exit(1);
}
printf('Validator TLD file updated.%s', PHP_EOL);
exit(0);
/**
* Get Official TLDs
*
* @return \Laminas\Http\Response
* @throws Exception
*/
function getOfficialTLDs()
{
$client = new Client();
$client->setOptions([
'adapter' => 'Laminas\Http\Client\Adapter\Curl',
]);
$client->setUri(IANA_URL);
$client->setMethod('GET');
$response = $client->send();
if (! $response->isSuccess()) {
throw new \Exception(sprintf("Error: cannot get '%s'%s", IANA_URL, PHP_EOL));
}
return $response;
}
/**
* Extract the first match of a string like
* "Version 2015072300" from the given string
*
* @param string $prefix
* @param string $string
* @return string
* @throws Exception
*/
function getVersionFromString($prefix, $string)
{
$matches = [];
if (! preg_match(sprintf('/%s\s+((\d+)?)/', $prefix), $string, $matches)) {
throw new Exception('Error: cannot get last update date');
}
return $matches[1];
}
/**
* Extract new Valid TLDs from a string containing one per line.
*
* @param string $string
* @return list<string>
*/
function getNewValidTlds($string)
{
$decodePunycode = getPunycodeDecoder();
// Get new TLDs from the list previously fetched
$newValidTlds = [];
foreach (preg_grep('/^[^#]/', preg_split("#\r?\n#", $string)) as $line) {
$newValidTlds []= sprintf(
"%s'%s',\n",
str_repeat(' ', 8),
$decodePunycode(strtolower($line))
);
}
return $newValidTlds;
}
/**
* Retrieve and return a punycode decoder.
*
* TLDs are puny encoded.
*
* We need a decodePunycode function to translate TLDs to UTF-8:
*
* - use idn_to_utf8 if available
* - otherwise, use Hostname::decodePunycode()
*
* @return callable
*/
function getPunycodeDecoder()
{
if (function_exists('idn_to_utf8')) {
return function ($domain) {
return idn_to_utf8($domain, 0, INTL_IDNA_VARIANT_UTS46);
};
}
$hostnameValidator = new Hostname();
$reflection = new ReflectionClass(get_class($hostnameValidator));
$decodePunyCode = $reflection->getMethod('decodePunycode');
$decodePunyCode->setAccessible(true);
return function ($encode) use ($hostnameValidator, $decodePunyCode) {
if (strpos($encode, 'xn--') === 0) {
return $decodePunyCode->invokeArgs($hostnameValidator, [substr($encode, 4)]);
}
return $encode;
};
}
laminas-validator/LICENSE.md 0000644 00000002732 15240152637 0011570 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of Laminas Foundation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
laminas-validator/renovate.json 0000644 00000000205 15240152637 0012673 0 ustar 00 {
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"local>laminas/.github:renovate-config"
]
}
laminas-servicemanager/src/AbstractPluginManager.php 0000644 00000017027 15240152637 0016712 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager;
use Laminas\ServiceManager\Exception\ContainerModificationsNotAllowedException;
use Laminas\ServiceManager\Exception\InvalidServiceException;
use Psr\Container\ContainerInterface;
use function class_exists;
use function gettype;
use function is_object;
use function method_exists;
use function sprintf;
use function trigger_error;
use const E_USER_DEPRECATED;
/**
* Abstract plugin manager.
*
* Abstract PluginManagerInterface implementation providing:
*
* - creation context support. The constructor accepts the parent container
* instance, which is then used when creating instances.
* - plugin validation. Implementations may define the `$instanceOf` property
* to indicate what class types constitute valid plugins, omitting the
* requirement to define the `validate()` method.
*
* The implementation extends `ServiceManager`, thus providing the same set
* of capabilities as found in that implementation.
*
* @template InstanceType
* @implements PluginManagerInterface<InstanceType>
* @psalm-import-type ServiceManagerConfiguration from ServiceManager
* @psalm-suppress PropertyNotSetInConstructor
*/
abstract class AbstractPluginManager extends ServiceManager implements PluginManagerInterface
{
/**
* Whether or not to auto-add a FQCN as an invokable if it exists.
*
* @var bool
*/
protected $autoAddInvokableClass = true;
/**
* An object type that the created instance must be instanced of
*
* @var null|string
* @psalm-var null|class-string<InstanceType>
*/
protected $instanceOf;
/**
* Sets the provided $parentLocator as the creation context for all
* factories; for $config, {@see \Laminas\ServiceManager\ServiceManager::configure()}
* for details on its accepted structure.
*
* @param null|ConfigInterface|ContainerInterface $configInstanceOrParentLocator
* @param array $config
* @psalm-param ServiceManagerConfiguration $config
*/
public function __construct($configInstanceOrParentLocator = null, array $config = [])
{
/** @psalm-suppress DocblockTypeContradiction */
if (
null !== $configInstanceOrParentLocator
&& ! $configInstanceOrParentLocator instanceof ConfigInterface
&& ! $configInstanceOrParentLocator instanceof ContainerInterface
) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a ConfigInterface or ContainerInterface instance as the first argument; received %s',
self::class,
is_object($configInstanceOrParentLocator)
? $configInstanceOrParentLocator::class
: gettype($configInstanceOrParentLocator)
));
}
if ($configInstanceOrParentLocator instanceof ConfigInterface) {
trigger_error(sprintf(
'Usage of %s as a constructor argument for %s is now deprecated',
ConfigInterface::class,
static::class
), E_USER_DEPRECATED);
$config = $configInstanceOrParentLocator->toArray();
}
parent::__construct($config);
if (! $configInstanceOrParentLocator instanceof ContainerInterface) {
trigger_error(sprintf(
'%s now expects a %s instance representing the parent container; please update your code',
__METHOD__,
ContainerInterface::class
), E_USER_DEPRECATED);
}
$this->creationContext = $configInstanceOrParentLocator instanceof ContainerInterface
? $configInstanceOrParentLocator
: $this;
}
/**
* Override configure() to validate service instances.
*
* @param array $config
* @psalm-param ServiceManagerConfiguration $config
* @return self
* @throws InvalidServiceException If an instance passed in the `services` configuration is invalid for the
* plugin manager.
* @throws ContainerModificationsNotAllowedException If the allow override flag has been toggled off, and a
* service instanceexists for a given service.
*/
public function configure(array $config)
{
if (isset($config['services'])) {
/** @psalm-suppress MixedAssignment */
foreach ($config['services'] as $service) {
$this->validate($service);
}
}
parent::configure($config);
return $this;
}
/**
* Override setService for additional plugin validation.
*
* {@inheritDoc}
*
* @param string|class-string<InstanceType> $name
* @param InstanceType $service
*/
public function setService($name, $service)
{
$this->validate($service);
parent::setService($name, $service);
}
/**
* @param class-string<InstanceType>|string $name Service name of plugin to retrieve.
* @param null|array<mixed> $options Options to use when creating the instance.
* @return mixed
* @psalm-return ($name is class-string<InstanceType> ? InstanceType : mixed)
* @throws Exception\ServiceNotFoundException If the manager does not have
* a service definition for the instance, and the service is not
* auto-invokable.
* @throws InvalidServiceException If the plugin created is invalid for the
* plugin context.
*/
public function get($name, ?array $options = null)
{
if (! $this->has($name)) {
if (! $this->autoAddInvokableClass || ! class_exists($name)) {
throw new Exception\ServiceNotFoundException(sprintf(
'A plugin by the name "%s" was not found in the plugin manager %s',
$name,
static::class
));
}
$this->setFactory($name, Factory\InvokableFactory::class);
}
$instance = ! $options ? parent::get($name) : $this->build($name, $options);
$this->validate($instance);
return $instance;
}
/**
* {@inheritDoc}
*
* @psalm-assert InstanceType $instance
*/
public function validate(mixed $instance)
{
if (method_exists($this, 'validatePlugin')) {
trigger_error(sprintf(
'%s::validatePlugin() has been deprecated as of 3.0; please define validate() instead',
static::class
), E_USER_DEPRECATED);
$this->validatePlugin($instance);
return;
}
if (empty($this->instanceOf) || $instance instanceof $this->instanceOf) {
return;
}
throw new InvalidServiceException(sprintf(
'Plugin manager "%s" expected an instance of type "%s", but "%s" was received',
self::class,
$this->instanceOf,
is_object($instance) ? $instance::class : gettype($instance)
));
}
/**
* Implemented for backwards compatibility only.
*
* Returns the creation context.
*
* @deprecated since 3.0.0. The creation context should be passed during
* instantiation instead.
*
* @return void
*/
public function setServiceLocator(ContainerInterface $container)
{
trigger_error(sprintf(
'Usage of %s is deprecated since v3.0.0; please pass the container to the constructor instead',
__METHOD__
), E_USER_DEPRECATED);
$this->creationContext = $container;
}
}
laminas-servicemanager/src/ConfigInterface.php 0000644 00000005552 15240152637 0015523 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager;
use ArrayAccess;
use Psr\Container\ContainerInterface;
/**
* @see ContainerInterface
* @see ArrayAccess
*
* @psalm-type AbstractFactoriesConfigurationType = array<
* array-key,
* (class-string<Factory\AbstractFactoryInterface>|Factory\AbstractFactoryInterface)
* >
* @psalm-type DelegatorsConfigurationType = array<
* string,
* array<
* array-key,
* (class-string<Factory\DelegatorFactoryInterface>|Factory\DelegatorFactoryInterface)
* |callable(ContainerInterface,string,callable():object,array<mixed>|null):object
* >
* >
* @psalm-type FactoriesConfigurationType = array<
* string,
* (class-string<Factory\FactoryInterface>|Factory\FactoryInterface)
* |callable(ContainerInterface,string,array<mixed>|null):object
* >
* @psalm-type InitializersConfigurationType = array<
* array-key,
* (class-string<Initializer\InitializerInterface>|Initializer\InitializerInterface)
* |callable(ContainerInterface,object):void
* >
* @psalm-type LazyServicesConfigurationType = array{
* class_map?:array<string,class-string>,
* proxies_namespace?:non-empty-string,
* proxies_target_dir?:non-empty-string,
* write_proxy_files?:bool
* }
* @psalm-type ServiceManagerConfigurationType = array{
* abstract_factories?: AbstractFactoriesConfigurationType,
* aliases?: array<string,string>,
* delegators?: DelegatorsConfigurationType,
* factories?: FactoriesConfigurationType,
* initializers?: InitializersConfigurationType,
* invokables?: array<string,string>,
* lazy_services?: LazyServicesConfigurationType,
* services?: array<string,object|array>,
* shared?:array<string,bool>
* }
*/
interface ConfigInterface
{
/**
* Configure a service manager.
*
* Implementations should pull configuration from somewhere (typically
* local properties) and pass it to a ServiceManager's withConfig() method,
* returning a new instance.
*
* @return ServiceManager
*/
public function configureServiceManager(ServiceManager $serviceManager);
/**
* Return configuration for a service manager instance as an array.
*
* Implementations MUST return an array compatible with ServiceManager::configure,
* containing one or more of the following keys:
*
* - abstract_factories
* - aliases
* - delegators
* - factories
* - initializers
* - invokables
* - lazy_services
* - services
* - shared
*
* In other words, this should return configuration that can be used to instantiate
* a service manager or plugin manager, or pass to its `withConfig()` method.
*
* @return array
* @psalm-return ServiceManagerConfigurationType
*/
public function toArray();
}
laminas-servicemanager/src/Exception/ServiceNotFoundException.php 0000644 00000000675 15240152637 0021370 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Exception;
use InvalidArgumentException as SplInvalidArgumentException;
use Psr\Container\NotFoundExceptionInterface;
/**
* This exception is thrown when the service locator do not manage to find a
* valid factory to create a service
*/
class ServiceNotFoundException extends SplInvalidArgumentException implements
ExceptionInterface,
NotFoundExceptionInterface
{
}
laminas-servicemanager/src/Exception/InvalidArgumentException.php 0000644 00000002422 15240152637 0021374 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Exception;
use InvalidArgumentException as SplInvalidArgumentException;
use Laminas\ServiceManager\AbstractFactoryInterface;
use Laminas\ServiceManager\Initializer\InitializerInterface;
use function gettype;
use function is_object;
use function sprintf;
/**
* @inheritDoc
*/
class InvalidArgumentException extends SplInvalidArgumentException implements ExceptionInterface
{
public static function fromInvalidInitializer(mixed $initializer): self
{
return new self(sprintf(
'An invalid initializer was registered. Expected a callable or an'
. ' instance of "%s"; received "%s"',
InitializerInterface::class,
is_object($initializer) ? $initializer::class : gettype($initializer)
));
}
public static function fromInvalidAbstractFactory(mixed $abstractFactory): self
{
return new self(sprintf(
'An invalid abstract factory was registered. Expected an instance of or a valid'
. ' class name resolving to an implementation of "%s", but "%s" was received.',
AbstractFactoryInterface::class,
is_object($abstractFactory) ? $abstractFactory::class : gettype($abstractFactory)
));
}
}
laminas-servicemanager/src/Exception/ServiceNotCreatedException.php 0000644 00000000542 15240152637 0021655 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Exception;
use RuntimeException as SplRuntimeException;
/**
* This exception is thrown when the service locator do not manage to create
* the service (factory that has an error...)
*/
class ServiceNotCreatedException extends SplRuntimeException implements
ExceptionInterface
{
}
laminas-servicemanager/src/Exception/CyclicAliasException.php 0000644 00000010205 15240152637 0020461 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Exception;
use function array_filter;
use function array_keys;
use function array_map;
use function array_values;
use function implode;
use function reset;
use function serialize;
use function sort;
use function sprintf;
class CyclicAliasException extends InvalidArgumentException
{
/**
* @param string $alias conflicting alias key
* @param string[] $aliases map of referenced services, indexed by alias name (string)
*/
public static function fromCyclicAlias(string $alias, array $aliases): self
{
$cycle = $alias;
$cursor = $alias;
while (isset($aliases[$cursor]) && $aliases[$cursor] !== $alias) {
$cursor = $aliases[$cursor];
$cycle .= ' -> ' . $cursor;
}
$cycle .= ' -> ' . $alias . "\n";
return new self(sprintf(
"A cycle was detected within the aliases definitions:\n%s",
$cycle
));
}
/**
* @param string[] $aliases map of referenced services, indexed by alias name (string)
* @return self
*/
public static function fromAliasesMap(array $aliases)
{
$detectedCycles = array_filter(array_map(
static fn($alias): ?array => self::getCycleFor($aliases, $alias),
array_keys($aliases)
));
if (! $detectedCycles) {
return new self(sprintf(
"A cycle was detected within the following aliases map:\n\n%s",
self::printReferencesMap($aliases)
));
}
return new self(sprintf(
"Cycles were detected within the provided aliases:\n\n%s\n\n"
. "The cycle was detected in the following alias map:\n\n%s",
self::printCycles(self::deDuplicateDetectedCycles($detectedCycles)),
self::printReferencesMap($aliases)
));
}
/**
* Retrieves the cycle detected for the given $alias, or `null` if no cycle was detected
*
* @param string[] $aliases
* @param string $alias
* @return array|null
*/
private static function getCycleFor(array $aliases, $alias)
{
$cycleCandidate = [];
$targetName = $alias;
while (isset($aliases[$targetName])) {
if (isset($cycleCandidate[$targetName])) {
return $cycleCandidate;
}
$cycleCandidate[$targetName] = true;
$targetName = $aliases[$targetName];
}
return null;
}
/**
* @param string[] $aliases
* @return string
*/
private static function printReferencesMap(array $aliases)
{
$map = [];
foreach ($aliases as $alias => $reference) {
$map[] = '"' . $alias . '" => "' . $reference . '"';
}
return "[\n" . implode("\n", $map) . "\n]";
}
/**
* @param string[][] $detectedCycles
* @return string
*/
private static function printCycles(array $detectedCycles)
{
return "[\n" . implode("\n", array_map([self::class, 'printCycle'], $detectedCycles)) . "\n]";
}
/**
* @param string[] $detectedCycle
* @return string
* @phpcsSuppress SlevomatCodingStandard.Classes.UnusedPrivateElements.UnusedMethod
*/
private static function printCycle(array $detectedCycle)
{
$fullCycle = array_keys($detectedCycle);
$fullCycle[] = reset($fullCycle);
return implode(
' => ',
array_map(
static fn($cycle): string => '"' . $cycle . '"',
$fullCycle
)
);
}
/**
* @param bool[][] $detectedCycles
* @return bool[][] de-duplicated
*/
private static function deDuplicateDetectedCycles(array $detectedCycles)
{
$detectedCyclesByHash = [];
foreach ($detectedCycles as $detectedCycle) {
$cycleAliases = array_keys($detectedCycle);
sort($cycleAliases);
$hash = serialize($cycleAliases);
$detectedCyclesByHash[$hash] ??= $detectedCycle;
}
return array_values($detectedCyclesByHash);
}
}
laminas-servicemanager/src/Exception/ExceptionInterface.php 0000644 00000000410 15240152637 0020176 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Exception;
use Psr\Container\ContainerExceptionInterface;
/**
* Base exception for all Laminas\ServiceManager exceptions.
*/
interface ExceptionInterface extends ContainerExceptionInterface
{
}
laminas-servicemanager/src/Exception/ContainerModificationsNotAllowedException.php 0000644 00000001215 15240152637 0024726 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Exception;
use DomainException;
use function sprintf;
class ContainerModificationsNotAllowedException extends DomainException implements ExceptionInterface
{
/**
* @param string $service Name of service that already exists.
*/
public static function fromExistingService(string $service): self
{
return new self(sprintf(
'The container does not allow replacing or updating a service'
. ' with existing instances; the following service'
. ' already exists in the container: %s',
$service
));
}
}
laminas-servicemanager/src/Exception/InvalidServiceException.php 0000644 00000000531 15240152637 0021211 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Exception;
use RuntimeException as SplRuntimeException;
/**
* This exception is thrown by plugin managers when the created object does not match
* the plugin manager's conditions
*/
class InvalidServiceException extends SplRuntimeException implements ExceptionInterface
{
}
laminas-servicemanager/src/Proxy/LazyServiceFactory.php 0000644 00000003342 15240152637 0017401 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Proxy;
use Laminas\ServiceManager\Exception;
use Laminas\ServiceManager\Factory\DelegatorFactoryInterface;
use ProxyManager\Factory\LazyLoadingValueHolderFactory;
use ProxyManager\Proxy\LazyLoadingInterface;
use ProxyManager\Proxy\VirtualProxyInterface;
use Psr\Container\ContainerInterface;
use function sprintf;
/**
* Delegator factory responsible of instantiating lazy loading value holder proxies of
* given services at runtime
*
* @link https://github.com/Ocramius/ProxyManager/blob/master/docs/lazy-loading-value-holder.md
*/
final class LazyServiceFactory implements DelegatorFactoryInterface
{
/**
* @param array<string, class-string> $servicesMap A map of service names to
* class names of their respective classes
*/
public function __construct(private LazyLoadingValueHolderFactory $proxyFactory, private array $servicesMap)
{
}
/**
* {@inheritDoc}
*
* @param string $name
* @return VirtualProxyInterface
*/
public function __invoke(ContainerInterface $container, $name, callable $callback, ?array $options = null)
{
if (isset($this->servicesMap[$name])) {
$initializer = static function (&$wrappedInstance, LazyLoadingInterface $proxy) use ($callback): bool {
$proxy->setProxyInitializer(null);
$wrappedInstance = $callback();
return true;
};
return $this->proxyFactory->createProxy($this->servicesMap[$name], $initializer);
}
throw new Exception\ServiceNotFoundException(
sprintf('The requested service "%s" was not found in the provided services map', $name)
);
}
}
laminas-servicemanager/src/Factory/InvokableFactory.php 0000644 00000001367 15240152637 0017346 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Factory;
use Psr\Container\ContainerInterface;
/**
* Factory for instantiating classes with no dependencies or which accept a single array.
*
* The InvokableFactory can be used for any class that:
*
* - has no constructor arguments;
* - accepts a single array of arguments via the constructor.
*
* It replaces the "invokables" and "invokable class" functionality of the v2
* service manager.
*/
final class InvokableFactory implements FactoryInterface
{
/** {@inheritDoc} */
public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null)
{
return null === $options ? new $requestedName() : new $requestedName($options);
}
}
laminas-servicemanager/src/Factory/AbstractFactoryInterface.php 0000644 00000001603 15240152637 0021011 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Factory;
use Psr\Container\ContainerInterface;
/**
* Interface for an abstract factory.
*
* An abstract factory extends the factory interface, but also has an
* additional "canCreate" method, which is called to check if the abstract
* factory has the ability to create an instance for the given service. You
* should limit the number of abstract factories to ensure good performance.
* Starting from ServiceManager v3, remember that you can also attach multiple
* names to the same factory, which reduces the need for abstract factories.
*/
interface AbstractFactoryInterface extends FactoryInterface
{
/**
* Can the factory create an instance for the service?
*
* @param string $requestedName
* @return bool
*/
public function canCreate(ContainerInterface $container, $requestedName);
}
laminas-servicemanager/src/Factory/DelegatorFactoryInterface.php 0000644 00000002311 15240152637 0021151 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Factory;
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
/**
* Delegator factory interface.
*
* Defines the capabilities required by a delegator factory. Delegator
* factories are used to either decorate a service instance, or to allow
* decorating the instantiation of a service instance (for instance, to
* provide optional dependencies via setters, etc.).
*/
interface DelegatorFactoryInterface
{
/**
* A factory that creates delegates of a given service
*
* @param string $name
* @psalm-param callable():mixed $callback
* @param null|array $options
* @return object
* @throws ServiceNotFoundException If unable to resolve the service.
* @throws ServiceNotCreatedException If an exception is raised when creating a service.
* @throws ContainerExceptionInterface If any other error occurs.
*/
public function __invoke(ContainerInterface $container, $name, callable $callback, ?array $options = null);
}
laminas-servicemanager/src/Factory/FactoryInterface.php 0000644 00000002134 15240152637 0017325 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Factory;
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
/**
* Interface for a factory
*
* A factory is an callable object that is able to create an object. It is
* given the instance of the service locator, the requested name of the class
* you want to create, and any additional options that could be used to
* configure the instance state.
*/
interface FactoryInterface
{
/**
* Create an object
*
* @param string $requestedName
* @param null|array<mixed> $options
* @return object
* @throws ServiceNotFoundException If unable to resolve the service.
* @throws ServiceNotCreatedException If an exception is raised when creating a service.
* @throws ContainerExceptionInterface If any other error occurs.
*/
public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null);
}
laminas-servicemanager/src/autoload.php 0000644 00000001640 15240152637 0014277 0 ustar 00 <?php // phpcs:disable WebimpressCodingStandard.PHP.CorrectClassNameCase.Invalid
declare(strict_types=1);
use Interop\Container\Containerinterface as InteropContainerInterface;
use Interop\Container\Exception\ContainerException as InteropContainerException;
use Interop\Container\Exception\NotFoundException as InteropNotFoundException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
if (! interface_exists(InteropContainerInterface::class, false)) {
class_alias(ContainerInterface::class, InteropContainerInterface::class);
}
if (! interface_exists(InteropContainerException::class, false)) {
class_alias(ContainerExceptionInterface::class, InteropContainerException::class);
}
if (! interface_exists(InteropNotFoundException::class, false)) {
class_alias(NotFoundExceptionInterface::class, InteropNotFoundException::class);
}
laminas-servicemanager/src/Tool/FactoryCreatorCommand.php 0000644 00000007651 15240152637 0017642 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Tool;
use Laminas\ServiceManager\Exception;
use Laminas\Stdlib\ConsoleHelper;
use function array_shift;
use function assert;
use function class_exists;
use function in_array;
use function is_string;
use function sprintf;
use const STDERR;
use const STDOUT;
/**
* @psalm-type ArgumentObject = object{command:string, class:null|string, message:null|string}
*/
class FactoryCreatorCommand
{
public const COMMAND_DUMP = 'dump';
public const COMMAND_ERROR = 'error';
public const COMMAND_HELP = 'help';
public const DEFAULT_SCRIPT_NAME = self::class;
public const HELP_TEMPLATE = <<<EOH
<info>Usage:</info>
%s [-h|--help|help] <className>
<info>Arguments:</info>
<info>-h|--help|help</info> This usage message
<info><className></info> Name of the class to reflect and for which to generate
a factory.
Generates to STDOUT a factory for creating the specified class; this may then
be added to your application, and configured as a factory for the class.
EOH;
private ConsoleHelper $helper;
/**
* @param string $scriptName
*/
public function __construct(private $scriptName = self::DEFAULT_SCRIPT_NAME, ?ConsoleHelper $helper = null)
{
$this->helper = $helper ?: new ConsoleHelper();
}
/**
* @param array $args Argument list, minus script name
* @return int Exit status
*/
public function __invoke(array $args)
{
$arguments = $this->parseArgs($args);
switch ($arguments->command) {
case self::COMMAND_HELP:
$this->help();
return 0;
case self::COMMAND_ERROR:
assert(is_string($arguments->message));
$this->helper->writeErrorMessage($arguments->message);
$this->help(STDERR);
return 1;
case self::COMMAND_DUMP:
// fall-through
default:
break;
}
$generator = new FactoryCreator();
assert(is_string($arguments->class));
try {
$factory = $generator->createFactory($arguments->class);
} catch (Exception\InvalidArgumentException $e) {
$this->helper->writeErrorMessage(sprintf(
'Unable to create factory for "%s": %s',
$arguments->class,
$e->getMessage()
));
$this->help(STDERR);
return 1;
}
$this->helper->write($factory, false);
return 0;
}
/**
* @return ArgumentObject
*/
private function parseArgs(array $args)
{
if (! $args) {
return $this->createArguments(self::COMMAND_HELP);
}
$arg1 = array_shift($args);
if (in_array($arg1, ['-h', '--help', 'help'], true)) {
return $this->createArguments(self::COMMAND_HELP);
}
$class = $arg1;
if (! class_exists($class)) {
return $this->createArguments(self::COMMAND_ERROR, null, sprintf(
'Class "%s" does not exist or could not be autoloaded.',
$class
));
}
return $this->createArguments(self::COMMAND_DUMP, $class);
}
/**
* @param resource $resource Defaults to STDOUT
* @return void
*/
private function help($resource = STDOUT)
{
$this->helper->writeLine(sprintf(
self::HELP_TEMPLATE,
$this->scriptName
), true, $resource);
}
/**
* @param string $command
* @param string|null $class Name of class to reflect.
* @param string|null $error Error message, if any.
* @return ArgumentObject
*/
private function createArguments($command, $class = null, $error = null)
{
return (object) [
'command' => $command,
'class' => $class,
'message' => $error,
];
}
}
laminas-servicemanager/src/Tool/ConfigDumperCommand.php 0000644 00000015566 15240152640 0017273 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Tool;
use Laminas\ServiceManager\Exception;
use Laminas\Stdlib\ConsoleHelper;
use function array_shift;
use function class_exists;
use function dirname;
use function file_exists;
use function file_put_contents;
use function in_array;
use function is_array;
use function is_writable;
use function sprintf;
use const STDERR;
use const STDOUT;
/**
* @psalm-type HelpObject = object{
* command: string
* }
* @psalm-type ErrorObject = object{
* command: string,
* message: string
* }
* @psalm-type ArgumentObject = object{
* command: string,
* configFile: string,
* config: array<array-key, mixed>,
* class: string,
* ignoreUnresolved: bool
* }
*/
class ConfigDumperCommand
{
public const COMMAND_DUMP = 'dump';
public const COMMAND_ERROR = 'error';
public const COMMAND_HELP = 'help';
public const DEFAULT_SCRIPT_NAME = self::class;
public const HELP_TEMPLATE = <<<EOH
<info>Usage:</info>
%s [-h|--help|help] [-i|--ignore-unresolved] <configFile> <className>
<info>Arguments:</info>
<info>-h|--help|help</info> This usage message
<info>-i|--ignore-unresolved</info> Ignore classes with unresolved direct dependencies.
<info><configFile></info> Path to a config file for which to generate
configuration. If the file does not exist, it will
be created. If it does exist, it must return an
array, and the file will be updated with new
configuration.
<info><className></info> Name of the class to reflect and for which to
generate dependency configuration.
Reads the provided configuration file (creating it if it does not exist),
and injects it with ConfigAbstractFactory dependency configuration for
the provided class name, writing the changes back to the file.
EOH;
private ConsoleHelper $helper;
/**
* @param string $scriptName
*/
public function __construct(private $scriptName = self::DEFAULT_SCRIPT_NAME, ?ConsoleHelper $helper = null)
{
$this->helper = $helper ?: new ConsoleHelper();
}
/**
* @param array $args Argument list, minus script name
* @return int Exit status
*/
public function __invoke(array $args)
{
$arguments = $this->parseArgs($args);
switch ($arguments->command) {
case self::COMMAND_HELP:
$this->help();
return 0;
case self::COMMAND_ERROR:
$this->helper->writeErrorMessage($arguments->message);
$this->help(STDERR);
return 1;
case self::COMMAND_DUMP:
// fall-through
default:
break;
}
$dumper = new ConfigDumper();
try {
$config = $dumper->createDependencyConfig(
$arguments->config,
$arguments->class,
$arguments->ignoreUnresolved
);
} catch (Exception\InvalidArgumentException $e) {
$this->helper->writeErrorMessage(sprintf(
'Unable to create config for "%s": %s',
$arguments->class,
$e->getMessage()
));
$this->help(STDERR);
return 1;
}
file_put_contents($arguments->configFile, $dumper->dumpConfigFile($config));
$this->helper->writeLine(sprintf(
'<info>[DONE]</info> Changes written to %s',
$arguments->configFile
));
return 0;
}
/**
* @return object
*/
private function parseArgs(array $args)
{
if (! $args) {
return $this->createHelpArgument();
}
$arg1 = array_shift($args);
if (in_array($arg1, ['-h', '--help', 'help'], true)) {
return $this->createHelpArgument();
}
$ignoreUnresolved = false;
if (in_array($arg1, ['-i', '--ignore-unresolved'], true)) {
$ignoreUnresolved = true;
$arg1 = array_shift($args);
}
if (! $args) {
return $this->createErrorArgument('Missing class name');
}
$configFile = $arg1;
switch (file_exists($configFile)) {
case true:
$config = require $configFile;
if (! is_array($config)) {
return $this->createErrorArgument(sprintf(
'Configuration at path "%s" does not return an array.',
$configFile
));
}
break;
case false:
// fall-through
default:
if (! is_writable(dirname($configFile))) {
return $this->createErrorArgument(sprintf(
'Cannot create configuration at path "%s"; not writable.',
$configFile
));
}
$config = [];
break;
}
$class = array_shift($args);
if (! class_exists($class)) {
return $this->createErrorArgument(sprintf(
'Class "%s" does not exist or could not be autoloaded.',
$class
));
}
return $this->createArguments(self::COMMAND_DUMP, $configFile, $config, $class, $ignoreUnresolved);
}
/**
* @param resource $resource Defaults to STDOUT
* @return void
*/
private function help($resource = STDOUT)
{
$this->helper->writeLine(sprintf(
self::HELP_TEMPLATE,
$this->scriptName
), true, $resource);
}
/**
* @param string $command
* @param string $configFile File from which config originates, and to
* which it will be written.
* @param array $config Parsed configuration.
* @param string $class Name of class to reflect.
* @param bool $ignoreUnresolved If to ignore classes with unresolved direct dependencies.
* @return ArgumentObject
*/
private function createArguments($command, $configFile, $config, $class, $ignoreUnresolved)
{
return (object) [
'command' => $command,
'configFile' => $configFile,
'config' => $config,
'class' => $class,
'ignoreUnresolved' => $ignoreUnresolved,
];
}
/**
* @param string $message
* @return ErrorObject
*/
private function createErrorArgument($message)
{
return (object) [
'command' => self::COMMAND_ERROR,
'message' => $message,
];
}
/**
* @return HelpObject
*/
private function createHelpArgument()
{
return (object) [
'command' => self::COMMAND_HELP,
];
}
}
laminas-servicemanager/src/Tool/FactoryCreator.php 0000644 00000011054 15240152640 0016325 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Tool;
use Laminas\ServiceManager\Exception\InvalidArgumentException;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Psr\Container\ContainerInterface;
use ReflectionClass;
use ReflectionNamedType;
use ReflectionParameter;
use function array_filter;
use function array_map;
use function array_merge;
use function array_shift;
use function count;
use function implode;
use function preg_replace;
use function sort;
use function sprintf;
use function str_repeat;
use function strrpos;
use function substr;
class FactoryCreator
{
public const FACTORY_TEMPLATE = <<<'EOT'
<?php
declare(strict_types=1);
namespace %s;
%s
class %sFactory implements FactoryInterface
{
/**
* @param ContainerInterface $container
* @param string $requestedName
* @param null|array $options
* @return %s
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new %s(%s);
}
}
EOT;
private const IMPORT_ALWAYS = [
FactoryInterface::class,
ContainerInterface::class,
];
/**
* @param string $className
* @return string
*/
public function createFactory($className)
{
$class = $this->getClassName($className);
return sprintf(
self::FACTORY_TEMPLATE,
preg_replace('/\\\\' . $class . '$/', '', $className),
$this->createImportStatements($className),
$class,
$class,
$class,
$this->createArgumentString($className)
);
}
private function getClassName(string $className): string
{
return substr($className, strrpos($className, '\\') + 1);
}
/**
* @param string $className
* @return array
*/
private function getConstructorParameters($className)
{
$reflectionClass = new ReflectionClass($className);
if (! $reflectionClass->getConstructor()) {
return [];
}
$constructorParameters = $reflectionClass->getConstructor()->getParameters();
if (empty($constructorParameters)) {
return [];
}
$constructorParameters = array_filter(
$constructorParameters,
static function (ReflectionParameter $argument): bool {
if ($argument->isOptional()) {
return false;
}
$type = $argument->getType();
$class = $type instanceof ReflectionNamedType && ! $type->isBuiltin() ? $type->getName() : null;
if (null === $class) {
throw new InvalidArgumentException(sprintf(
'Cannot identify type for constructor argument "%s"; '
. 'no type hint, or non-class/interface type hint',
$argument->getName()
));
}
return true;
}
);
if (empty($constructorParameters)) {
return [];
}
return array_map(static function (ReflectionParameter $parameter): ?string {
$type = $parameter->getType();
return $type instanceof ReflectionNamedType && ! $type->isBuiltin() ? $type->getName() : null;
}, $constructorParameters);
}
/**
* @param string $className
* @return string
*/
private function createArgumentString($className)
{
$arguments = array_map(static fn(string $dependency): string
=> sprintf('$container->get(\\%s::class)', $dependency), $this->getConstructorParameters($className));
switch (count($arguments)) {
case 0:
return '';
case 1:
return array_shift($arguments);
default:
$argumentPad = str_repeat(' ', 12);
$closePad = str_repeat(' ', 8);
return sprintf(
"\n%s%s\n%s",
$argumentPad,
implode(",\n" . $argumentPad, $arguments),
$closePad
);
}
}
private function createImportStatements(string $className): string
{
$imports = array_merge(self::IMPORT_ALWAYS, [$className]);
sort($imports);
return implode("\n", array_map(static fn(string $import): string => sprintf('use %s;', $import), $imports));
}
}
laminas-servicemanager/src/Tool/ConfigDumper.php 0000644 00000016430 15240152640 0015763 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Tool;
use Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory;
use Laminas\ServiceManager\Exception\InvalidArgumentException;
use Psr\Container\ContainerInterface;
use ReflectionClass;
use ReflectionNamedType;
use ReflectionParameter;
use Traversable;
use function array_filter;
use function array_key_exists;
use function class_exists;
use function date;
use function gettype;
use function implode;
use function interface_exists;
use function is_array;
use function is_int;
use function is_string;
use function sprintf;
use function str_repeat;
use function var_export;
class ConfigDumper
{
public const CONFIG_TEMPLATE = <<<EOC
<?php
/**
* This file generated by %s.
* Generated %s
*/
return %s;
EOC;
public function __construct(private ?ContainerInterface $container = null)
{
}
/**
* @param string $className
* @param bool $ignoreUnresolved
* @return array
* @throws InvalidArgumentException For invalid $className.
*/
public function createDependencyConfig(array $config, $className, $ignoreUnresolved = false)
{
$this->validateClassName($className);
$reflectionClass = new ReflectionClass($className);
// class is an interface; do nothing
if ($reflectionClass->isInterface()) {
return $config;
}
// class has no constructor, treat it as an invokable
if (! $reflectionClass->getConstructor()) {
return $this->createInvokable($config, $className);
}
$constructorArguments = $reflectionClass->getConstructor()->getParameters();
$constructorArguments = array_filter(
$constructorArguments,
static fn(ReflectionParameter $argument): bool => ! $argument->isOptional()
);
// has no required parameters, treat it as an invokable
if (empty($constructorArguments)) {
return $this->createInvokable($config, $className);
}
$classConfig = [];
foreach ($constructorArguments as $constructorArgument) {
$type = $constructorArgument->getType();
$argumentType = $type instanceof ReflectionNamedType && ! $type->isBuiltin() ? $type->getName() : null;
if ($argumentType === null) {
if ($ignoreUnresolved) {
// don't throw an exception, just return the previous config
return $config;
}
// don't throw an exception if the class is an already defined service
if ($this->container && $this->container->has($className)) {
return $config;
}
throw new InvalidArgumentException(sprintf(
'Cannot create config for constructor argument "%s", '
. 'it has no type hint, or non-class/interface type hint',
$constructorArgument->getName()
));
}
$config = $this->createDependencyConfig($config, $argumentType, $ignoreUnresolved);
$classConfig[] = $argumentType;
}
$config[ConfigAbstractFactory::class][$className] = $classConfig;
return $config;
}
/**
* @param string $className
* @throws InvalidArgumentException If class name is not a string or does
* not exist.
*/
private function validateClassName($className)
{
if (! is_string($className)) {
throw new InvalidArgumentException('Class name must be a string, ' . gettype($className) . ' given');
}
if (! class_exists($className) && ! interface_exists($className)) {
throw new InvalidArgumentException('Cannot find class or interface with name ' . $className);
}
}
/**
* @param string $className
* @return array
*/
private function createInvokable(array $config, $className)
{
$config[ConfigAbstractFactory::class][$className] = [];
return $config;
}
/**
* @return array
* @throws InvalidArgumentException If ConfigAbstractFactory configuration
* value is not an array.
*/
public function createFactoryMappingsFromConfig(array $config)
{
if (! array_key_exists(ConfigAbstractFactory::class, $config)) {
return $config;
}
if (! is_array($config[ConfigAbstractFactory::class])) {
throw new InvalidArgumentException(
'Config key for ' . ConfigAbstractFactory::class . ' should be an array, ' . gettype(
$config[ConfigAbstractFactory::class]
) . ' given'
);
}
foreach ($config[ConfigAbstractFactory::class] as $className => $dependency) {
$config = $this->createFactoryMappings($config, $className);
}
return $config;
}
/**
* @param string $className
* @return array
*/
public function createFactoryMappings(array $config, $className)
{
$this->validateClassName($className);
if (
array_key_exists('service_manager', $config)
&& array_key_exists('factories', $config['service_manager'])
&& array_key_exists($className, $config['service_manager']['factories'])
) {
return $config;
}
$config['service_manager']['factories'][$className] = ConfigAbstractFactory::class;
return $config;
}
/**
* @return string
*/
public function dumpConfigFile(array $config)
{
$prepared = $this->prepareConfig($config);
return sprintf(
self::CONFIG_TEMPLATE,
static::class,
date('Y-m-d H:i:s'),
$prepared
);
}
/**
* @param array|Traversable $config
* @param int $indentLevel
* @return string
*/
private function prepareConfig($config, $indentLevel = 1)
{
$indent = str_repeat(' ', $indentLevel * 4);
$entries = [];
foreach ($config as $key => $value) {
$key = $this->createConfigKey($key);
$entries[] = sprintf(
'%s%s%s,',
$indent,
$key ? sprintf('%s => ', $key) : '',
$this->createConfigValue($value, $indentLevel)
);
}
$outerIndent = str_repeat(' ', ($indentLevel - 1) * 4);
return sprintf(
"[\n%s\n%s]",
implode("\n", $entries),
$outerIndent
);
}
/**
* @param string|int|null $key
* @return null|string
*/
private function createConfigKey($key)
{
if (is_string($key) && class_exists($key)) {
return sprintf('\\%s::class', $key);
}
if (is_int($key)) {
return null;
}
return sprintf("'%s'", $key);
}
/**
* @param int $indentLevel
* @return string
*/
private function createConfigValue(mixed $value, $indentLevel)
{
if (is_array($value) || $value instanceof Traversable) {
return $this->prepareConfig($value, $indentLevel + 1);
}
if (is_string($value) && class_exists($value)) {
return sprintf('\\%s::class', $value);
}
return var_export($value, true);
}
}
laminas-servicemanager/src/Initializer/InitializerInterface.php 0000644 00000001041 15240152640 0021043 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Initializer;
use Psr\Container\ContainerInterface;
/**
* Interface for an initializer
*
* An initializer can be registered to a service locator, and are run after an instance is created
* to inject additional dependencies through setters
*/
interface InitializerInterface
{
/**
* Initialize the given instance
*
* @param object $instance
* @return void
*/
public function __invoke(ContainerInterface $container, $instance);
}
laminas-servicemanager/src/ServiceManager.php 0000644 00000101561 15240152640 0015357 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager;
use Exception;
use Laminas\ServiceManager\Exception\ContainerModificationsNotAllowedException;
use Laminas\ServiceManager\Exception\CyclicAliasException;
use Laminas\ServiceManager\Exception\InvalidArgumentException;
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
use Laminas\ServiceManager\Proxy\LazyServiceFactory;
use Laminas\Stdlib\ArrayUtils;
use ProxyManager\Configuration as ProxyConfiguration;
use ProxyManager\Factory\LazyLoadingValueHolderFactory;
use ProxyManager\FileLocator\FileLocator;
use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
use ProxyManager\GeneratorStrategy\FileWriterGeneratorStrategy;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use function array_intersect;
use function array_key_exists;
use function array_keys;
use function class_exists;
use function gettype;
use function in_array;
use function is_callable;
use function is_object;
use function is_string;
use function spl_autoload_register;
use function spl_object_hash;
use function sprintf;
use function trigger_error;
use const E_USER_DEPRECATED;
/**
* Service Manager.
*
* Default implementation of the ServiceLocatorInterface, providing capabilities
* for object creation via:
*
* - factories
* - abstract factories
* - delegator factories
* - lazy service factories (generated proxies)
* - initializers (interface injection)
*
* It also provides the ability to inject specific service instances and to
* define aliases.
*
* @see ConfigInterface
*
* @psalm-import-type ServiceManagerConfigurationType from ConfigInterface
* @psalm-import-type AbstractFactoriesConfigurationType from ConfigInterface
* @psalm-import-type DelegatorsConfigurationType from ConfigInterface
* @psalm-import-type FactoriesConfigurationType from ConfigInterface
* @psalm-import-type InitializersConfigurationType from ConfigInterface
* @psalm-import-type LazyServicesConfigurationType from ConfigInterface
* @psalm-type ServiceManagerConfiguration = array{shared_by_default?:bool}&ServiceManagerConfigurationType
*/
class ServiceManager implements ServiceLocatorInterface
{
/** @var Factory\AbstractFactoryInterface[] */
protected $abstractFactories = [];
/**
* A list of aliases
*
* Should map one alias to a service name, or another alias (aliases are recursively resolved)
*
* @var string[]
*/
protected $aliases = [];
/**
* Whether or not changes may be made to this instance.
*
* @var bool
*/
protected $allowOverride = false;
/** @var ContainerInterface */
protected $creationContext;
/**
* @var string[][]|Factory\DelegatorFactoryInterface[][]
* @psalm-var DelegatorsConfigurationType
*/
protected $delegators = [];
/**
* A list of factories (either as string name or callable)
*
* @var string[]|callable[]
* @psalm-var FactoriesConfigurationType
*/
protected $factories = [];
/**
* @var Initializer\InitializerInterface[]|callable[]
* @psalm-var InitializersConfigurationType
*/
protected $initializers = [];
/**
* @var array
* @psalm-var LazyServicesConfigurationType
*/
protected $lazyServices = [];
private ?LazyServiceFactory $lazyServicesDelegator = null;
/**
* A list of already loaded services (this act as a local cache)
*
* @var array<string,array|object>
*/
protected $services = [];
/**
* Enable/disable shared instances by service name.
*
* Example configuration:
*
* 'shared' => [
* MyService::class => true, // will be shared, even if "sharedByDefault" is false
* MyOtherService::class => false // won't be shared, even if "sharedByDefault" is true
* ]
*
* @var array<string,bool>
*/
protected $shared = [];
/**
* Should the services be shared by default?
*
* @var bool
*/
protected $sharedByDefault = true;
/**
* Service manager was already configured?
*
* @var bool
*/
protected $configured = false;
/**
* Cached abstract factories from string.
*/
private array $cachedAbstractFactories = [];
/**
* See {@see \Laminas\ServiceManager\ServiceManager::configure()} for details
* on what $config accepts.
*
* @psalm-param ServiceManagerConfiguration $config
*/
public function __construct(array $config = [])
{
$this->creationContext = $this;
$this->configure($config);
}
/**
* Implemented for backwards compatibility with previous plugin managers only.
*
* Returns the creation context.
*
* @deprecated since 3.0.0. Factories using 3.0 should use the container
* instance passed to the factory instead.
*
* @return ContainerInterface
*/
public function getServiceLocator()
{
trigger_error(sprintf(
'Usage of %s is deprecated since v3.0.0; please use the container passed to the factory instead',
__METHOD__
), E_USER_DEPRECATED);
return $this->creationContext;
}
/** {@inheritDoc} */
public function get($name)
{
// We start by checking if we have cached the requested service;
// this is the fastest method.
if (isset($this->services[$name])) {
return $this->services[$name];
}
// Determine if the service should be shared.
$sharedService = $this->shared[$name] ?? $this->sharedByDefault;
// We achieve better performance if we can let all alias
// considerations out.
if (! $this->aliases) {
$object = $this->doCreate($name);
// Cache the object for later, if it is supposed to be shared.
if ($sharedService) {
$this->services[$name] = $object;
}
return $object;
}
// We now deal with requests which may be aliases.
$resolvedName = $this->aliases[$name] ?? $name;
// Update shared service information as we checked if the alias was shared before.
if ($resolvedName !== $name) {
$sharedService = $this->shared[$resolvedName] ?? $sharedService;
}
// The following is only true if the requested service is a shared alias.
$sharedAlias = $sharedService && isset($this->services[$resolvedName]);
// If the alias is configured as a shared service, we are done.
if ($sharedAlias) {
$this->services[$name] = $this->services[$resolvedName];
return $this->services[$resolvedName];
}
// At this point, we have to create the object.
// We use the resolved name for that.
$object = $this->doCreate($resolvedName);
// Cache the object for later, if it is supposed to be shared.
if ($sharedService) {
$this->services[$resolvedName] = $object;
}
// Also cache under the alias name; this allows sharing based on the
// service name used.
if ($sharedAlias) {
$this->services[$name] = $object;
}
return $object;
}
/** {@inheritDoc} */
public function build($name, ?array $options = null)
{
// We never cache when using "build".
$name = $this->aliases[$name] ?? $name;
return $this->doCreate($name, $options);
}
/**
* {@inheritDoc}
*
* @param string|class-string $name
* @return bool
*/
public function has($name)
{
// Check static services and factories first to speedup the most common requests.
return $this->staticServiceOrFactoryCanCreate($name) || $this->abstractFactoryCanCreate($name);
}
/**
* Indicate whether or not the instance is immutable.
*
* @param bool $flag
*/
public function setAllowOverride($flag)
{
$this->allowOverride = (bool) $flag;
}
/**
* Retrieve the flag indicating immutability status.
*
* @return bool
*/
public function getAllowOverride()
{
return $this->allowOverride;
}
/**
* @psalm-param ServiceManagerConfiguration $config
* @return self
* @throws ContainerModificationsNotAllowedException If the allow
* override flag has been toggled off, and a service instance
* exists for a given service.
*/
public function configure(array $config)
{
// This is a bulk update/initial configuration,
// so we check all definitions up front.
$this->validateServiceNames($config);
if (isset($config['services'])) {
$this->services = $config['services'] + $this->services;
}
if (isset($config['invokables']) && ! empty($config['invokables'])) {
$newAliases = $this->createAliasesAndFactoriesForInvokables($config['invokables']);
// override existing aliases with those created by invokables to ensure
// that they are still present after merging aliases later on
$config['aliases'] = $newAliases + ($config['aliases'] ?? []);
}
if (isset($config['factories'])) {
$this->factories = $config['factories'] + $this->factories;
}
if (isset($config['delegators'])) {
$this->mergeDelegators($config['delegators']);
}
if (isset($config['shared'])) {
$this->shared = $config['shared'] + $this->shared;
}
if (! empty($config['aliases'])) {
$this->aliases = $config['aliases'] + $this->aliases;
$this->mapAliasesToTargets();
} elseif (! $this->configured && ! empty($this->aliases)) {
$this->mapAliasesToTargets();
}
if (isset($config['shared_by_default'])) {
$this->sharedByDefault = $config['shared_by_default'];
}
// If lazy service configuration was provided, reset the lazy services
// delegator factory.
if (isset($config['lazy_services']) && ! empty($config['lazy_services'])) {
/** @psalm-suppress MixedPropertyTypeCoercion */
$this->lazyServices = ArrayUtils::merge($this->lazyServices, $config['lazy_services']);
$this->lazyServicesDelegator = null;
}
// For abstract factories and initializers, we always directly
// instantiate them to avoid checks during service construction.
if (isset($config['abstract_factories'])) {
$abstractFactories = $config['abstract_factories'];
// $key not needed, but foreach is faster than foreach + array_values.
foreach ($abstractFactories as $key => $abstractFactory) {
$this->resolveAbstractFactoryInstance($abstractFactory);
}
}
if (isset($config['initializers'])) {
$this->resolveInitializers($config['initializers']);
}
$this->configured = true;
return $this;
}
/**
* Add an alias.
*
* @param string $alias
* @param string $target
* @throws ContainerModificationsNotAllowedException If $alias already
* exists as a service and overrides are disallowed.
*/
public function setAlias($alias, $target)
{
if (isset($this->services[$alias]) && ! $this->allowOverride) {
throw ContainerModificationsNotAllowedException::fromExistingService($alias);
}
$this->mapAliasToTarget($alias, $target);
}
/**
* Add an invokable class mapping.
*
* @param string $name Service name
* @param null|string $class Class to which to map; if omitted, $name is
* assumed.
* @throws ContainerModificationsNotAllowedException If $name already
* exists as a service and overrides are disallowed.
*/
public function setInvokableClass($name, $class = null)
{
if (isset($this->services[$name]) && ! $this->allowOverride) {
throw ContainerModificationsNotAllowedException::fromExistingService($name);
}
$this->createAliasesAndFactoriesForInvokables([$name => $class ?? $name]);
}
/**
* Specify a factory for a given service name.
*
* @param string $name Service name
* @param string|callable|Factory\FactoryInterface $factory Factory to which to map.
* phpcs:disable Generic.Files.LineLength.TooLong
* @psalm-param class-string<Factory\FactoryInterface>|callable(ContainerInterface,string,array<mixed>|null):object|Factory\FactoryInterface $factory
* phpcs:enable Generic.Files.LineLength.TooLong
* @return void
* @throws ContainerModificationsNotAllowedException If $name already
* exists as a service and overrides are disallowed.
*/
public function setFactory($name, $factory)
{
if (isset($this->services[$name]) && ! $this->allowOverride) {
throw ContainerModificationsNotAllowedException::fromExistingService($name);
}
$this->factories[$name] = $factory;
}
/**
* Create a lazy service mapping to a class.
*
* @param string $name Service name to map
* @param null|string $class Class to which to map; if not provided, $name
* will be used for the mapping.
*/
public function mapLazyService($name, $class = null)
{
$this->configure(['lazy_services' => ['class_map' => [$name => $class ?: $name]]]);
}
/**
* Add an abstract factory for resolving services.
*
* @param string|Factory\AbstractFactoryInterface $factory Abstract factory
* instance or class name.
* @psalm-param class-string<Factory\AbstractFactoryInterface>|Factory\AbstractFactoryInterface $factory
*/
public function addAbstractFactory($factory)
{
$this->resolveAbstractFactoryInstance($factory);
}
/**
* Add a delegator for a given service.
*
* @param string $name Service name
* @param string|callable|Factory\DelegatorFactoryInterface $factory Delegator
* factory to assign.
* @psalm-param class-string<Factory\DelegatorFactoryInterface>
* |callable(ContainerInterface,string,callable,array<mixed>|null) $factory
*/
public function addDelegator($name, $factory)
{
$this->configure(['delegators' => [$name => [$factory]]]);
}
/**
* Add an initializer.
*
* @param string|callable|Initializer\InitializerInterface $initializer
* @psalm-param class-string<Initializer\InitializerInterface>
* |callable(ContainerInterface,mixed):void
* |Initializer\InitializerInterface $initializer
*/
public function addInitializer($initializer)
{
$this->configure(['initializers' => [$initializer]]);
}
/**
* Map a service.
*
* @param string $name Service name
* @param array|object $service
* @throws ContainerModificationsNotAllowedException If $name already
* exists as a service and overrides are disallowed.
*/
public function setService($name, $service)
{
if (isset($this->services[$name]) && ! $this->allowOverride) {
throw ContainerModificationsNotAllowedException::fromExistingService($name);
}
$this->services[$name] = $service;
}
/**
* Add a service sharing rule.
*
* @param string $name Service name
* @param bool $flag Whether or not the service should be shared.
* @throws ContainerModificationsNotAllowedException If $name already
* exists as a service and overrides are disallowed.
*/
public function setShared($name, $flag)
{
if (isset($this->services[$name]) && ! $this->allowOverride) {
throw ContainerModificationsNotAllowedException::fromExistingService($name);
}
$this->shared[$name] = (bool) $flag;
}
/**
* Instantiate initializers for to avoid checks during service construction.
*
* @psalm-param InitializersConfigurationType $initializers
*/
private function resolveInitializers(array $initializers): void
{
foreach ($initializers as $initializer) {
if (is_string($initializer) && class_exists($initializer)) {
$initializer = new $initializer();
}
if (is_callable($initializer)) {
$this->initializers[] = $initializer;
continue;
}
throw InvalidArgumentException::fromInvalidInitializer($initializer);
}
}
/**
* Get a factory for the given service name
*
* @psalm-return (callable(ContainerInterface,string,array<mixed>|null):object)|Factory\FactoryInterface
* @throws ServiceNotFoundException
*/
private function getFactory(string $name): callable
{
$factory = $this->factories[$name] ?? null;
$lazyLoaded = false;
if (is_string($factory) && class_exists($factory)) {
$factory = new $factory();
$lazyLoaded = true;
}
if (is_callable($factory)) {
if ($lazyLoaded) {
$this->factories[$name] = $factory;
}
return $factory;
}
// Check abstract factories
foreach ($this->abstractFactories as $abstractFactory) {
if ($abstractFactory->canCreate($this->creationContext, $name)) {
return $abstractFactory;
}
}
throw new ServiceNotFoundException(sprintf(
'Unable to resolve service "%s" to a factory; are you certain you provided it during configuration?',
$name
));
}
/**
* @return object
*/
private function createDelegatorFromName(string $name, ?array $options = null)
{
$creationCallback = function () use ($name, $options) {
// Code is inlined for performance reason, instead of abstracting the creation
$factory = $this->getFactory($name);
return $factory($this->creationContext, $name, $options);
};
$initialCreationContext = $this->creationContext;
foreach ($this->delegators[$name] as $index => $delegatorFactory) {
$delegatorFactory = $this->delegators[$name][$index];
if ($delegatorFactory === LazyServiceFactory::class) {
$delegatorFactory = $this->createLazyServiceDelegatorFactory();
} elseif (is_string($delegatorFactory) && class_exists($delegatorFactory)) {
$delegatorFactory = new $delegatorFactory();
}
$this->assertCallableDelegatorFactory($delegatorFactory);
$this->delegators[$name][$index] = $delegatorFactory;
$creationCallback =
/** @return object */
static fn() => $delegatorFactory($initialCreationContext, $name, $creationCallback, $options);
}
return $creationCallback();
}
/**
* Create a new instance with an already resolved name
*
* This is a highly performance sensitive method, do not modify if you have not benchmarked it carefully
*
* @return object
* @throws ServiceNotFoundException If unable to resolve the service.
* @throws ServiceNotCreatedException If an exception is raised when creating a service.
* @throws ContainerExceptionInterface If any other error occurs.
*/
private function doCreate(string $resolvedName, ?array $options = null)
{
try {
if (! isset($this->delegators[$resolvedName])) {
// Let's create the service by fetching the factory
$factory = $this->getFactory($resolvedName);
$object = $factory($this->creationContext, $resolvedName, $options);
} else {
$object = $this->createDelegatorFromName($resolvedName, $options);
}
} catch (ContainerExceptionInterface $exception) {
throw $exception;
} catch (Exception $exception) {
throw new ServiceNotCreatedException(sprintf(
'Service with name "%s" could not be created. Reason: %s',
$resolvedName,
$exception->getMessage()
), (int) $exception->getCode(), $exception);
}
foreach ($this->initializers as $initializer) {
$initializer($this->creationContext, $object);
}
return $object;
}
/**
* Create the lazy services delegator factory.
*
* Creates the lazy services delegator factory based on the lazy_services
* configuration present.
*
* @throws ServiceNotCreatedException When the lazy service class_map configuration is missing.
*/
private function createLazyServiceDelegatorFactory(): LazyServiceFactory
{
if ($this->lazyServicesDelegator) {
return $this->lazyServicesDelegator;
}
if (! isset($this->lazyServices['class_map'])) {
throw new ServiceNotCreatedException('Missing "class_map" config key in "lazy_services"');
}
$factoryConfig = new ProxyConfiguration();
if (isset($this->lazyServices['proxies_namespace'])) {
$factoryConfig->setProxiesNamespace($this->lazyServices['proxies_namespace']);
}
if (isset($this->lazyServices['proxies_target_dir'])) {
$factoryConfig->setProxiesTargetDir($this->lazyServices['proxies_target_dir']);
}
if (! isset($this->lazyServices['write_proxy_files']) || ! $this->lazyServices['write_proxy_files']) {
$factoryConfig->setGeneratorStrategy(new EvaluatingGeneratorStrategy());
} else {
$factoryConfig->setGeneratorStrategy(new FileWriterGeneratorStrategy(
new FileLocator($factoryConfig->getProxiesTargetDir())
));
}
spl_autoload_register($factoryConfig->getProxyAutoloader());
$this->lazyServicesDelegator = new LazyServiceFactory(
new LazyLoadingValueHolderFactory($factoryConfig),
$this->lazyServices['class_map']
);
return $this->lazyServicesDelegator;
}
/**
* Merge delegators avoiding multiple same delegators for the same service.
* It works with strings and class instances.
* It's not possible to de-duple anonymous functions
*
* @psalm-param DelegatorsConfigurationType $config
* @psalm-return DelegatorsConfigurationType
*/
private function mergeDelegators(array $config): array
{
foreach ($config as $key => $delegators) {
if (! array_key_exists($key, $this->delegators)) {
$this->delegators[$key] = $delegators;
continue;
}
foreach ($delegators as $delegator) {
if (! in_array($delegator, $this->delegators[$key], true)) {
$this->delegators[$key][] = $delegator;
}
}
}
return $this->delegators;
}
/**
* Create aliases and factories for invokable classes.
*
* If an invokable service name does not match the class it maps to, this
* creates an alias to the class (which will later be mapped as an
* invokable factory). The newly created aliases will be returned as an array.
*
* @param array<string,string> $invokables
* @return array<string,string>
*/
private function createAliasesAndFactoriesForInvokables(array $invokables): array
{
$newAliases = [];
foreach ($invokables as $name => $class) {
$this->factories[$class] = Factory\InvokableFactory::class;
if ($name !== $class) {
$this->aliases[$name] = $class;
$newAliases[$name] = $class;
}
}
return $newAliases;
}
/**
* Determine if a service for any name provided by a service
* manager configuration(services, aliases, factories, ...)
* already exists, and if it exists, determine if is it allowed
* to get overriden.
*
* Validation in the context of this class means, that for
* a given service name we do not have a service instance
* in the cache OR override is explicitly allowed.
*
* @psalm-param ServiceManagerConfigurationType $config
* @throws ContainerModificationsNotAllowedException If any
* service key is invalid.
*/
private function validateServiceNames(array $config): void
{
if ($this->allowOverride || ! $this->configured) {
return;
}
if (isset($config['services'])) {
foreach (array_keys($config['services']) as $service) {
if (isset($this->services[$service])) {
throw ContainerModificationsNotAllowedException::fromExistingService($service);
}
}
}
if (isset($config['aliases'])) {
foreach (array_keys($config['aliases']) as $service) {
if (isset($this->services[$service])) {
throw ContainerModificationsNotAllowedException::fromExistingService($service);
}
}
}
if (isset($config['invokables'])) {
foreach (array_keys($config['invokables']) as $service) {
if (isset($this->services[$service])) {
throw ContainerModificationsNotAllowedException::fromExistingService($service);
}
}
}
if (isset($config['factories'])) {
foreach (array_keys($config['factories']) as $service) {
if (isset($this->services[$service])) {
throw ContainerModificationsNotAllowedException::fromExistingService($service);
}
}
}
if (isset($config['delegators'])) {
foreach (array_keys($config['delegators']) as $service) {
if (isset($this->services[$service])) {
throw ContainerModificationsNotAllowedException::fromExistingService($service);
}
}
}
if (isset($config['shared'])) {
foreach (array_keys($config['shared']) as $service) {
if (isset($this->services[$service])) {
throw ContainerModificationsNotAllowedException::fromExistingService($service);
}
}
}
if (isset($config['lazy_services']['class_map'])) {
foreach (array_keys($config['lazy_services']['class_map']) as $service) {
if (isset($this->services[$service])) {
throw ContainerModificationsNotAllowedException::fromExistingService($service);
}
}
}
}
/**
* Assuming that the alias name is valid (see above) resolve/add it.
*
* This is done differently from bulk mapping aliases for performance reasons, as the
* algorithms for mapping a single item efficiently are different from those of mapping
* many.
*/
private function mapAliasToTarget(string $alias, string $target): void
{
// $target is either an alias or something else
// if it is an alias, resolve it
$this->aliases[$alias] = $this->aliases[$target] ?? $target;
// a self-referencing alias indicates a cycle
if ($alias === $this->aliases[$alias]) {
throw CyclicAliasException::fromCyclicAlias($alias, $this->aliases);
}
// finally we have to check if existing incomplete alias definitions
// exist which can get resolved by the new alias
if (in_array($alias, $this->aliases)) {
$r = array_intersect($this->aliases, [$alias]);
// found some, resolve them
foreach ($r as $name => $service) {
$this->aliases[$name] = $target;
}
}
}
/**
* Assuming that all provided alias keys are valid resolve them.
*
* This function maps $this->aliases in place.
*
* This algorithm is an adaptated version of Tarjans Strongly
* Connected Components. Instead of returning the strongly
* connected components (i.e. cycles in our case), we throw.
* If nodes are not strongly connected (i.e. resolvable in
* our case), they get resolved.
*
* This algorithm is fast for mass updates through configure().
* It is not appropriate if just a single alias is added.
*
* @see mapAliasToTarget above
*/
private function mapAliasesToTargets(): void
{
$tagged = [];
foreach ($this->aliases as $alias => $target) {
if (isset($tagged[$alias])) {
continue;
}
$tCursor = $this->aliases[$alias];
$aCursor = $alias;
if ($aCursor === $tCursor) {
throw CyclicAliasException::fromCyclicAlias($alias, $this->aliases);
}
if (! isset($this->aliases[$tCursor])) {
continue;
}
$stack = [];
while (isset($this->aliases[$tCursor])) {
$stack[] = $aCursor;
if ($aCursor === $this->aliases[$tCursor]) {
throw CyclicAliasException::fromCyclicAlias($alias, $this->aliases);
}
$aCursor = $tCursor;
$tCursor = $this->aliases[$tCursor];
}
$tagged[$aCursor] = true;
foreach ($stack as $alias) {
if ($alias === $tCursor) {
throw CyclicAliasException::fromCyclicAlias($alias, $this->aliases);
}
$this->aliases[$alias] = $tCursor;
$tagged[$alias] = true;
}
}
}
/**
* Instantiate abstract factories in order to avoid checks during service construction.
*
* @param string|Factory\AbstractFactoryInterface $abstractFactory
* @psalm-param class-string<Factory\AbstractFactoryInterface>|Factory\AbstractFactoryInterface $abstractFactory
*/
private function resolveAbstractFactoryInstance($abstractFactory): void
{
if (is_string($abstractFactory) && class_exists($abstractFactory)) {
// Cached string factory name
if (! isset($this->cachedAbstractFactories[$abstractFactory])) {
$this->cachedAbstractFactories[$abstractFactory] = new $abstractFactory();
}
$abstractFactory = $this->cachedAbstractFactories[$abstractFactory];
}
if (! $abstractFactory instanceof Factory\AbstractFactoryInterface) {
throw InvalidArgumentException::fromInvalidAbstractFactory($abstractFactory);
}
$abstractFactoryObjHash = spl_object_hash($abstractFactory);
$this->abstractFactories[$abstractFactoryObjHash] = $abstractFactory;
}
/**
* Check if a static service or factory exists for the given name.
*/
private function staticServiceOrFactoryCanCreate(string $name): bool
{
if (isset($this->services[$name]) || isset($this->factories[$name])) {
return true;
}
$resolvedName = $this->aliases[$name] ?? $name;
if ($resolvedName !== $name) {
return $this->staticServiceOrFactoryCanCreate($resolvedName);
}
return false;
}
/**
* Check if an abstract factory exists that can create a service for the given name.
*/
private function abstractFactoryCanCreate(string $name): bool
{
foreach ($this->abstractFactories as $abstractFactory) {
if ($abstractFactory->canCreate($this->creationContext, $name)) {
return true;
}
}
$resolvedName = $this->aliases[$name] ?? $name;
if ($resolvedName !== $name) {
return $this->abstractFactoryCanCreate($resolvedName);
}
return false;
}
/**
* @psalm-param mixed $delegatorFactory
* @psalm-assert callable(ContainerInterface,string,callable():object,array<mixed>|null):object $delegatorFactory
*/
private function assertCallableDelegatorFactory($delegatorFactory): void
{
if (
$delegatorFactory instanceof Factory\DelegatorFactoryInterface
|| is_callable($delegatorFactory)
) {
return;
}
if (is_string($delegatorFactory)) {
throw new ServiceNotCreatedException(sprintf(
'An invalid delegator factory was registered; resolved to class or function "%s"'
. ' which does not exist; please provide a valid function name or class name resolving'
. ' to an implementation of %s',
$delegatorFactory,
DelegatorFactoryInterface::class
));
}
throw new ServiceNotCreatedException(sprintf(
'A non-callable delegator, "%s", was provided; expected a callable or instance of "%s"',
is_object($delegatorFactory) ? $delegatorFactory::class : gettype($delegatorFactory),
DelegatorFactoryInterface::class
));
}
}
laminas-servicemanager/src/ServiceLocatorInterface.php 0000644 00000001662 15240152640 0017232 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
/**
* Interface for service locator
*/
interface ServiceLocatorInterface extends ContainerInterface
{
/**
* Build a service by its name, using optional options (such services are NEVER cached).
*
* @template T of object
* @param string|class-string<T> $name
* @param null|array<mixed> $options
* @return mixed
* @psalm-return ($name is class-string<T> ? T : mixed)
* @throws Exception\ServiceNotFoundException If no factory/abstract
* factory could be found to create the instance.
* @throws Exception\ServiceNotCreatedException If factory/delegator fails
* to create the instance.
* @throws ContainerExceptionInterface If any other error occurs.
*/
public function build($name, ?array $options = null);
}
laminas-servicemanager/src/Test/CommonPluginManagerTrait.php 0000644 00000007241 15240152640 0020311 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\Test;
use Laminas\ServiceManager\AbstractPluginManager;
use Laminas\ServiceManager\Exception\InvalidServiceException;
use ReflectionClass;
use ReflectionProperty;
use function method_exists;
/**
* Trait for testing plugin managers for v2-v3 compatibility
*
* To use this trait:
* * implement the `getPluginManager()` method to return your plugin manager
* * implement the `getV2InvalidPluginException()` method to return the class `validatePlugin()` throws under v2
*/
trait CommonPluginManagerTrait
{
public function testInstanceOfMatches()
{
$manager = $this->getPluginManager();
$reflection = new ReflectionProperty($manager, 'instanceOf');
$reflection->setAccessible(true);
$this->assertEquals($this->getInstanceOf(), $reflection->getValue($manager), 'instanceOf does not match');
}
public function testShareByDefaultAndSharedByDefault()
{
$manager = $this->getPluginManager();
$reflection = new ReflectionClass($manager);
$shareByDefault = $sharedByDefault = true;
foreach ($reflection->getProperties() as $prop) {
if ($prop->getName() === 'shareByDefault') {
$prop->setAccessible(true);
$shareByDefault = $prop->getValue($manager);
}
if ($prop->getName() === 'sharedByDefault') {
$prop->setAccessible(true);
$sharedByDefault = $prop->getValue($manager);
}
}
$this->assertSame(
$shareByDefault,
$sharedByDefault,
'Values of shareByDefault and sharedByDefault do not match'
);
}
public function testRegisteringInvalidElementRaisesException()
{
$this->expectException($this->getServiceNotFoundException());
$this->getPluginManager()->setService('test', $this);
}
public function testLoadingInvalidElementRaisesException()
{
$manager = $this->getPluginManager();
$manager->setInvokableClass('test', static::class);
$this->expectException($this->getServiceNotFoundException());
$manager->get('test');
}
/**
* @dataProvider aliasProvider
* @param string $alias
* @param string $expected
*/
public function testPluginAliasesResolve($alias, $expected)
{
$this->assertInstanceOf($expected, $this->getPluginManager()->get($alias), "Alias '$alias' does not resolve'");
}
/**
* @return array
*/
public function aliasProvider()
{
$manager = $this->getPluginManager();
$reflection = new ReflectionProperty($manager, 'aliases');
$reflection->setAccessible(true);
$data = [];
foreach ($reflection->getValue($manager) as $alias => $expected) {
$data[] = [$alias, $expected];
}
return $data;
}
protected function getServiceNotFoundException(): string
{
$manager = $this->getPluginManager();
if (method_exists($manager, 'configure')) {
return InvalidServiceException::class;
}
return $this->getV2InvalidPluginException();
}
/**
* Returns the plugin manager to test
*
* @return AbstractPluginManager
*/
abstract protected function getPluginManager();
/**
* Returns the FQCN of the exception thrown under v2 by `validatePlugin()`
*
* @return mixed
*/
abstract protected function getV2InvalidPluginException();
/**
* Returns the value the instanceOf property has been set to
*
* @return string
*/
abstract protected function getInstanceOf();
}
laminas-servicemanager/src/InitializerInterface.php 0000644 00000002301 15240152640 0016560 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager;
/**
* Backwards-compatibility shim for InitializerInterface.
*
* Implementations should update to implement only Laminas\ServiceManager\Initializer\InitializerInterface.
*
* If upgrading from v2, take the following steps:
*
* - rename the method `initialize()` to `__invoke()`, and:
* - rename the `$serviceLocator` argument to `$container`, and change the
* typehint to `Psr\Container\ContainerInterface`
* - swap the order of the arguments (so that `$instance` comes second)
* - create an `initialize()` method as defined in this interface, and have it
* proxy to `__invoke()`, passing the arguments in the new order.
*
* Once you have tested your code, you can then update your class to only implement
* Laminas\ServiceManager\Initializer\InitializerInterface, and remove the `initialize()`
* method.
*
* @deprecated Use Laminas\ServiceManager\Initializer\InitializerInterface instead.
*/
interface InitializerInterface extends Initializer\InitializerInterface
{
/**
* Initialize
*
* @return mixed
*/
public function initialize(mixed $instance, ServiceLocatorInterface $serviceLocator);
}
laminas-servicemanager/src/AbstractFactoryInterface.php 0000644 00000004131 15240152640 0017373 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager;
/**
* Backwards-compatibility shim for AbstractFactoryInterface.
*
* Implementations should update to implement only Laminas\ServiceManager\Factory\AbstractFactoryInterface.
*
* If upgrading from v2, take the following steps:
*
* - rename the method `canCreateServiceWithName()` to `canCreate()`, and:
* - rename the `$serviceLocator` argument to `$container`, and change the
* typehint to `Psr\Container\ContainerInterface`
* - merge the `$name` and `$requestedName` arguments
* - rename the method `createServiceWithName()` to `__invoke()`, and:
* - rename the `$serviceLocator` argument to `$container`, and change the
* typehint to `Psr\Container\ContainerInterface`
* - merge the `$name` and `$requestedName` arguments
* - add the optional `array $options = null` argument.
* - create a `canCreateServiceWithName()` method as defined in this interface, and have it
* proxy to `canCreate()`, passing `$requestedName` as the second argument.
* - create a `createServiceWithName()` method as defined in this interface, and have it
* proxy to `__invoke()`, passing `$requestedName` as the second argument.
*
* Once you have tested your code, you can then update your class to only implement
* Laminas\ServiceManager\Factory\AbstractFactoryInterface, and remove the `canCreateServiceWithName()`
* and `createServiceWithName()` methods.
*
* @deprecated Use Laminas\ServiceManager\Factory\AbstractFactoryInterface instead.
*/
interface AbstractFactoryInterface extends Factory\AbstractFactoryInterface
{
/**
* Determine if we can create a service with name
*
* @param string $name
* @param string $requestedName
* @return bool
*/
public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName);
/**
* Create service with name
*
* @param string $name
* @param string $requestedName
* @return mixed
*/
public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName);
}
laminas-servicemanager/src/Config.php 0000644 00000005713 15240152640 0013673 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager;
use Laminas\Stdlib\ArrayUtils;
use function array_keys;
/**
* Object for defining configuration and configuring an existing service manager instance.
*
* In order to provide configuration merging capabilities, this class implements
* the same functionality as `Laminas\Stdlib\ArrayUtils::merge()`. That routine
* allows developers to specifically shape how values are merged:
*
* - A value which is an instance of `MergeRemoveKey` indicates the value should
* be removed during merge.
* - A value that is an instance of `MergeReplaceKeyInterface` indicates that the
* value it contains should be used to replace any previous versions.
*
* These features are advanced, and not typically used. If you wish to use them,
* you will need to require the laminas-stdlib package in your application.
*
* @psalm-import-type ServiceManagerConfigurationType from ConfigInterface
*/
class Config implements ConfigInterface
{
/** @var array<string,bool> */
private array $allowedKeys = [
'abstract_factories' => true,
'aliases' => true,
'delegators' => true,
'factories' => true,
'initializers' => true,
'invokables' => true,
'lazy_services' => true,
'services' => true,
'shared' => true,
];
/**
* @var array<string,array>
* @psalm-var ServiceManagerConfigurationType
*/
protected $config = [
'abstract_factories' => [],
'aliases' => [],
'delegators' => [],
'factories' => [],
'initializers' => [],
'invokables' => [],
'lazy_services' => [],
'services' => [],
'shared' => [],
];
/**
* @psalm-param ServiceManagerConfigurationType $config
*/
public function __construct(array $config = [])
{
// Only merge keys we're interested in
foreach (array_keys($config) as $key) {
if (! isset($this->allowedKeys[$key])) {
unset($config[$key]);
}
}
/** @psalm-suppress ArgumentTypeCoercion */
$this->config = $this->merge($this->config, $config);
}
/**
* @inheritDoc
*/
public function configureServiceManager(ServiceManager $serviceManager)
{
return $serviceManager->configure($this->config);
}
/**
* @inheritDoc
*/
public function toArray()
{
return $this->config;
}
/**
* @psalm-param ServiceManagerConfigurationType $a
* @psalm-param ServiceManagerConfigurationType $b
* @psalm-return ServiceManagerConfigurationType
* @psalm-suppress MixedReturnTypeCoercion
*/
private function merge(array $a, array $b)
{
/** @psalm-suppress MixedReturnTypeCoercion */
return ArrayUtils::merge($a, $b);
}
}
laminas-servicemanager/src/AbstractFactory/ReflectionBasedAbstractFactory.php 0000644 00000020137 15240152640 0023623 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\AbstractFactory;
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
use Laminas\ServiceManager\Factory\AbstractFactoryInterface;
use Psr\Container\ContainerInterface;
use ReflectionClass;
use ReflectionNamedType;
use ReflectionParameter;
use function array_map;
use function class_exists;
use function interface_exists;
use function is_string;
use function sprintf;
/**
* Reflection-based factory.
*
* To ease development, this factory may be used for classes with
* type-hinted arguments that resolve to services in the application
* container; this allows omitting the step of writing a factory for
* each controller.
*
* You may use it as either an abstract factory:
*
* <code>
* 'service_manager' => [
* 'abstract_factories' => [
* ReflectionBasedAbstractFactory::class,
* ],
* ],
* </code>
*
* Or as a factory, mapping a class name to it:
*
* <code>
* 'service_manager' => [
* 'factories' => [
* MyClassWithDependencies::class => ReflectionBasedAbstractFactory::class,
* ],
* ],
* </code>
*
* The latter approach is more explicit, and also more performant.
*
* The factory has the following constraints/features:
*
* - A parameter named `$config` typehinted as an array will receive the
* application "config" service (i.e., the merged configuration).
* - Parameters type-hinted against array, but not named `$config` will
* be injected with an empty array.
* - Scalar parameters will result in an exception being thrown, unless
* a default value is present; if the default is present, that will be used.
* - If a service cannot be found for a given typehint, the factory will
* raise an exception detailing this.
* - Some services provided by Laminas components do not have
* entries based on their class name (for historical reasons); the
* factory allows defining a map of these class/interface names to the
* corresponding service name to allow them to resolve.
*
* `$options` passed to the factory are ignored in all cases, as we cannot
* make assumptions about which argument(s) they might replace.
*
* Based on the LazyControllerAbstractFactory from laminas-mvc.
*/
class ReflectionBasedAbstractFactory implements AbstractFactoryInterface
{
/**
* Maps known classes/interfaces to the service that provides them; only
* required for those services with no entry based on the class/interface
* name.
*
* Extend the class if you wish to add to the list.
*
* Example:
*
* <code>
* [
* \Laminas\Filter\FilterPluginManager::class => 'FilterManager',
* \Laminas\Validator\ValidatorPluginManager::class => 'ValidatorManager',
* ]
* </code>
*
* @var string[]
*/
protected $aliases = [];
/**
* Allows overriding the internal list of aliases. These should be of the
* form `class name => well-known service name`; see the documentation for
* the `$aliases` property for details on what is accepted.
*
* @param string[] $aliases
*/
public function __construct(array $aliases = [])
{
if (! empty($aliases)) {
$this->aliases = $aliases;
}
}
/**
* {@inheritDoc}
*
* @return DispatchableInterface
*/
public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null)
{
$reflectionClass = new ReflectionClass($requestedName);
if (null === ($constructor = $reflectionClass->getConstructor())) {
return new $requestedName();
}
$reflectionParameters = $constructor->getParameters();
if (empty($reflectionParameters)) {
return new $requestedName();
}
$resolver = $container->has('config')
? $this->resolveParameterWithConfigService($container, $requestedName)
: $this->resolveParameterWithoutConfigService($container, $requestedName);
$parameters = array_map($resolver, $reflectionParameters);
return new $requestedName(...$parameters);
}
/** {@inheritDoc} */
public function canCreate(ContainerInterface $container, $requestedName)
{
return class_exists($requestedName) && $this->canCallConstructor($requestedName);
}
private function canCallConstructor(string $requestedName): bool
{
$constructor = (new ReflectionClass($requestedName))->getConstructor();
return $constructor === null || $constructor->isPublic();
}
/**
* Resolve a parameter to a value.
*
* Returns a callback for resolving a parameter to a value, but without
* allowing mapping array `$config` arguments to the `config` service.
*
* @param string $requestedName
* @return callable
*/
private function resolveParameterWithoutConfigService(ContainerInterface $container, $requestedName)
{
/**
* @param ReflectionParameter $parameter
* @return mixed
* @throws ServiceNotFoundException If type-hinted parameter cannot be
* resolved to a service in the container.
* @psalm-suppress MissingClosureReturnType
*/
return fn(ReflectionParameter $parameter) => $this->resolveParameter($parameter, $container, $requestedName);
}
/**
* Returns a callback for resolving a parameter to a value, including mapping 'config' arguments.
*
* Unlike resolveParameter(), this version will detect `$config` array
* arguments and have them return the 'config' service.
*
* @param string $requestedName
* @return callable
*/
private function resolveParameterWithConfigService(ContainerInterface $container, $requestedName)
{
/**
* @param ReflectionParameter $parameter
* @return mixed
* @throws ServiceNotFoundException If type-hinted parameter cannot be
* resolved to a service in the container.
*/
return function (ReflectionParameter $parameter) use ($container, $requestedName) {
if ($parameter->getName() === 'config') {
$type = $parameter->getType();
if ($type instanceof ReflectionNamedType && $type->getName() === 'array') {
return $container->get('config');
}
}
return $this->resolveParameter($parameter, $container, $requestedName);
};
}
/**
* Logic common to all parameter resolution.
*
* @param string $requestedName
* @return mixed
* @throws ServiceNotFoundException If type-hinted parameter cannot be
* resolved to a service in the container.
*/
private function resolveParameter(ReflectionParameter $parameter, ContainerInterface $container, $requestedName)
{
$type = $parameter->getType();
$type = $type instanceof ReflectionNamedType ? $type->getName() : null;
if ($type === 'array') {
return [];
}
if ($type === null || (is_string($type) && ! class_exists($type) && ! interface_exists($type))) {
if (! $parameter->isDefaultValueAvailable()) {
throw new ServiceNotFoundException(sprintf(
'Unable to create service "%s"; unable to resolve parameter "%s" '
. 'to a class, interface, or array type',
$requestedName,
$parameter->getName()
));
}
return $parameter->getDefaultValue();
}
$type = $this->aliases[$type] ?? $type;
if ($container->has($type)) {
return $container->get($type);
}
if (! $parameter->isOptional()) {
throw new ServiceNotFoundException(sprintf(
'Unable to create service "%s"; unable to resolve parameter "%s" using type hint "%s"',
$requestedName,
$parameter->getName(),
$type
));
}
// Type not available in container, but the value is optional and has a
// default defined.
return $parameter->getDefaultValue();
}
}
laminas-servicemanager/src/AbstractFactory/ConfigAbstractFactory.php 0000644 00000005057 15240152640 0022003 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager\AbstractFactory;
use ArrayObject;
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
use Laminas\ServiceManager\Factory\AbstractFactoryInterface;
use Psr\Container\ContainerInterface;
use function array_key_exists;
use function array_map;
use function array_values;
use function is_array;
use function json_encode;
final class ConfigAbstractFactory implements AbstractFactoryInterface
{
/**
* Factory can create the service if there is a key for it in the config
*
* {@inheritdoc}
*/
public function canCreate(ContainerInterface $container, $requestedName)
{
if (! $container->has('config')) {
return false;
}
$config = $container->get('config');
if (! isset($config[self::class])) {
return false;
}
$dependencies = $config[self::class];
return is_array($dependencies) && array_key_exists($requestedName, $dependencies);
}
/** {@inheritDoc} */
public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null)
{
if (! $container->has('config')) {
throw new ServiceNotCreatedException('Cannot find a config array in the container');
}
$config = $container->get('config');
if (! (is_array($config) || $config instanceof ArrayObject)) {
throw new ServiceNotCreatedException('Config must be an array or an instance of ArrayObject');
}
if (! isset($config[self::class])) {
throw new ServiceNotCreatedException('Cannot find a `' . self::class . '` key in the config array');
}
$dependencies = $config[self::class];
if (
! is_array($dependencies)
|| ! array_key_exists($requestedName, $dependencies)
|| ! is_array($dependencies[$requestedName])
) {
throw new ServiceNotCreatedException('Service dependencies config must exist and be an array');
}
$serviceDependencies = $dependencies[$requestedName];
if ($serviceDependencies !== array_values(array_map('strval', $serviceDependencies))) {
$problem = json_encode(array_map('gettype', $serviceDependencies));
throw new ServiceNotCreatedException(
'Service dependencies config must be an array of strings, ' . $problem . ' given'
);
}
$arguments = array_map([$container, 'get'], $serviceDependencies);
return new $requestedName(...$arguments);
}
}
laminas-servicemanager/src/DelegatorFactoryInterface.php 0000644 00000003470 15240152640 0017543 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager;
/**
* Backwards-compatibility shim for DelegatorFactoryInterface.
*
* Implementations should update to implement only Laminas\ServiceManager\Factory\DelegatorFactoryInterface.
*
* If upgrading from v2, take the following steps:
*
* - rename the method `createDelegatorWithName()` to `__invoke()`, and:
* - rename the `$serviceLocator` argument to `$container`, and change the
* typehint to `Psr\Container\ContainerInterface`
* - merge the `$name` and `$requestedName` arguments
* - add the `callable` typehint to the `$callback` argument
* - add the optional `array $options = null` argument as a final argument
* - create a `createDelegatorWithName()` method as defined in this interface, and have it
* proxy to `__invoke()`, passing `$requestedName` as the second argument.
*
* Once you have tested your code, you can then update your class to only implement
* Laminas\ServiceManager\Factory\DelegatorFactoryInterface, and remove the `createDelegatorWithName()`
* method.
*
* @deprecated Use Laminas\ServiceManager\Factory\DelegatorFactoryInterface instead.
*/
interface DelegatorFactoryInterface extends Factory\DelegatorFactoryInterface
{
/**
* A factory that creates delegates of a given service
*
* @param ServiceLocatorInterface $serviceLocator the service locator which requested the service
* @param string $name the normalized service name
* @param string $requestedName the requested service name
* @param callable $callback the callback that is responsible for creating the service
* @return mixed
*/
public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback);
}
laminas-servicemanager/src/PluginManagerInterface.php 0000644 00000001416 15240152640 0017034 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager;
use Laminas\ServiceManager\Exception\InvalidServiceException;
use Psr\Container\ContainerExceptionInterface;
/**
* Interface for a plugin manager
*
* A plugin manager is a specialized service locator used to create homogeneous objects
*
* @template InstanceType
*/
interface PluginManagerInterface extends ServiceLocatorInterface
{
/**
* Validate an instance
*
* @return void
* @throws InvalidServiceException If created instance does not respect the
* constraint on type imposed by the plugin manager.
* @throws ContainerExceptionInterface If any other error occurs.
* @psalm-assert InstanceType $instance
*/
public function validate(mixed $instance);
}
laminas-servicemanager/src/FactoryInterface.php 0000644 00000002247 15240152640 0015715 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\ServiceManager;
/**
* Backwards-compatibility shim for FactoryInterface.
*
* Implementations should update to implement only Laminas\ServiceManager\Factory\FactoryInterface.
*
* If upgrading from v2, take the following steps:
*
* - rename the method `createService()` to `__invoke()`, and:
* - rename the `$serviceLocator` argument to `$container`, and change the
* typehint to `Psr\Container\ContainerInterface`
* - add the `$requestedName` as a second argument
* - add the optional `array $options = null` argument as a final argument
* - create a `createService()` method as defined in this interface, and have it
* proxy to `__invoke()`.
*
* Once you have tested your code, you can then update your class to only implement
* Laminas\ServiceManager\Factory\FactoryInterface, and remove the `createService()`
* method.
*
* @deprecated Use Laminas\ServiceManager\Factory\FactoryInterface instead.
*/
interface FactoryInterface extends Factory\FactoryInterface
{
/**
* Create service
*
* @return mixed
*/
public function createService(ServiceLocatorInterface $serviceLocator);
}
laminas-servicemanager/README.md 0000644 00000007272 15240152640 0012447 0 ustar 00 # laminas-servicemanager
[](https://github.com/laminas/laminas-servicemanager/actions/workflows/continuous-integration.yml)
[](https://shepherd.dev/github/laminas/laminas-servicemanager)
> ## 🇷🇺 Русским гражданам
>
> Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм.
>
> У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую.
>
> Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!"
>
> ## 🇺🇸 To Citizens of Russia
>
> We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism.
>
> One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences.
>
> You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!"
The Service Locator design pattern is implemented by the `Laminas\ServiceManager`
component. The Service Locator is a service/object locator, tasked with
retrieving other objects.
- File issues at https://github.com/laminas/laminas-servicemanager/issues
- [Online documentation](https://docs.laminas.dev/laminas-servicemanager)
- [Documentation source files](docs/book/)
## Benchmarks
We provide scripts for benchmarking laminas-servicemanager using the
[PHPBench](https://github.com/phpbench/phpbench) framework; these can be
found in the `benchmarks/` directory.
To execute the benchmarks you can run the following command:
```bash
$ vendor/bin/phpbench run --report=aggregate
```
laminas-servicemanager/composer.json 0000644 00000006044 15240152640 0013706 0 ustar 00 {
"name": "laminas/laminas-servicemanager",
"description": "Factory-Driven Dependency Injection Container",
"license": "BSD-3-Clause",
"keywords": [
"laminas",
"di",
"dic",
"dependency-injection",
"psr-11",
"servicemanager",
"service-manager"
],
"homepage": "https://laminas.dev",
"support": {
"docs": "https://docs.laminas.dev/laminas-servicemanager/",
"issues": "https://github.com/laminas/laminas-servicemanager/issues",
"source": "https://github.com/laminas/laminas-servicemanager",
"rss": "https://github.com/laminas/laminas-servicemanager/releases.atom",
"chat": "https://laminas.dev/chat",
"forum": "https://discourse.laminas.dev"
},
"config": {
"platform": {
"php": "8.0.99"
},
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true,
"composer/package-versions-deprecated": true,
"laminas/laminas-dependency-plugin": true
}
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"laminas/laminas-stdlib": "^3.2.1",
"psr/container": "^1.0"
},
"require-dev": {
"composer/package-versions-deprecated": "^1.11.99.5",
"laminas/laminas-coding-standard": "~2.4.0",
"laminas/laminas-container-config-test": "^0.7",
"laminas/laminas-dependency-plugin": "^2.2",
"mikey179/vfsstream": "^1.6.11@alpha",
"ocramius/proxy-manager": "^2.14.1",
"phpbench/phpbench": "^1.2.6",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.28"
},
"provide": {
"psr/container-implementation": "^1.0"
},
"conflict": {
"ext-psr": "*",
"laminas/laminas-code": "<3.3.1",
"zendframework/zend-code": "<3.3.1",
"zendframework/zend-servicemanager": "*"
},
"suggest": {
"ocramius/proxy-manager": "ProxyManager ^2.1.1 to handle lazy initialization of services"
},
"autoload": {
"psr-4": {
"Laminas\\ServiceManager\\": "src/"
},
"files": ["src/autoload.php"]
},
"autoload-dev": {
"files": [
"test/autoload.php"
],
"psr-4": {
"LaminasTest\\ServiceManager\\": "test/",
"LaminasBench\\ServiceManager\\": "benchmarks/"
}
},
"bin": [
"bin/generate-deps-for-config-factory",
"bin/generate-factory-for-class"
],
"scripts": {
"benchmark": "phpbench run --revs=2 --iterations=2 --report=aggregate",
"check": [
"@cs-check",
"@test"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml",
"static-analysis" : "psalm --shepherd --stats"
},
"replace": {
"container-interop/container-interop": "^1.2.0"
}
}
laminas-servicemanager/COPYRIGHT.md 0000644 00000000133 15240152640 0013047 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/)
laminas-servicemanager/composer.lock 0000644 00000563026 15240152640 0013675 0 ustar 00 {
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "14aa91cb32d02c98d71bd10bb1a32057",
"packages": [
{
"name": "laminas/laminas-stdlib",
"version": "3.14.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-stdlib.git",
"reference": "627e06f1d1ac276fd4c6f78407ce3d72db341a30"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/627e06f1d1ac276fd4c6f78407ce3d72db341a30",
"reference": "627e06f1d1ac276fd4c6f78407ce3d72db341a30",
"shasum": ""
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-stdlib": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "^2.4.0",
"phpbench/phpbench": "^1.2.6",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.28"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Stdlib\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "SPL extensions, array utilities, error handlers, and more",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"stdlib"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-stdlib/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-stdlib/issues",
"rss": "https://github.com/laminas/laminas-stdlib/releases.atom",
"source": "https://github.com/laminas/laminas-stdlib"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-10T13:20:55+00:00"
},
{
"name": "psr/container",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
"shasum": ""
},
"require": {
"php": ">=7.4.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
"homepage": "https://github.com/php-fig/container",
"keywords": [
"PSR-11",
"container",
"container-interface",
"container-interop",
"psr"
],
"support": {
"issues": "https://github.com/php-fig/container/issues",
"source": "https://github.com/php-fig/container/tree/1.1.2"
},
"time": "2021-11-05T16:50:12+00:00"
}
],
"packages-dev": [
{
"name": "amphp/amp",
"version": "v2.6.2",
"source": {
"type": "git",
"url": "https://github.com/amphp/amp.git",
"reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb",
"reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"amphp/php-cs-fixer-config": "dev-master",
"amphp/phpunit-util": "^1",
"ext-json": "*",
"jetbrains/phpstorm-stubs": "^2019.3",
"phpunit/phpunit": "^7 | ^8 | ^9",
"psalm/phar": "^3.11@dev",
"react/promise": "^2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
},
"autoload": {
"files": [
"lib/functions.php",
"lib/Internal/functions.php"
],
"psr-4": {
"Amp\\": "lib"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Daniel Lowrey",
"email": "rdlowrey@php.net"
},
{
"name": "Aaron Piotrowski",
"email": "aaron@trowski.com"
},
{
"name": "Bob Weinand",
"email": "bobwei9@hotmail.com"
},
{
"name": "Niklas Keller",
"email": "me@kelunik.com"
}
],
"description": "A non-blocking concurrency framework for PHP applications.",
"homepage": "https://amphp.org/amp",
"keywords": [
"async",
"asynchronous",
"awaitable",
"concurrency",
"event",
"event-loop",
"future",
"non-blocking",
"promise"
],
"support": {
"irc": "irc://irc.freenode.org/amphp",
"issues": "https://github.com/amphp/amp/issues",
"source": "https://github.com/amphp/amp/tree/v2.6.2"
},
"funding": [
{
"url": "https://github.com/amphp",
"type": "github"
}
],
"time": "2022-02-20T17:52:18+00:00"
},
{
"name": "amphp/byte-stream",
"version": "v1.8.1",
"source": {
"type": "git",
"url": "https://github.com/amphp/byte-stream.git",
"reference": "acbd8002b3536485c997c4e019206b3f10ca15bd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd",
"reference": "acbd8002b3536485c997c4e019206b3f10ca15bd",
"shasum": ""
},
"require": {
"amphp/amp": "^2",
"php": ">=7.1"
},
"require-dev": {
"amphp/php-cs-fixer-config": "dev-master",
"amphp/phpunit-util": "^1.4",
"friendsofphp/php-cs-fixer": "^2.3",
"jetbrains/phpstorm-stubs": "^2019.3",
"phpunit/phpunit": "^6 || ^7 || ^8",
"psalm/phar": "^3.11.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"files": [
"lib/functions.php"
],
"psr-4": {
"Amp\\ByteStream\\": "lib"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Aaron Piotrowski",
"email": "aaron@trowski.com"
},
{
"name": "Niklas Keller",
"email": "me@kelunik.com"
}
],
"description": "A stream abstraction to make working with non-blocking I/O simple.",
"homepage": "http://amphp.org/byte-stream",
"keywords": [
"amp",
"amphp",
"async",
"io",
"non-blocking",
"stream"
],
"support": {
"irc": "irc://irc.freenode.org/amphp",
"issues": "https://github.com/amphp/byte-stream/issues",
"source": "https://github.com/amphp/byte-stream/tree/v1.8.1"
},
"funding": [
{
"url": "https://github.com/amphp",
"type": "github"
}
],
"time": "2021-03-30T17:13:30+00:00"
},
{
"name": "composer/package-versions-deprecated",
"version": "1.11.99.5",
"source": {
"type": "git",
"url": "https://github.com/composer/package-versions-deprecated.git",
"reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d",
"reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.1.0 || ^2.0",
"php": "^7 || ^8"
},
"replace": {
"ocramius/package-versions": "1.11.99"
},
"require-dev": {
"composer/composer": "^1.9.3 || ^2.0@dev",
"ext-zip": "^1.13",
"phpunit/phpunit": "^6.5 || ^7"
},
"type": "composer-plugin",
"extra": {
"class": "PackageVersions\\Installer",
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"PackageVersions\\": "src/PackageVersions"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be"
}
],
"description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
"support": {
"issues": "https://github.com/composer/package-versions-deprecated/issues",
"source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-01-17T14:14:24+00:00"
},
{
"name": "composer/pcre",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
"reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/e300eb6c535192decd27a85bc72a9290f0d6b3bd",
"reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1.3",
"phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Pcre\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "PCRE wrapping library that offers type-safe preg_* replacements.",
"keywords": [
"PCRE",
"preg",
"regex",
"regular expression"
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.0.0"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-02-25T20:21:48+00:00"
},
{
"name": "composer/semver",
"version": "3.3.2",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1.4",
"symfony/phpunit-bridge": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Semver\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
},
{
"name": "Rob Bast",
"email": "rob.bast@gmail.com",
"homepage": "http://robbast.nl"
}
],
"description": "Semver library that offers utilities, version constraint parsing and validation.",
"keywords": [
"semantic",
"semver",
"validation",
"versioning"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.3.2"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-04-01T19:23:25+00:00"
},
{
"name": "composer/xdebug-handler",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
"reference": "ced299686f41dce890debac69273b47ffe98a40c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c",
"reference": "ced299686f41dce890debac69273b47ffe98a40c",
"shasum": ""
},
"require": {
"composer/pcre": "^1 || ^2 || ^3",
"php": "^7.2.5 || ^8.0",
"psr/log": "^1 || ^2 || ^3"
},
"require-dev": {
"phpstan/phpstan": "^1.0",
"phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Composer\\XdebugHandler\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "John Stevenson",
"email": "john-stevenson@blueyonder.co.uk"
}
],
"description": "Restarts a process without Xdebug.",
"keywords": [
"Xdebug",
"performance"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/xdebug-handler/issues",
"source": "https://github.com/composer/xdebug-handler/tree/3.0.3"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-02-25T21:32:43+00:00"
},
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
"version": "v0.7.2",
"source": {
"type": "git",
"url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
"phpcompatibility/php-compatibility": "^9.0"
},
"type": "composer-plugin",
"extra": {
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
"Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Franck Nijhof",
"email": "franck.nijhof@dealerdirect.com",
"homepage": "http://www.frenck.nl",
"role": "Developer / IT Manager"
},
{
"name": "Contributors",
"homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
"homepage": "http://www.dealerdirect.com",
"keywords": [
"PHPCodeSniffer",
"PHP_CodeSniffer",
"code quality",
"codesniffer",
"composer",
"installer",
"phpcbf",
"phpcs",
"plugin",
"qa",
"quality",
"standard",
"standards",
"style guide",
"stylecheck",
"tests"
],
"support": {
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
"time": "2022-02-04T12:51:07+00:00"
},
{
"name": "dnoegel/php-xdg-base-dir",
"version": "v0.1.1",
"source": {
"type": "git",
"url": "https://github.com/dnoegel/php-xdg-base-dir.git",
"reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd",
"reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"require-dev": {
"phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35"
},
"type": "library",
"autoload": {
"psr-4": {
"XdgBaseDir\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "implementation of xdg base directory specification for php",
"support": {
"issues": "https://github.com/dnoegel/php-xdg-base-dir/issues",
"source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1"
},
"time": "2019-12-04T15:06:13+00:00"
},
{
"name": "doctrine/annotations",
"version": "1.13.3",
"source": {
"type": "git",
"url": "https://github.com/doctrine/annotations.git",
"reference": "648b0343343565c4a056bfc8392201385e8d89f0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/648b0343343565c4a056bfc8392201385e8d89f0",
"reference": "648b0343343565c4a056bfc8392201385e8d89f0",
"shasum": ""
},
"require": {
"doctrine/lexer": "1.*",
"ext-tokenizer": "*",
"php": "^7.1 || ^8.0",
"psr/cache": "^1 || ^2 || ^3"
},
"require-dev": {
"doctrine/cache": "^1.11 || ^2.0",
"doctrine/coding-standard": "^6.0 || ^8.1",
"phpstan/phpstan": "^1.4.10 || ^1.8.0",
"phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5",
"symfony/cache": "^4.4 || ^5.2",
"vimeo/psalm": "^4.10"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Docblock Annotations Parser",
"homepage": "https://www.doctrine-project.org/projects/annotations.html",
"keywords": [
"annotations",
"docblock",
"parser"
],
"support": {
"issues": "https://github.com/doctrine/annotations/issues",
"source": "https://github.com/doctrine/annotations/tree/1.13.3"
},
"time": "2022-07-02T10:48:51+00:00"
},
{
"name": "doctrine/instantiator",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9",
"ext-pdo": "*",
"ext-phar": "*",
"phpbench/phpbench": "^0.16 || ^1",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-phpunit": "^1",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"vimeo/psalm": "^4.22"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "https://ocramius.github.io/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://www.doctrine-project.org/projects/instantiator.html",
"keywords": [
"constructor",
"instantiate"
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/1.4.1"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
"type": "tidelift"
}
],
"time": "2022-03-03T08:28:38+00:00"
},
{
"name": "doctrine/lexer",
"version": "1.2.3",
"source": {
"type": "git",
"url": "https://github.com/doctrine/lexer.git",
"reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229",
"reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9.0",
"phpstan/phpstan": "^1.3",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"vimeo/psalm": "^4.11"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
"homepage": "https://www.doctrine-project.org/projects/lexer.html",
"keywords": [
"annotations",
"docblock",
"lexer",
"parser",
"php"
],
"support": {
"issues": "https://github.com/doctrine/lexer/issues",
"source": "https://github.com/doctrine/lexer/tree/1.2.3"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer",
"type": "tidelift"
}
],
"time": "2022-02-28T11:07:21+00:00"
},
{
"name": "felixfbecker/advanced-json-rpc",
"version": "v3.2.1",
"source": {
"type": "git",
"url": "https://github.com/felixfbecker/php-advanced-json-rpc.git",
"reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447",
"reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447",
"shasum": ""
},
"require": {
"netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0",
"php": "^7.1 || ^8.0",
"phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0"
},
"require-dev": {
"phpunit/phpunit": "^7.0 || ^8.0"
},
"type": "library",
"autoload": {
"psr-4": {
"AdvancedJsonRpc\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"ISC"
],
"authors": [
{
"name": "Felix Becker",
"email": "felix.b@outlook.com"
}
],
"description": "A more advanced JSONRPC implementation",
"support": {
"issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues",
"source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1"
},
"time": "2021-06-11T22:34:44+00:00"
},
{
"name": "felixfbecker/language-server-protocol",
"version": "v1.5.2",
"source": {
"type": "git",
"url": "https://github.com/felixfbecker/php-language-server-protocol.git",
"reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842",
"reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"phpstan/phpstan": "*",
"squizlabs/php_codesniffer": "^3.1",
"vimeo/psalm": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"LanguageServerProtocol\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"ISC"
],
"authors": [
{
"name": "Felix Becker",
"email": "felix.b@outlook.com"
}
],
"description": "PHP classes for the Language Server Protocol",
"keywords": [
"language",
"microsoft",
"php",
"server"
],
"support": {
"issues": "https://github.com/felixfbecker/php-language-server-protocol/issues",
"source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2"
},
"time": "2022-03-02T22:36:06+00:00"
},
{
"name": "laminas/laminas-code",
"version": "4.7.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-code.git",
"reference": "0337d9265bc2e6376babad8c511500821620cb30"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-code/zipball/0337d9265bc2e6376babad8c511500821620cb30",
"reference": "0337d9265bc2e6376babad8c511500821620cb30",
"shasum": ""
},
"require": {
"php": ">=7.4, <8.2"
},
"require-dev": {
"doctrine/annotations": "^1.13.2",
"ext-phar": "*",
"laminas/laminas-coding-standard": "^2.3.0",
"laminas/laminas-stdlib": "^3.6.1",
"phpunit/phpunit": "^9.5.10",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.13.1"
},
"suggest": {
"doctrine/annotations": "Doctrine\\Common\\Annotations >=1.0 for annotation features",
"laminas/laminas-stdlib": "Laminas\\Stdlib component"
},
"type": "library",
"autoload": {
"files": [
"polyfill/ReflectionEnumPolyfill.php"
],
"psr-4": {
"Laminas\\Code\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Extensions to the PHP Reflection API, static code scanning, and code generation",
"homepage": "https://laminas.dev",
"keywords": [
"code",
"laminas",
"laminasframework"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-code/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-code/issues",
"rss": "https://github.com/laminas/laminas-code/releases.atom",
"source": "https://github.com/laminas/laminas-code"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-09-13T10:33:30+00:00"
},
{
"name": "laminas/laminas-coding-standard",
"version": "2.4.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-coding-standard.git",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7",
"php": "^7.4 || ^8.0",
"slevomat/coding-standard": "^7.0",
"squizlabs/php_codesniffer": "^3.6",
"webimpress/coding-standard": "^1.2"
},
"conflict": {
"phpstan/phpdoc-parser": ">=1.6.0"
},
"type": "phpcodesniffer-standard",
"autoload": {
"psr-4": {
"LaminasCodingStandard\\": "src/LaminasCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Laminas Coding Standard",
"homepage": "https://laminas.dev",
"keywords": [
"Coding Standard",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-coding-standard/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-coding-standard/issues",
"rss": "https://github.com/laminas/laminas-coding-standard/releases.atom",
"source": "https://github.com/laminas/laminas-coding-standard"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-08-24T17:45:47+00:00"
},
{
"name": "laminas/laminas-container-config-test",
"version": "0.7.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-container-config-test.git",
"reference": "799bbd667c25bf5b88ff879be2ac0e33a5a15185"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-container-config-test/zipball/799bbd667c25bf5b88ff879be2ac0e33a5a15185",
"reference": "799bbd667c25bf5b88ff879be2ac0e33a5a15185",
"shasum": ""
},
"require": {
"php": "^7.4 || ~8.0.0 || ~8.1.0",
"psr/container": "^1.0 || ^2.0"
},
"conflict": {
"zendframework/zend-container-config-test": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "^2.3",
"phpunit/phpunit": "^9.5.21",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.24.0"
},
"type": "library",
"autoload": {
"files": [
"src/TestAsset/function-factory.php",
"src/TestAsset/function-factory-with-name.php",
"src/TestAsset/function-factory.legacy.php",
"src/TestAsset/function-factory-with-name.legacy.php"
],
"psr-4": {
"Laminas\\ContainerConfigTest\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Mezzio PSR-11 container configuration tests",
"homepage": "https://laminas.dev",
"keywords": [
"PSR-11",
"container",
"laminas",
"mezzio",
"test"
],
"support": {
"chat": "https://laminas.dev/chat",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-container-config-test/issues",
"rss": "https://github.com/laminas/laminas-container-config-test/releases.atom",
"source": "https://github.com/laminas/laminas-container-config-test"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-07-24T20:30:12+00:00"
},
{
"name": "laminas/laminas-dependency-plugin",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-dependency-plugin.git",
"reference": "73cfb63ddca9d6bfedad5e0a038f6d55063975a3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-dependency-plugin/zipball/73cfb63ddca9d6bfedad5e0a038f6d55063975a3",
"reference": "73cfb63ddca9d6bfedad5e0a038f6d55063975a3",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.1 || ^2.0",
"php": "^7.3 || ~8.0.0 || ~8.1.0"
},
"require-dev": {
"composer/composer": "^1.9 || ^2.0",
"laminas/laminas-coding-standard": "^2.2.1",
"mikey179/vfsstream": "^1.6.10@alpha",
"phpunit/phpunit": "^9.5.5",
"psalm/plugin-phpunit": "^0.15.1",
"roave/security-advisories": "dev-master",
"vimeo/psalm": "^4.5"
},
"type": "composer-plugin",
"extra": {
"class": "Laminas\\DependencyPlugin\\DependencyRewriterPluginDelegator"
},
"autoload": {
"psr-4": {
"Laminas\\DependencyPlugin\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Replace zendframework and zfcampus packages with their Laminas Project equivalents.",
"support": {
"issues": "https://github.com/laminas/laminas-dependency-plugin/issues",
"source": "https://github.com/laminas/laminas-dependency-plugin/tree/2.2.0"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2021-09-08T17:51:35+00:00"
},
{
"name": "mikey179/vfsstream",
"version": "v1.6.11",
"source": {
"type": "git",
"url": "https://github.com/bovigo/vfsStream.git",
"reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bovigo/vfsStream/zipball/17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f",
"reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "^4.5|^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6.x-dev"
}
},
"autoload": {
"psr-0": {
"org\\bovigo\\vfs\\": "src/main/php"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Frank Kleine",
"homepage": "http://frankkleine.de/",
"role": "Developer"
}
],
"description": "Virtual file system to mock the real file system in unit tests.",
"homepage": "http://vfs.bovigo.org/",
"support": {
"issues": "https://github.com/bovigo/vfsStream/issues",
"source": "https://github.com/bovigo/vfsStream/tree/master",
"wiki": "https://github.com/bovigo/vfsStream/wiki"
},
"time": "2022-02-23T02:02:42+00:00"
},
{
"name": "myclabs/deep-copy",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"conflict": {
"doctrine/collections": "<1.6.8",
"doctrine/common": "<2.13.3 || >=3,<3.2.2"
},
"require-dev": {
"doctrine/collections": "^1.6.8",
"doctrine/common": "^2.13.3 || ^3.2.2",
"phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
},
"type": "library",
"autoload": {
"files": [
"src/DeepCopy/deep_copy.php"
],
"psr-4": {
"DeepCopy\\": "src/DeepCopy/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Create deep copies (clones) of your objects",
"keywords": [
"clone",
"copy",
"duplicate",
"object",
"object graph"
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
},
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
"type": "tidelift"
}
],
"time": "2022-03-03T13:19:32+00:00"
},
{
"name": "netresearch/jsonmapper",
"version": "v4.0.0",
"source": {
"type": "git",
"url": "https://github.com/cweiske/jsonmapper.git",
"reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
"reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-pcre": "*",
"ext-reflection": "*",
"ext-spl": "*",
"php": ">=7.1"
},
"require-dev": {
"phpunit/phpunit": "~7.5 || ~8.0 || ~9.0",
"squizlabs/php_codesniffer": "~3.5"
},
"type": "library",
"autoload": {
"psr-0": {
"JsonMapper": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"OSL-3.0"
],
"authors": [
{
"name": "Christian Weiske",
"email": "cweiske@cweiske.de",
"homepage": "http://github.com/cweiske/jsonmapper/",
"role": "Developer"
}
],
"description": "Map nested JSON structures onto PHP classes",
"support": {
"email": "cweiske@cweiske.de",
"issues": "https://github.com/cweiske/jsonmapper/issues",
"source": "https://github.com/cweiske/jsonmapper/tree/v4.0.0"
},
"time": "2020-12-01T19:48:11+00:00"
},
{
"name": "nikic/php-parser",
"version": "v4.15.1",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=7.0"
},
"require-dev": {
"ircmaxell/php-yacc": "^0.0.7",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
},
"bin": [
"bin/php-parse"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.9-dev"
}
},
"autoload": {
"psr-4": {
"PhpParser\\": "lib/PhpParser"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov"
}
],
"description": "A PHP parser written in PHP",
"keywords": [
"parser",
"php"
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1"
},
"time": "2022-09-04T07:30:47+00:00"
},
{
"name": "ocramius/proxy-manager",
"version": "2.14.1",
"source": {
"type": "git",
"url": "https://github.com/Ocramius/ProxyManager.git",
"reference": "3990d60ef79001badbab4927a6a811682274a0d1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Ocramius/ProxyManager/zipball/3990d60ef79001badbab4927a6a811682274a0d1",
"reference": "3990d60ef79001badbab4927a6a811682274a0d1",
"shasum": ""
},
"require": {
"composer-runtime-api": "^2.1.0",
"laminas/laminas-code": "^4.4.2",
"php": "~8.0.0",
"webimpress/safe-writer": "^2.2.0"
},
"conflict": {
"thecodingmachine/safe": "<1.3.3"
},
"require-dev": {
"codelicia/xulieta": "^0.1.6",
"doctrine/coding-standard": "^9.0.0",
"ext-phar": "*",
"phpbench/phpbench": "^1.0.3",
"phpunit/phpunit": "^9.5.6",
"roave/infection-static-analysis-plugin": "^1.8",
"squizlabs/php_codesniffer": "^3.6.0",
"vimeo/psalm": "^4.8.1"
},
"suggest": {
"laminas/laminas-json": "To have the JsonRpc adapter (Remote Object feature)",
"laminas/laminas-soap": "To have the Soap adapter (Remote Object feature)",
"laminas/laminas-xmlrpc": "To have the XmlRpc adapter (Remote Object feature)",
"ocramius/generated-hydrator": "To have very fast object to array to object conversion for ghost objects"
},
"type": "library",
"autoload": {
"psr-4": {
"ProxyManager\\": "src/ProxyManager"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "https://ocramius.github.io/"
}
],
"description": "A library providing utilities to generate, instantiate and generally operate with Object Proxies",
"homepage": "https://github.com/Ocramius/ProxyManager",
"keywords": [
"aop",
"lazy loading",
"proxy",
"proxy pattern",
"service proxies"
],
"support": {
"issues": "https://github.com/Ocramius/ProxyManager/issues",
"source": "https://github.com/Ocramius/ProxyManager/tree/2.14.1"
},
"funding": [
{
"url": "https://github.com/Ocramius",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/ocramius/proxy-manager",
"type": "tidelift"
}
],
"time": "2022-03-05T18:43:14+00:00"
},
{
"name": "openlss/lib-array2xml",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/nullivex/lib-array2xml.git",
"reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90",
"reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"type": "library",
"autoload": {
"psr-0": {
"LSS": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Bryan Tong",
"email": "bryan@nullivex.com",
"homepage": "https://www.nullivex.com"
},
{
"name": "Tony Butler",
"email": "spudz76@gmail.com",
"homepage": "https://www.nullivex.com"
}
],
"description": "Array2XML conversion library credit to lalit.org",
"homepage": "https://www.nullivex.com",
"keywords": [
"array",
"array conversion",
"xml",
"xml conversion"
],
"support": {
"issues": "https://github.com/nullivex/lib-array2xml/issues",
"source": "https://github.com/nullivex/lib-array2xml/tree/master"
},
"time": "2019-03-29T20:06:56+00:00"
},
{
"name": "phar-io/manifest",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-phar": "*",
"ext-xmlwriter": "*",
"phar-io/version": "^3.0.1",
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
"support": {
"issues": "https://github.com/phar-io/manifest/issues",
"source": "https://github.com/phar-io/manifest/tree/2.0.3"
},
"time": "2021-07-20T11:28:43+00:00"
},
{
"name": "phar-io/version",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/phar-io/version.git",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Library for handling version information and constraints",
"support": {
"issues": "https://github.com/phar-io/version/issues",
"source": "https://github.com/phar-io/version/tree/3.2.1"
},
"time": "2022-02-21T01:04:05+00:00"
},
{
"name": "phpbench/container",
"version": "2.2.1",
"source": {
"type": "git",
"url": "https://github.com/phpbench/container.git",
"reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpbench/container/zipball/6d555ff7174fca13f9b1ec0b4a089ed41d0ab392",
"reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392",
"shasum": ""
},
"require": {
"psr/container": "^1.0|^2.0",
"symfony/options-resolver": "^4.2 || ^5.0 || ^6.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.16",
"phpstan/phpstan": "^0.12.52",
"phpunit/phpunit": "^8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
},
"autoload": {
"psr-4": {
"PhpBench\\DependencyInjection\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Daniel Leech",
"email": "daniel@dantleech.com"
}
],
"description": "Simple, configurable, service container.",
"support": {
"issues": "https://github.com/phpbench/container/issues",
"source": "https://github.com/phpbench/container/tree/2.2.1"
},
"time": "2022-01-25T10:17:35+00:00"
},
{
"name": "phpbench/dom",
"version": "0.3.2",
"source": {
"type": "git",
"url": "https://github.com/phpbench/dom.git",
"reference": "b013b717832ddbaadf2a40984b04bc66af9a7110"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpbench/dom/zipball/b013b717832ddbaadf2a40984b04bc66af9a7110",
"reference": "b013b717832ddbaadf2a40984b04bc66af9a7110",
"shasum": ""
},
"require": {
"ext-dom": "*",
"php": "^7.2||^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.18",
"phpstan/phpstan": "^0.12.83",
"phpunit/phpunit": "^8.0||^9.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"PhpBench\\Dom\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Daniel Leech",
"email": "daniel@dantleech.com"
}
],
"description": "DOM wrapper to simplify working with the PHP DOM implementation",
"support": {
"issues": "https://github.com/phpbench/dom/issues",
"source": "https://github.com/phpbench/dom/tree/0.3.2"
},
"time": "2021-09-24T15:26:07+00:00"
},
{
"name": "phpbench/phpbench",
"version": "1.2.6",
"source": {
"type": "git",
"url": "https://github.com/phpbench/phpbench.git",
"reference": "c30fac992e72b505a1f131790583647f4d3255c3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpbench/phpbench/zipball/c30fac992e72b505a1f131790583647f4d3255c3",
"reference": "c30fac992e72b505a1f131790583647f4d3255c3",
"shasum": ""
},
"require": {
"doctrine/annotations": "^1.13",
"ext-dom": "*",
"ext-json": "*",
"ext-pcre": "*",
"ext-reflection": "*",
"ext-spl": "*",
"ext-tokenizer": "*",
"php": "^7.3 || ^8.0",
"phpbench/container": "^2.1",
"phpbench/dom": "~0.3.1",
"psr/log": "^1.1 || ^2.0 || ^3.0",
"seld/jsonlint": "^1.1",
"symfony/console": "^4.2 || ^5.0 || ^6.0",
"symfony/filesystem": "^4.2 || ^5.0 || ^6.0",
"symfony/finder": "^4.2 || ^5.0 || ^6.0",
"symfony/options-resolver": "^4.2 || ^5.0 || ^6.0",
"symfony/process": "^4.2 || ^5.0 || ^6.0",
"webmozart/path-util": "^2.3"
},
"require-dev": {
"dantleech/invoke": "^2.0",
"friendsofphp/php-cs-fixer": "^3.0",
"jangregor/phpstan-prophecy": "^0.8.1",
"phpspec/prophecy": "^1.12",
"phpstan/phpstan": "^0.12.7",
"phpunit/phpunit": "^8.5.8 || ^9.0",
"symfony/error-handler": "^5.2 || ^6.0",
"symfony/var-dumper": "^4.0 || ^5.0 || ^6.0"
},
"suggest": {
"ext-xdebug": "For Xdebug profiling extension."
},
"bin": [
"bin/phpbench"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2-dev"
}
},
"autoload": {
"files": [
"lib/Report/Func/functions.php"
],
"psr-4": {
"PhpBench\\": "lib/",
"PhpBench\\Extensions\\XDebug\\": "extensions/xdebug/lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Daniel Leech",
"email": "daniel@dantleech.com"
}
],
"description": "PHP Benchmarking Framework",
"support": {
"issues": "https://github.com/phpbench/phpbench/issues",
"source": "https://github.com/phpbench/phpbench/tree/1.2.6"
},
"funding": [
{
"url": "https://github.com/dantleech",
"type": "github"
}
],
"time": "2022-07-19T19:52:39+00:00"
},
{
"name": "phpdocumentor/reflection-common",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-2.x": "2.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jaap van Otterdijk",
"email": "opensource@ijaap.nl"
}
],
"description": "Common reflection classes used by phpdocumentor to reflect the code structure",
"homepage": "http://www.phpdoc.org",
"keywords": [
"FQSEN",
"phpDocumentor",
"phpdoc",
"reflection",
"static analysis"
],
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
"source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x"
},
"time": "2020-06-27T09:03:43+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "5.3.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "622548b623e81ca6d78b721c5e029f4ce664f170"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170",
"reference": "622548b623e81ca6d78b721c5e029f4ce664f170",
"shasum": ""
},
"require": {
"ext-filter": "*",
"php": "^7.2 || ^8.0",
"phpdocumentor/reflection-common": "^2.2",
"phpdocumentor/type-resolver": "^1.3",
"webmozart/assert": "^1.9.1"
},
"require-dev": {
"mockery/mockery": "~1.3.2",
"psalm/phar": "^4.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
},
{
"name": "Jaap van Otterdijk",
"email": "account@ijaap.nl"
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0"
},
"time": "2021-10-19T17:43:47+00:00"
},
{
"name": "phpdocumentor/type-resolver",
"version": "1.6.1",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "77a32518733312af16a44300404e945338981de3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3",
"reference": "77a32518733312af16a44300404e945338981de3",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
"phpdocumentor/reflection-common": "^2.0"
},
"require-dev": {
"ext-tokenizer": "*",
"psalm/phar": "^4.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-1.x": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
}
],
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"support": {
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1"
},
"time": "2022-03-15T21:29:03+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "981cc368a216c988e862a75e526b6076987d1b50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/981cc368a216c988e862a75e526b6076987d1b50",
"reference": "981cc368a216c988e862a75e526b6076987d1b50",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.5.1"
},
"time": "2022-05-05T11:32:40+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.17",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
"nikic/php-parser": "^4.14",
"php": ">=7.3",
"phpunit/php-file-iterator": "^3.0.3",
"phpunit/php-text-template": "^2.0.2",
"sebastian/code-unit-reverse-lookup": "^2.0.2",
"sebastian/complexity": "^2.0",
"sebastian/environment": "^5.1.2",
"sebastian/lines-of-code": "^1.0.3",
"sebastian/version": "^3.0.1",
"theseer/tokenizer": "^1.2.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcov": "*",
"ext-xdebug": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-08-30T12:24:04+00:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "3.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2021-12-02T12:48:52+00:00"
},
{
"name": "phpunit/php-invoker",
"version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-invoker.git",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"ext-pcntl": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcntl": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Invoke callables with a timeout",
"homepage": "https://github.com/sebastianbergmann/php-invoker/",
"keywords": [
"process"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-invoker/issues",
"source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:58:55+00:00"
},
{
"name": "phpunit/php-text-template",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
"source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T05:33:50+00:00"
},
{
"name": "phpunit/php-timer",
"version": "5.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-timer/issues",
"source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:16:10+00:00"
},
{
"name": "phpunit/phpunit",
"version": "9.5.25",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
"reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.3.1",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
"myclabs/deep-copy": "^1.10.1",
"phar-io/manifest": "^2.0.3",
"phar-io/version": "^3.0.2",
"php": ">=7.3",
"phpunit/php-code-coverage": "^9.2.13",
"phpunit/php-file-iterator": "^3.0.5",
"phpunit/php-invoker": "^3.1.1",
"phpunit/php-text-template": "^2.0.3",
"phpunit/php-timer": "^5.0.2",
"sebastian/cli-parser": "^1.0.1",
"sebastian/code-unit": "^1.0.6",
"sebastian/comparator": "^4.0.8",
"sebastian/diff": "^4.0.3",
"sebastian/environment": "^5.1.3",
"sebastian/exporter": "^4.0.5",
"sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3",
"sebastian/type": "^3.2",
"sebastian/version": "^3.0.2"
},
"suggest": {
"ext-soap": "*",
"ext-xdebug": "*"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.5-dev"
}
},
"autoload": {
"files": [
"src/Framework/Assert/Functions.php"
],
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.25"
},
"funding": [
{
"url": "https://phpunit.de/sponsors.html",
"type": "custom"
},
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
"type": "tidelift"
}
],
"time": "2022-09-25T03:44:45+00:00"
},
{
"name": "psalm/plugin-phpunit",
"version": "0.17.0",
"source": {
"type": "git",
"url": "https://github.com/psalm/psalm-plugin-phpunit.git",
"reference": "45951541beef07e93e3ad197daf01da88e85c31d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/psalm/psalm-plugin-phpunit/zipball/45951541beef07e93e3ad197daf01da88e85c31d",
"reference": "45951541beef07e93e3ad197daf01da88e85c31d",
"shasum": ""
},
"require": {
"composer/package-versions-deprecated": "^1.10",
"composer/semver": "^1.4 || ^2.0 || ^3.0",
"ext-simplexml": "*",
"php": "^7.1 || ^8.0",
"vimeo/psalm": "dev-master || dev-4.x || ^4.5"
},
"conflict": {
"phpunit/phpunit": "<7.5"
},
"require-dev": {
"codeception/codeception": "^4.0.3",
"php": "^7.3 || ^8.0",
"phpunit/phpunit": "^7.5 || ^8.0 || ^9.0",
"squizlabs/php_codesniffer": "^3.3.1",
"weirdan/codeception-psalm-module": "^0.11.0",
"weirdan/prophecy-shim": "^1.0 || ^2.0"
},
"type": "psalm-plugin",
"extra": {
"psalm": {
"pluginClass": "Psalm\\PhpUnitPlugin\\Plugin"
}
},
"autoload": {
"psr-4": {
"Psalm\\PhpUnitPlugin\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Matt Brown",
"email": "github@muglug.com"
}
],
"description": "Psalm plugin for PHPUnit",
"support": {
"issues": "https://github.com/psalm/psalm-plugin-phpunit/issues",
"source": "https://github.com/psalm/psalm-plugin-phpunit/tree/0.17.0"
},
"time": "2022-06-14T17:05:57+00:00"
},
{
"name": "psr/cache",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/cache.git",
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Cache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for caching libraries",
"keywords": [
"cache",
"psr",
"psr-6"
],
"support": {
"source": "https://github.com/php-fig/cache/tree/3.0.0"
},
"time": "2021-02-03T23:26:27+00:00"
},
{
"name": "psr/log",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"support": {
"source": "https://github.com/php-fig/log/tree/3.0.0"
},
"time": "2021-07-14T16:46:02+00:00"
},
{
"name": "sebastian/cli-parser",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for parsing CLI options",
"homepage": "https://github.com/sebastianbergmann/cli-parser",
"support": {
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
"source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:08:49+00:00"
},
{
"name": "sebastian/code-unit",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit.git",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the PHP code units",
"homepage": "https://github.com/sebastianbergmann/code-unit",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit/issues",
"source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:08:54+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
"source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:30:19+00:00"
},
{
"name": "sebastian/comparator",
"version": "4.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/diff": "^4.0",
"sebastian/exporter": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "https://github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
"source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T12:41:17+00:00"
},
{
"name": "sebastian/complexity",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.7",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for calculating the complexity of PHP code units",
"homepage": "https://github.com/sebastianbergmann/complexity",
"support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues",
"source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T15:52:27+00:00"
},
{
"name": "sebastian/diff",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3",
"symfony/process": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
}
],
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
"diff",
"udiff",
"unidiff",
"unified diff"
],
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:10:38+00:00"
},
{
"name": "sebastian/environment",
"version": "5.1.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-posix": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"support": {
"issues": "https://github.com/sebastianbergmann/environment/issues",
"source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-04-03T09:37:03+00:00"
},
{
"name": "sebastian/exporter",
"version": "4.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-mbstring": "*",
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "https://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T06:03:37+00:00"
},
{
"name": "sebastian/global-state",
"version": "5.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-dom": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-uopz": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-02-14T08:28:10+00:00"
},
{
"name": "sebastian/lines-of-code",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.6",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for counting the lines of code in PHP source code",
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
"support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-11-28T06:42:11+00:00"
},
{
"name": "sebastian/object-enumerator",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
"source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:12:34+00:00"
},
{
"name": "sebastian/object-reflector",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Allows reflection of object attributes, including inherited and non-public ones",
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-reflector/issues",
"source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:14:26+00:00"
},
{
"name": "sebastian/recursion-context",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
"source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:17:30+00:00"
},
{
"name": "sebastian/resource-operations",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"support": {
"issues": "https://github.com/sebastianbergmann/resource-operations/issues",
"source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:45:17+00:00"
},
{
"name": "sebastian/type",
"version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the types of the PHP type system",
"homepage": "https://github.com/sebastianbergmann/type",
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
"source": "https://github.com/sebastianbergmann/type/tree/3.2.0"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-12T14:47:03+00:00"
},
{
"name": "sebastian/version",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "c6c1022351a901512170118436c764e473f6de8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
"reference": "c6c1022351a901512170118436c764e473f6de8c",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"support": {
"issues": "https://github.com/sebastianbergmann/version/issues",
"source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:39:44+00:00"
},
{
"name": "seld/jsonlint",
"version": "1.9.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/jsonlint.git",
"reference": "4211420d25eba80712bff236a98960ef68b866b7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/4211420d25eba80712bff236a98960ef68b866b7",
"reference": "4211420d25eba80712bff236a98960ef68b866b7",
"shasum": ""
},
"require": {
"php": "^5.3 || ^7.0 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1.5",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13"
},
"bin": [
"bin/jsonlint"
],
"type": "library",
"autoload": {
"psr-4": {
"Seld\\JsonLint\\": "src/Seld/JsonLint/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "JSON Linter",
"keywords": [
"json",
"linter",
"parser",
"validator"
],
"support": {
"issues": "https://github.com/Seldaek/jsonlint/issues",
"source": "https://github.com/Seldaek/jsonlint/tree/1.9.0"
},
"funding": [
{
"url": "https://github.com/Seldaek",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/seld/jsonlint",
"type": "tidelift"
}
],
"time": "2022-04-01T13:37:23+00:00"
},
{
"name": "slevomat/coding-standard",
"version": "7.2.1",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
"php": "^7.2 || ^8.0",
"phpstan/phpdoc-parser": "^1.5.1",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phing/phing": "2.17.3",
"php-parallel-lint/php-parallel-lint": "1.3.2",
"phpstan/phpstan": "1.4.10|1.7.1",
"phpstan/phpstan-deprecation-rules": "1.0.0",
"phpstan/phpstan-phpunit": "1.0.0|1.1.1",
"phpstan/phpstan-strict-rules": "1.2.3",
"phpunit/phpunit": "7.5.20|8.5.21|9.5.20"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "7.x-dev"
}
},
"autoload": {
"psr-4": {
"SlevomatCodingStandard\\": "SlevomatCodingStandard"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
"source": "https://github.com/slevomat/coding-standard/tree/7.2.1"
},
"funding": [
{
"url": "https://github.com/kukulich",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
"type": "tidelift"
}
],
"time": "2022-05-25T10:58:12+00:00"
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.7.1",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"bin/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2022-06-18T07:21:10+00:00"
},
{
"name": "symfony/console",
"version": "v6.0.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "8f14753b865651c2aad107ef97475740a9b0730f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/8f14753b865651c2aad107ef97475740a9b0730f",
"reference": "8f14753b865651c2aad107ef97475740a9b0730f",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^1.1|^2|^3",
"symfony/string": "^5.4|^6.0"
},
"conflict": {
"symfony/dependency-injection": "<5.4",
"symfony/dotenv": "<5.4",
"symfony/event-dispatcher": "<5.4",
"symfony/lock": "<5.4",
"symfony/process": "<5.4"
},
"provide": {
"psr/log-implementation": "1.0|2.0|3.0"
},
"require-dev": {
"psr/log": "^1|^2|^3",
"symfony/config": "^5.4|^6.0",
"symfony/dependency-injection": "^5.4|^6.0",
"symfony/event-dispatcher": "^5.4|^6.0",
"symfony/lock": "^5.4|^6.0",
"symfony/process": "^5.4|^6.0",
"symfony/var-dumper": "^5.4|^6.0"
},
"suggest": {
"psr/log": "For using the console logger",
"symfony/event-dispatcher": "",
"symfony/lock": "",
"symfony/process": ""
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Eases the creation of beautiful and testable command line interfaces",
"homepage": "https://symfony.com",
"keywords": [
"cli",
"command line",
"console",
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v6.0.13"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-09-03T14:23:25+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.0.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c",
"reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c",
"shasum": ""
},
"require": {
"php": ">=8.0.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.0-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-01-02T09:55:41+00:00"
},
{
"name": "symfony/filesystem",
"version": "v6.0.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "3adca49133bd055ebe6011ed1e012be3c908af79"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/3adca49133bd055ebe6011ed1e012be3c908af79",
"reference": "3adca49133bd055ebe6011ed1e012be3c908af79",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.8"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Filesystem\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v6.0.13"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-09-21T20:25:27+00:00"
},
{
"name": "symfony/finder",
"version": "v6.0.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "09cb683ba5720385ea6966e5e06be2a34f2568b1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/09cb683ba5720385ea6966e5e06be2a34f2568b1",
"reference": "09cb683ba5720385ea6966e5e06be2a34f2568b1",
"shasum": ""
},
"require": {
"php": ">=8.0.2"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Finder\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v6.0.11"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-07-29T07:39:48+00:00"
},
{
"name": "symfony/options-resolver",
"version": "v6.0.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
"reference": "51f7006670febe4cbcbae177cbffe93ff833250d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/51f7006670febe4cbcbae177cbffe93ff833250d",
"reference": "51f7006670febe4cbcbae177cbffe93ff833250d",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"symfony/deprecation-contracts": "^2.1|^3"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\OptionsResolver\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an improved replacement for the array_replace PHP function",
"homepage": "https://symfony.com",
"keywords": [
"config",
"configuration",
"options"
],
"support": {
"source": "https://github.com/symfony/options-resolver/tree/v6.0.3"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-01-02T09:55:41+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-ctype": "*"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "433d05519ce6990bf3530fba6957499d327395c2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
"reference": "433d05519ce6990bf3530fba6957499d327395c2",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Grapheme\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's grapheme_* functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"grapheme",
"intl",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's Normalizer class and related functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"intl",
"normalizer",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-mbstring": "*"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php80\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ion Bazan",
"email": "ion.bazan@gmail.com"
},
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-10T07:21:04+00:00"
},
{
"name": "symfony/process",
"version": "v6.0.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "44270a08ccb664143dede554ff1c00aaa2247a43"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/44270a08ccb664143dede554ff1c00aaa2247a43",
"reference": "44270a08ccb664143dede554ff1c00aaa2247a43",
"shasum": ""
},
"require": {
"php": ">=8.0.2"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Process\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v6.0.11"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-06-27T17:10:44+00:00"
},
{
"name": "symfony/service-contracts",
"version": "v2.5.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
"reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1",
"symfony/deprecation-contracts": "^2.1|^3"
},
"conflict": {
"ext-psr": "<1.1|>=2"
},
"suggest": {
"symfony/service-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\Service\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to writing services",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v2.5.2"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-30T19:17:29+00:00"
},
{
"name": "symfony/string",
"version": "v6.0.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "65e99fb179e7241606377e4042cd2161f3dd1c05"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/65e99fb179e7241606377e4042cd2161f3dd1c05",
"reference": "65e99fb179e7241606377e4042cd2161f3dd1c05",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
"symfony/translation-contracts": "<2.0"
},
"require-dev": {
"symfony/error-handler": "^5.4|^6.0",
"symfony/http-client": "^5.4|^6.0",
"symfony/translation-contracts": "^2.0|^3.0",
"symfony/var-exporter": "^5.4|^6.0"
},
"type": "library",
"autoload": {
"files": [
"Resources/functions.php"
],
"psr-4": {
"Symfony\\Component\\String\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
"homepage": "https://symfony.com",
"keywords": [
"grapheme",
"i18n",
"string",
"unicode",
"utf-8",
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v6.0.13"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-09-02T08:05:03+00:00"
},
{
"name": "theseer/tokenizer",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
}
],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/1.2.1"
},
"funding": [
{
"url": "https://github.com/theseer",
"type": "github"
}
],
"time": "2021-07-28T10:34:58+00:00"
},
{
"name": "vimeo/psalm",
"version": "4.28.0",
"source": {
"type": "git",
"url": "https://github.com/vimeo/psalm.git",
"reference": "52e96bea381e6cb07a672aefec791a5817694a26"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/vimeo/psalm/zipball/52e96bea381e6cb07a672aefec791a5817694a26",
"reference": "52e96bea381e6cb07a672aefec791a5817694a26",
"shasum": ""
},
"require": {
"amphp/amp": "^2.4.2",
"amphp/byte-stream": "^1.5",
"composer/package-versions-deprecated": "^1.8.0",
"composer/semver": "^1.4 || ^2.0 || ^3.0",
"composer/xdebug-handler": "^1.1 || ^2.0 || ^3.0",
"dnoegel/php-xdg-base-dir": "^0.1.1",
"ext-ctype": "*",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-simplexml": "*",
"ext-tokenizer": "*",
"felixfbecker/advanced-json-rpc": "^3.0.3",
"felixfbecker/language-server-protocol": "^1.5",
"netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0",
"nikic/php-parser": "^4.13",
"openlss/lib-array2xml": "^1.0",
"php": "^7.1|^8",
"sebastian/diff": "^3.0 || ^4.0",
"symfony/console": "^3.4.17 || ^4.1.6 || ^5.0 || ^6.0",
"symfony/polyfill-php80": "^1.25",
"webmozart/path-util": "^2.3"
},
"provide": {
"psalm/psalm": "self.version"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.2",
"brianium/paratest": "^4.0||^6.0",
"ext-curl": "*",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpdocumentor/reflection-docblock": "^5",
"phpmyadmin/sql-parser": "5.1.0||dev-master",
"phpspec/prophecy": ">=1.9.0",
"phpstan/phpdoc-parser": "1.2.* || 1.6.4",
"phpunit/phpunit": "^9.0",
"psalm/plugin-phpunit": "^0.16",
"slevomat/coding-standard": "^7.0",
"squizlabs/php_codesniffer": "^3.5",
"symfony/process": "^4.3 || ^5.0 || ^6.0",
"weirdan/prophecy-shim": "^1.0 || ^2.0"
},
"suggest": {
"ext-curl": "In order to send data to shepherd",
"ext-igbinary": "^2.0.5 is required, used to serialize caching data"
},
"bin": [
"psalm",
"psalm-language-server",
"psalm-plugin",
"psalm-refactor",
"psalter"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.x-dev",
"dev-3.x": "3.x-dev",
"dev-2.x": "2.x-dev",
"dev-1.x": "1.x-dev"
}
},
"autoload": {
"files": [
"src/functions.php",
"src/spl_object_id.php"
],
"psr-4": {
"Psalm\\": "src/Psalm/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Matthew Brown"
}
],
"description": "A static analysis tool for finding errors in PHP applications",
"keywords": [
"code",
"inspection",
"php"
],
"support": {
"issues": "https://github.com/vimeo/psalm/issues",
"source": "https://github.com/vimeo/psalm/tree/4.28.0"
},
"time": "2022-10-07T16:13:24+00:00"
},
{
"name": "webimpress/coding-standard",
"version": "1.2.4",
"source": {
"type": "git",
"url": "https://github.com/webimpress/coding-standard.git",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webimpress/coding-standard/zipball/cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"shasum": ""
},
"require": {
"php": "^7.3 || ^8.0",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phpunit/phpunit": "^9.5.13"
},
"type": "phpcodesniffer-standard",
"extra": {
"dev-master": "1.2.x-dev",
"dev-develop": "1.3.x-dev"
},
"autoload": {
"psr-4": {
"WebimpressCodingStandard\\": "src/WebimpressCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-2-Clause"
],
"description": "Webimpress Coding Standard",
"keywords": [
"Coding Standard",
"PSR-2",
"phpcs",
"psr-12",
"webimpress"
],
"support": {
"issues": "https://github.com/webimpress/coding-standard/issues",
"source": "https://github.com/webimpress/coding-standard/tree/1.2.4"
},
"funding": [
{
"url": "https://github.com/michalbundyra",
"type": "github"
}
],
"time": "2022-02-15T19:52:12+00:00"
},
{
"name": "webimpress/safe-writer",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/webimpress/safe-writer.git",
"reference": "9d37cc8bee20f7cb2f58f6e23e05097eab5072e6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webimpress/safe-writer/zipball/9d37cc8bee20f7cb2f58f6e23e05097eab5072e6",
"reference": "9d37cc8bee20f7cb2f58f6e23e05097eab5072e6",
"shasum": ""
},
"require": {
"php": "^7.3 || ^8.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5.4",
"vimeo/psalm": "^4.7",
"webimpress/coding-standard": "^1.2.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.2.x-dev",
"dev-develop": "2.3.x-dev",
"dev-release-1.0": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Webimpress\\SafeWriter\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-2-Clause"
],
"description": "Tool to write files safely, to avoid race conditions",
"keywords": [
"concurrent write",
"file writer",
"race condition",
"safe writer",
"webimpress"
],
"support": {
"issues": "https://github.com/webimpress/safe-writer/issues",
"source": "https://github.com/webimpress/safe-writer/tree/2.2.0"
},
"funding": [
{
"url": "https://github.com/michalbundyra",
"type": "github"
}
],
"time": "2021-04-19T16:34:45+00:00"
},
{
"name": "webmozart/assert",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/webmozarts/assert.git",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"php": "^7.2 || ^8.0"
},
"conflict": {
"phpstan/phpstan": "<0.12.20",
"vimeo/psalm": "<4.6.1 || 4.6.2"
},
"require-dev": {
"phpunit/phpunit": "^8.5.13"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.10-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\Assert\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Assertions to validate method input/output with nice error messages.",
"keywords": [
"assert",
"check",
"validate"
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.11.0"
},
"time": "2022-06-03T18:03:27+00:00"
},
{
"name": "webmozart/path-util",
"version": "2.3.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/path-util.git",
"reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
"reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"webmozart/assert": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.6",
"sebastian/version": "^1.0.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.3-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\PathUtil\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.",
"support": {
"issues": "https://github.com/webmozart/path-util/issues",
"source": "https://github.com/webmozart/path-util/tree/2.3.0"
},
"abandoned": "symfony/filesystem",
"time": "2015-12-17T08:42:14+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"mikey179/vfsstream": 15
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"platform-dev": [],
"platform-overrides": {
"php": "8.0.99"
},
"plugin-api-version": "2.3.0"
}
laminas-servicemanager/bin/generate-deps-for-config-factory 0000644 00000001102 15240152640 0020064 0 ustar 00 #!/usr/bin/env php
<?php
declare(strict_types=1);
namespace Laminas\ServiceManager;
// Setup/verify autoloading
if (file_exists($a = getcwd() . '/vendor/autoload.php')) {
require $a;
} elseif (file_exists($a = __DIR__ . '/../../../autoload.php')) {
require $a;
} elseif (file_exists($a = __DIR__ . '/../vendor/autoload.php')) {
require $a;
} else {
fwrite(STDERR, 'Cannot locate autoloader; please run "composer install"' . PHP_EOL);
exit(1);
}
$command = new Tool\ConfigDumperCommand($argv[0]);
$status = $command(array_slice($argv, 1));
exit($status);
laminas-servicemanager/bin/generate-factory-for-class 0000644 00000001104 15240152640 0016775 0 ustar 00 #!/usr/bin/env php
<?php
declare(strict_types=1);
namespace Laminas\ServiceManager;
// Setup/verify autoloading
if (file_exists($a = getcwd() . '/vendor/autoload.php')) {
require $a;
} elseif (file_exists($a = __DIR__ . '/../../../autoload.php')) {
require $a;
} elseif (file_exists($a = __DIR__ . '/../vendor/autoload.php')) {
require $a;
} else {
fwrite(STDERR, 'Cannot locate autoloader; please run "composer install"' . PHP_EOL);
exit(1);
}
$command = new Tool\FactoryCreatorCommand($argv[0]);
$status = $command(array_slice($argv, 1));
exit($status);
laminas-servicemanager/LICENSE.md 0000644 00000002732 15240152640 0012570 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of Laminas Foundation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
laminas-math/src/Exception/InvalidArgumentException.php 0000644 00000000267 15240152640 0017331 0 ustar 00 <?php
namespace Laminas\Math\Exception;
/**
* Invalid argument exception
*/
class InvalidArgumentException extends \InvalidArgumentException implements
ExceptionInterface
{
}
laminas-math/src/Exception/ExceptionInterface.php 0000644 00000000113 15240152640 0016126 0 ustar 00 <?php
namespace Laminas\Math\Exception;
interface ExceptionInterface
{
}
laminas-math/src/Exception/DomainException.php 0000644 00000000241 15240152640 0015437 0 ustar 00 <?php
namespace Laminas\Math\Exception;
/**
* Invalid argument exception
*/
class DomainException extends \DomainException implements ExceptionInterface
{
}
laminas-math/src/Exception/RuntimeException.php 0000644 00000000247 15240152640 0015661 0 ustar 00 <?php
namespace Laminas\Math\Exception;
/**
* Runtime argument exception
*/
class RuntimeException extends \RuntimeException implements
ExceptionInterface
{
}
laminas-math/src/Rand.php 0000644 00000010457 15240152640 0011311 0 ustar 00 <?php
namespace Laminas\Math;
use Error;
use TypeError;
use function base64_encode;
use function ceil;
use function chr;
use function mb_strlen;
use function mb_substr;
use function ord;
use function random_bytes;
use function random_int;
use function rtrim;
use function str_repeat;
use function unpack;
/**
* Pseudorandom number generator (PRNG)
*/
// phpcs:ignore WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix
abstract class Rand
{
/** @deprecated No longer used internally */
// phpcs:ignore SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingAnyTypeHint
protected static $generator;
/**
* Generate random bytes using different approaches
* If PHP 7 is running we use the random_bytes() function
*
* @param int $length
* @return string
* @throws Exception\RuntimeException
*/
public static function getBytes($length)
{
try {
return random_bytes($length);
} catch (TypeError $e) {
throw new Exception\InvalidArgumentException(
'Invalid parameter provided to getBytes(length)',
0,
$e
);
} catch (Error $e) {
throw new Exception\DomainException(
'The length must be a positive number in getBytes(length)',
0,
$e
);
}
}
/**
* Generate random boolean
*
* @return bool
*/
public static function getBoolean()
{
$byte = static::getBytes(1);
return (bool) (ord($byte) % 2);
}
/**
* Generate a random integer between $min and $max
*
* @param int $min
* @param int $max
* @return int
* @throws Exception\DomainException
*/
public static function getInteger($min, $max)
{
try {
return random_int($min, $max);
} catch (TypeError $e) {
throw new Exception\InvalidArgumentException(
'Invalid parameters provided to getInteger(min, max)',
0,
$e
);
} catch (Error $e) {
throw new Exception\DomainException(
'The min parameter must be lower than max in getInteger(min, max)',
0,
$e
);
}
}
/**
* Generate random float [0..1)
* This function generates floats with platform-dependent precision
*
* PHP uses double precision floating-point format (64-bit) which has
* 52-bits of significand precision. We gather 7 bytes of random data,
* and we fix the exponent to the bias (1023). In this way we generate
* a float of 1.mantissa.
*
* @return float
*/
public static function getFloat()
{
$bytes = static::getBytes(7);
// phpcs:ignore SlevomatCodingStandard.Operators.RequireCombinedAssignmentOperator.RequiredCombinedAssigmentOperator
$bytes[6] = $bytes[6] | chr(0xF0);
$bytes .= chr(63); // exponent bias (1023)
$float = unpack('d', $bytes)[1];
return $float - 1;
}
/**
* Generate a random string of specified length.
*
* Uses supplied character list for generating the new string.
* If no character list provided - uses Base 64 character set.
*
* @param int $length
* @param string|null $charlist
* @return string
* @throws Exception\DomainException
*/
public static function getString($length, $charlist = null)
{
if ($length < 1) {
throw new Exception\DomainException('Length should be >= 1');
}
// charlist is empty or not provided
if (empty($charlist)) {
$numBytes = ceil($length * 0.75);
$bytes = static::getBytes($numBytes);
return mb_substr(rtrim(base64_encode($bytes), '='), 0, $length, '8bit');
}
$listLen = mb_strlen($charlist, '8bit');
// phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator
if ($listLen == 1) {
return str_repeat($charlist, $length);
}
$result = '';
for ($i = 0; $i < $length; $i++) {
$pos = static::getInteger(0, $listLen - 1);
$result .= $charlist[$pos];
}
return $result;
}
}
laminas-math/src/BigInteger/Exception/InvalidArgumentException.php 0000644 00000000344 15240152640 0021344 0 ustar 00 <?php
namespace Laminas\Math\BigInteger\Exception;
use Laminas\Math\Exception;
/**
* Invalid argument exception
*/
class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface
{
}
laminas-math/src/BigInteger/Exception/ExceptionInterface.php 0000644 00000000276 15240152640 0020157 0 ustar 00 <?php
namespace Laminas\Math\BigInteger\Exception;
use Laminas\Math\Exception;
/**
* Invalid argument exception
*/
interface ExceptionInterface extends Exception\ExceptionInterface
{
}
laminas-math/src/BigInteger/Exception/DivisionByZeroException.php 0000644 00000000264 15240152640 0021173 0 ustar 00 <?php
namespace Laminas\Math\BigInteger\Exception;
/**
* Division by zero exception
*/
class DivisionByZeroException extends RuntimeException implements ExceptionInterface
{
}
laminas-math/src/BigInteger/Exception/RuntimeException.php 0000644 00000000313 15240152640 0017672 0 ustar 00 <?php
namespace Laminas\Math\BigInteger\Exception;
use Laminas\Math\Exception;
/**
* Runtime exception
*/
class RuntimeException extends Exception\RuntimeException implements ExceptionInterface
{
}
laminas-math/src/BigInteger/Adapter/AdapterInterface.php 0000644 00000006367 15240152640 0017232 0 ustar 00 <?php
namespace Laminas\Math\BigInteger\Adapter;
interface AdapterInterface
{
/**
* Base62 alphabet for arbitrary base conversion
*/
public const BASE62_ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
/**
* Create adapter-specific representation of a big integer
*
* @param string $operand
* @param int|null $base
* @return mixed
*/
public function init($operand, $base = null);
/**
* Add two big integers
*
* @param string $leftOperand
* @param string $rightOperand
* @return string
*/
public function add($leftOperand, $rightOperand);
/**
* Subtract two big integers
*
* @param string $leftOperand
* @param string $rightOperand
* @return string
*/
public function sub($leftOperand, $rightOperand);
/**
* Multiply two big integers
*
* @param string $leftOperand
* @param string $rightOperand
* @return string
*/
public function mul($leftOperand, $rightOperand);
/**
* Divide two big integers
* (this method returns only int part of result)
*
* @param string $leftOperand
* @param string $rightOperand
* @return string
*/
public function div($leftOperand, $rightOperand);
/**
* Raise a big integers to another
*
* @param string $operand
* @param string $exp
* @return string
*/
public function pow($operand, $exp);
/**
* Get the square root of a big integer
*
* @param string $operand
* @return string
*/
public function sqrt($operand);
/**
* Get absolute value of a big integer
*
* @param string $operand
* @return string
*/
public function abs($operand);
/**
* Get modulus of a big integer
*
* @param string $leftOperand
* @param string $modulus
* @return string
*/
public function mod($leftOperand, $modulus);
/**
* Raise a big integer to another, reduced by a specified modulus
*
* @param string $leftOperand
* @param string $rightOperand
* @param string $modulus
* @return string
*/
public function powmod($leftOperand, $rightOperand, $modulus);
/**
* Compare two big integers
* Returns < 0 if leftOperand is less than rightOperand;
* > 0 if leftOperand is greater than rightOperand, and 0 if they are equal.
*
* @param string $leftOperand
* @param string $rightOperand
* @return int
*/
public function comp($leftOperand, $rightOperand);
/**
* Convert big integer into it's binary number representation
*
* @param string $int
* @param bool $twoc
* @return string
*/
public function intToBin($int, $twoc = false);
/**
* Convert binary number into big integer
*
* @param string $bytes
* @param bool $twoc
* @return string
*/
public function binToInt($bytes, $twoc = false);
/**
* Convert a number between arbitrary bases
*
* @param string $operand
* @param int $fromBase
* @param int $toBase
* @return string
*/
public function baseConvert($operand, $fromBase, $toBase = 10);
}
laminas-math/src/BigInteger/Adapter/Bcmath.php 0000644 00000022624 15240152640 0015221 0 ustar 00 <?php
namespace Laminas\Math\BigInteger\Adapter;
use Laminas\Math\BigInteger\Exception;
use function base_convert;
use function bcadd;
use function bccomp;
use function bcdiv;
use function bcmod;
use function bcmul;
use function bcpow;
use function bcpowmod;
use function bcsqrt;
use function bcsub;
use function chr;
use function ltrim;
use function mb_strlen;
use function ord;
use function preg_match;
use function str_pad;
use function strpos;
use function strtolower;
use const STR_PAD_LEFT;
/**
* Bcmath extension adapter
*/
class Bcmath implements AdapterInterface
{
/**
* Create string representing big integer in decimal form from arbitrary integer format
*
* @param string $operand
* @param int|null $base
* @return bool|string
*/
public function init($operand, $base = null)
{
$sign = strpos($operand, '-') === 0 ? '-' : '';
$operand = ltrim($operand, '-+');
if (null === $base) {
// decimal
if (preg_match('#^([1-9][0-9]*)$#', $operand, $m)) {
$base = 10;
$operand = $m[1];
// octal
} elseif (preg_match('#^(0[0-7]+)$#', $operand, $m)) {
$base = 8;
$operand = $m[1];
// hex
} elseif (preg_match('#^(?:0x)?([0-9a-f]+)$#', strtolower($operand), $m)) {
$base = 16;
$operand = $m[1];
// scientific notation
} elseif (preg_match('#^([1-9]?\.?[0-9]+)[eE]\+?([0-9]+)$#', $operand, $m)) {
$base = 10;
$operand = bcmul($m[1], bcpow('10', $m[2]));
} else {
return false;
}
}
// phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedNotEqualOperator
if ($base != 10) {
$operand = $this->baseConvert($operand, $base, 10);
}
$prod = bcmul($operand, '1');
if (bccomp($operand, $prod) !== 0) {
return false;
}
return $sign . $operand;
}
/**
* Add two big integers
*
* @param string $leftOperand
* @param string $rightOperand
* @return string
*/
public function add($leftOperand, $rightOperand)
{
return bcadd($leftOperand, $rightOperand, 0);
}
/**
* Subtract two big integers
*
* @param string $leftOperand
* @param string $rightOperand
* @return string
*/
public function sub($leftOperand, $rightOperand)
{
return bcsub($leftOperand, $rightOperand, 0);
}
/**
* Multiply two big integers
*
* @param string $leftOperand
* @param string $rightOperand
* @return string
*/
public function mul($leftOperand, $rightOperand)
{
return bcmul($leftOperand, $rightOperand, 0);
}
/**
* Divide two big integers and return integer part result.
* Raises exception if the divisor is zero.
*
* @param string $leftOperand
* @param string $rightOperand
* @return string
* @throws Exception\DivisionByZeroException
*/
public function div($leftOperand, $rightOperand)
{
// phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator
if ($rightOperand == 0) {
throw new Exception\DivisionByZeroException(
"Division by zero; divisor = {$rightOperand}"
);
}
return bcdiv($leftOperand, $rightOperand, 0);
}
/**
* Raise a big integers to another
*
* @param string $operand
* @param string $exp
* @return string
*/
public function pow($operand, $exp)
{
return bcpow($operand, $exp, 0);
}
/**
* Get the square root of a big integer
*
* @param string $operand
* @return string
*/
public function sqrt($operand)
{
return bcsqrt($operand, 0);
}
/**
* Get absolute value of a big integer
*
* @param string $operand
* @return string
*/
public function abs($operand)
{
return ltrim($operand, '-');
}
/**
* Get modulus of a big integer
*
* @param string $leftOperand
* @param string $rightOperand
* @return string
*/
public function mod($leftOperand, $rightOperand)
{
return bcmod($leftOperand, $rightOperand);
}
/**
* Raise a big integer to another, reduced by a specified modulus
*
* @param string $leftOperand
* @param string $rightOperand
* @param string $modulus
* @return string
*/
public function powmod($leftOperand, $rightOperand, $modulus)
{
return bcpowmod($leftOperand, $rightOperand, $modulus, 0);
}
/**
* Compare two big integers and returns result as an integer where
* Returns < 0 if leftOperand is less than rightOperand;
* > 0 if leftOperand is greater than rightOperand, and 0 if they are equal.
*
* @param string $leftOperand
* @param string $rightOperand
* @return int
*/
public function comp($leftOperand, $rightOperand)
{
return bccomp($leftOperand, $rightOperand, 0);
}
/**
* Convert big integer into it's binary number representation
*
* @param string $operand
* @param bool $twoc return in two's complement form
* @return string
*/
public function intToBin($operand, $twoc = false)
{
$nb = chr(0);
$isNegative = strpos($operand, '-') === 0;
$operand = ltrim($operand, '+-0');
if (empty($operand)) {
return $nb;
}
if ($isNegative && $twoc) {
$operand = bcsub($operand, '1');
}
$bytes = '';
while (bccomp($operand, '0', 0) > 0) {
$temp = bcmod($operand, '16777216');
$bytes = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $bytes;
$operand = bcdiv($operand, '16777216', 0);
}
$bytes = ltrim($bytes, $nb);
if ($twoc) {
if (ord($bytes[0]) & 0x80) {
$bytes = $nb . $bytes;
}
return $isNegative ? ~$bytes : $bytes;
}
return $bytes;
}
/**
* Convert big integer into it's binary number representation
*
* @param string $bytes
* @param bool $twoc whether binary number is in twos' complement form
* @return string
*/
public function binToInt($bytes, $twoc = false)
{
$isNegative = (ord($bytes[0]) & 0x80) && $twoc;
if ($isNegative) {
$bytes = ~$bytes;
}
$len = (mb_strlen($bytes, '8bit') + 3) & 0xfffffffc;
$bytes = str_pad($bytes, $len, chr(0), STR_PAD_LEFT);
$result = '0';
for ($i = 0; $i < $len; $i += 4) {
$result = bcmul($result, '4294967296'); // 2**32
$result = bcadd($result, 0x1000000 * ord($bytes[$i]) +
((ord($bytes[$i + 1]) << 16) |
(ord($bytes[$i + 2]) << 8) |
ord($bytes[$i + 3])));
}
if ($isNegative) {
$result = bcsub('-' . $result, '1');
}
return $result;
}
/**
* Base conversion. Bases 2..62 are supported
*
* @param string $operand
* @param int $fromBase
* @param int $toBase
* @return string
* @throws Exception\InvalidArgumentException
*/
public function baseConvert($operand, $fromBase, $toBase = 10)
{
// phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator
if ($fromBase == $toBase) {
return $operand;
}
if ($fromBase < 2 || $fromBase > 62) {
throw new Exception\InvalidArgumentException(
"Unsupported base: {$fromBase}, should be 2..62"
);
}
if ($toBase < 2 || $toBase > 62) {
throw new Exception\InvalidArgumentException(
"Unsupported base: {$toBase}, should be 2..62"
);
}
$sign = strpos($operand, '-') === 0 ? '-' : '';
$operand = ltrim($operand, '-+');
$chars = self::BASE62_ALPHABET;
// convert to decimal
// phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator
if ($fromBase == 10) {
$decimal = $operand;
} else {
$decimal = '0';
for ($i = 0, $len = mb_strlen($operand, '8bit'); $i < $len; $i++) {
$decimal = bcmul($decimal, $fromBase);
$remainder = $fromBase <= 36
? base_convert($operand[$i], $fromBase, 10)
: strpos($chars, $operand[$i]);
$decimal = bcadd($decimal, $remainder, 0);
}
}
// phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator
if ($toBase == 10) {
return $decimal;
}
// convert decimal to base
$result = '';
do {
$remainder = bcmod($decimal, $toBase);
$decimal = bcdiv($decimal, $toBase);
$intermediate = $toBase <= 36
? base_convert($remainder, 10, $toBase)
: $chars[$remainder];
$result = $intermediate . $result;
} while (bccomp($decimal, '0'));
return $sign . $result;
}
}
laminas-math/src/BigInteger/Adapter/Gmp.php 0000644 00000021452 15240152640 0014544 0 ustar 00 <?php
namespace Laminas\Math\BigInteger\Adapter;
use Laminas\Math\BigInteger\Exception;
use TypeError;
use ValueError;
use function bin2hex;
use function chr;
use function ltrim;
use function mb_strlen;
use function ord;
use function pack;
use function preg_match;
use function restore_error_handler;
use function set_error_handler;
use function str_pad;
use function strpos;
use const E_WARNING;
use const STR_PAD_RIGHT;
/**
* GMP extension adapter
*/
class Gmp implements AdapterInterface
{
/**
* Create string representing big integer in decimal form from arbitrary integer format
*
* @param string $operand
* @param int|null $base
* @return bool|string
*/
public function init($operand, $base = null)
{
$sign = strpos($operand, '-') === 0 ? '-' : '';
$operand = ltrim($operand, '-+');
if (null === $base) {
// scientific notation
if (preg_match('#^(?:([1-9])\.)?([0-9]+)[eE]\+?([0-9]+)$#', $operand, $m)) {
if (! empty($m[1])) {
if ($m[3] < mb_strlen($m[2], '8bit')) {
return false;
}
} else {
$m[1] = '';
}
$operand = str_pad($m[1] . $m[2], $m[3] + 1, '0', STR_PAD_RIGHT);
} else {
// let GMP guess base
$base = 0;
}
}
set_error_handler(function () {
/* Do nothing */
}, E_WARNING);
try {
$res = gmp_init($sign . $operand, $base);
} catch (TypeError $e) {
$res = false;
} catch (ValueError $e) {
$res = false;
}
restore_error_handler();
if ($res === false) {
return false;
}
return gmp_strval($res);
}
/**
* Add two big integers
*
* @param string $leftOperand
* @param string $rightOperand
* @return string
*/
public function add($leftOperand, $rightOperand)
{
$result = gmp_add($leftOperand, $rightOperand);
return gmp_strval($result);
}
/**
* Subtract two big integers
*
* @param string $leftOperand
* @param string $rightOperand
* @return string
*/
public function sub($leftOperand, $rightOperand)
{
$result = gmp_sub($leftOperand, $rightOperand);
return gmp_strval($result);
}
/**
* Multiply two big integers
*
* @param string $leftOperand
* @param string $rightOperand
* @return string
*/
public function mul($leftOperand, $rightOperand)
{
$result = gmp_mul($leftOperand, $rightOperand);
return gmp_strval($result);
}
/**
* Divide two big integers and return integer part result.
* Raises exception if the divisor is zero.
*
* @param string $leftOperand
* @param string $rightOperand
* @return string|null
* @throws Exception\DivisionByZeroException
*/
public function div($leftOperand, $rightOperand)
{
// phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator
if ($rightOperand == 0) {
throw new Exception\DivisionByZeroException(
"Division by zero; divisor = {$rightOperand}"
);
}
$result = gmp_div_q($leftOperand, $rightOperand);
return gmp_strval($result);
}
/**
* Raise a big integers to another
*
* @param string $operand
* @param string $exp
* @return string
*/
public function pow($operand, $exp)
{
$result = gmp_pow($operand, $exp);
return gmp_strval($result);
}
/**
* Get the square root of a big integer
*
* @param string $operand
* @return string
*/
public function sqrt($operand)
{
$result = gmp_sqrt($operand);
return gmp_strval($result);
}
/**
* Get absolute value of a big integer
*
* @param string $operand
* @return string
*/
public function abs($operand)
{
$result = gmp_abs($operand);
return gmp_strval($result);
}
/**
* Get modulus of a big integer
*
* @param string $leftOperand
* @param string $modulus
* @return string
*/
public function mod($leftOperand, $modulus)
{
$result = gmp_mod($leftOperand, $modulus);
return gmp_strval($result);
}
/**
* Raise a big integer to another, reduced by a specified modulus
*
* @param string $leftOperand
* @param string $rightOperand
* @param string $modulus
* @return string
*/
public function powmod($leftOperand, $rightOperand, $modulus)
{
$result = gmp_powm($leftOperand, $rightOperand, $modulus);
return gmp_strval($result);
}
/**
* Compare two big integers and returns result as an integer where
* Returns < 0 if leftOperand is less than rightOperand;
* > 0 if leftOperand is greater than rightOperand, and 0 if they are equal.
*
* @param string $leftOperand
* @param string $rightOperand
* @return int
*/
public function comp($leftOperand, $rightOperand)
{
return gmp_cmp($leftOperand, $rightOperand);
}
/**
* Convert big integer into it's binary number representation
*
* @param string $int
* @param bool $twoc return in twos' complement form
* @return string
*/
public function intToBin($int, $twoc = false)
{
$nb = chr(0);
$isNegative = strpos($int, '-') === 0;
$int = ltrim($int, '+-0');
if (empty($int)) {
return $nb;
}
if ($isNegative && $twoc) {
$int = gmp_sub($int, '1');
}
$hex = gmp_strval($int, 16);
if (mb_strlen($hex, '8bit') & 1) {
$hex = '0' . $hex;
}
$bytes = pack('H*', $hex);
$bytes = ltrim($bytes, $nb);
if ($twoc) {
if (ord($bytes[0]) & 0x80) {
$bytes = $nb . $bytes;
}
return $isNegative ? ~$bytes : $bytes;
}
return $bytes;
}
/**
* Convert binary number into big integer
*
* @param string $bytes
* @param bool $twoc whether binary number is in twos' complement form
* @return string
*/
public function binToInt($bytes, $twoc = false)
{
$isNegative = (ord($bytes[0]) & 0x80) && $twoc;
$sign = '';
if ($isNegative) {
$bytes = ~$bytes;
$sign = '-';
}
$result = gmp_init($sign . bin2hex($bytes), 16);
if ($isNegative) {
$result = gmp_sub($result, '1');
}
return gmp_strval($result);
}
/**
* Base conversion. Bases 2..62 are supported
*
* @param string $operand
* @param int $fromBase
* @param int $toBase
* @return string
* @throws Exception\InvalidArgumentException
*/
public function baseConvert($operand, $fromBase, $toBase = 10)
{
// phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator
if ($fromBase == $toBase) {
return $operand;
}
if ($fromBase < 2 || $fromBase > 62) {
throw new Exception\InvalidArgumentException(
"Unsupported base: {$fromBase}, should be 2..62"
);
}
if ($toBase < 2 || $toBase > 62) {
throw new Exception\InvalidArgumentException(
"Unsupported base: {$toBase}, should be 2..62"
);
}
if ($fromBase <= 36 && $toBase <= 36) {
return gmp_strval(gmp_init($operand, $fromBase), $toBase);
}
$sign = strpos($operand, '-') === 0 ? '-' : '';
$operand = ltrim($operand, '-+');
$chars = self::BASE62_ALPHABET;
// convert operand to decimal
if ($fromBase !== 10) {
$decimal = '0';
for ($i = 0, $len = mb_strlen($operand, '8bit'); $i < $len; $i++) {
$decimal = gmp_mul($decimal, $fromBase);
$decimal = gmp_add($decimal, strpos($chars, $operand[$i]));
}
} else {
$decimal = gmp_init($operand);
}
// phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator
if ($toBase == 10) {
return gmp_strval($decimal);
}
// convert decimal to base
$result = '';
do {
[$decimal, $remainder] = gmp_div_qr($decimal, $toBase);
$pos = gmp_strval($remainder);
$result = $chars[$pos] . $result;
} while (gmp_cmp($decimal, '0'));
return $sign . $result;
}
}
laminas-math/src/BigInteger/BigInteger.php 0000644 00000005164 15240152640 0014462 0 ustar 00 <?php
namespace Laminas\Math\BigInteger;
use function call_user_func_array;
use function class_exists;
use function extension_loaded;
use function is_subclass_of;
use function sprintf;
use function ucfirst;
// phpcs:ignore WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix
abstract class BigInteger
{
/**
* The default adapter.
*
* @var Adapter\AdapterInterface
*/
protected static $defaultAdapter;
/**
* Create a BigInteger adapter instance
*
* @param string|null $adapterName
* @return Adapter\AdapterInterface
*/
public static function factory($adapterName = null)
{
if (null === $adapterName) {
return static::getAvailableAdapter();
}
$adapterName = sprintf('%s\\Adapter\\%s', __NAMESPACE__, ucfirst($adapterName));
if (
! class_exists($adapterName)
|| ! is_subclass_of($adapterName, Adapter\AdapterInterface::class)
) {
throw new Exception\InvalidArgumentException(sprintf(
'The adapter %s either does not exist or does not implement %s',
$adapterName,
Adapter\AdapterInterface::class
));
}
return new $adapterName();
}
/**
* Set default BigInteger adapter
*
* @param string|Adapter\AdapterInterface $adapter
*/
public static function setDefaultAdapter($adapter)
{
static::$defaultAdapter = static::factory($adapter);
}
/**
* Get default BigInteger adapter
*
* @return null|Adapter\AdapterInterface
*/
public static function getDefaultAdapter()
{
if (null === static::$defaultAdapter) {
static::$defaultAdapter = static::getAvailableAdapter();
}
return static::$defaultAdapter;
}
/**
* Determine and return available adapter
*
* @return Adapter\AdapterInterface
* @throws Exception\RuntimeException
*/
public static function getAvailableAdapter()
{
if (extension_loaded('gmp')) {
return static::factory('Gmp');
}
if (extension_loaded('bcmath')) {
return static::factory('Bcmath');
}
throw new Exception\RuntimeException('Big integer math support is not detected');
}
/**
* Call adapter methods statically
*
* @param string $method
* @param mixed $args
* @return mixed
*/
public static function __callStatic($method, $args)
{
$adapter = static::getDefaultAdapter();
return call_user_func_array([$adapter, $method], $args);
}
}
laminas-math/README.md 0000644 00000010420 15240152640 0010372 0 ustar 00 # laminas-math
> ## 🇷🇺 Русским гражданам
>
> Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм.
>
> У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую.
>
> Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!"
>
> ## 🇺🇸 To Citizens of Russia
>
> We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism.
>
> One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences.
>
> You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!"
> This package is considered feature-complete, and is now in **security-only** maintenance mode, following a [decision by the Technical Steering Committee](https://github.com/laminas/technical-steering-committee/blob/2b55453e172a1b8c9c4c212be7cf7e7a58b9352c/meetings/minutes/2020-08-03-TSC-Minutes.md#vote-on-components-to-mark-as-security-only).
> If you have a security issue, please [follow our security reporting guidelines](https://getlaminas.org/security/).
> If you wish to take on the role of maintainer, please [nominate yourself](https://github.com/laminas/technical-steering-committee/issues/new?assignees=&labels=Nomination&template=Maintainer_Nomination.md&title=%5BNOMINATION%5D%5BMAINTAINER%5D%3A+%7Bname+of+person+being+nominated%7D)
>
> If you are looking for an actively maintained package alternative, we recommend:
>
> - [brick/math](https://packagist.org/packages/brick/math)
[](https://github.com/laminas/laminas-math/actions?query=workflow%3A"Continuous+Integration")
`Laminas\Math` provides general mathematical functions. So far the supported
functionalities are:
- `Laminas\Math\Rand`, a random number generator;
- `Laminas\Math\BigInteger`, a library to manage big integers.
## Migration notes from v2 to v3
[We document migration notes from v2 to v3](https://docs.laminas.dev/laminas-math/migration/),
providing details of potential BC breaks and/or API differences
you may need to be aware of.
## Miscellany
- File issues at https://github.com/laminas/laminas-math/issues
- Documentation is at https://docs.laminas.dev/laminas-math/
laminas-math/composer.json 0000644 00000003555 15240152640 0011650 0 ustar 00 {
"name": "laminas/laminas-math",
"description": "Create cryptographically secure pseudo-random numbers, and manage big integers",
"license": "BSD-3-Clause",
"keywords": [
"laminas",
"math"
],
"homepage": "https://laminas.dev",
"support": {
"docs": "https://docs.laminas.dev/laminas-math/",
"issues": "https://github.com/laminas/laminas-math/issues",
"source": "https://github.com/laminas/laminas-math",
"rss": "https://github.com/laminas/laminas-math/releases.atom",
"chat": "https://laminas.dev/chat",
"forum": "https://discourse.laminas.dev"
},
"config": {
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"extra": {
"branch-alias": {
"dev-master": "3.2.x-dev",
"dev-develop": "3.3.x-dev"
}
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"ext-mbstring": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"phpunit/phpunit": "~9.5.25"
},
"suggest": {
"ext-bcmath": "If using the bcmath functionality",
"ext-gmp": "If using the gmp functionality"
},
"autoload": {
"psr-4": {
"Laminas\\Math\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"LaminasTest\\Math\\": "test/"
},
"files": [
"test/TestAsset/random_bytes.php"
]
},
"scripts": {
"check": [
"@cs-check",
"@test"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
},
"conflict": {
"zendframework/zend-math": "*"
}
}
laminas-math/COPYRIGHT.md 0000644 00000000133 15240152640 0011005 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/)
laminas-math/composer.lock 0000644 00000225441 15240152640 0011627 0 ustar 00 {
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "509ebb94425de56ff14d1328df280d9d",
"packages": [],
"packages-dev": [
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
"version": "v0.7.2",
"source": {
"type": "git",
"url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
"phpcompatibility/php-compatibility": "^9.0"
},
"type": "composer-plugin",
"extra": {
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
"Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Franck Nijhof",
"email": "franck.nijhof@dealerdirect.com",
"homepage": "http://www.frenck.nl",
"role": "Developer / IT Manager"
},
{
"name": "Contributors",
"homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
"homepage": "http://www.dealerdirect.com",
"keywords": [
"PHPCodeSniffer",
"PHP_CodeSniffer",
"code quality",
"codesniffer",
"composer",
"installer",
"phpcbf",
"phpcs",
"plugin",
"qa",
"quality",
"standard",
"standards",
"style guide",
"stylecheck",
"tests"
],
"support": {
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
"time": "2022-02-04T12:51:07+00:00"
},
{
"name": "doctrine/instantiator",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9",
"ext-pdo": "*",
"ext-phar": "*",
"phpbench/phpbench": "^0.16 || ^1",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-phpunit": "^1",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"vimeo/psalm": "^4.22"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "https://ocramius.github.io/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://www.doctrine-project.org/projects/instantiator.html",
"keywords": [
"constructor",
"instantiate"
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/1.4.1"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
"type": "tidelift"
}
],
"time": "2022-03-03T08:28:38+00:00"
},
{
"name": "laminas/laminas-coding-standard",
"version": "2.4.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-coding-standard.git",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7",
"php": "^7.4 || ^8.0",
"slevomat/coding-standard": "^7.0",
"squizlabs/php_codesniffer": "^3.6",
"webimpress/coding-standard": "^1.2"
},
"conflict": {
"phpstan/phpdoc-parser": ">=1.6.0"
},
"type": "phpcodesniffer-standard",
"autoload": {
"psr-4": {
"LaminasCodingStandard\\": "src/LaminasCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Laminas Coding Standard",
"homepage": "https://laminas.dev",
"keywords": [
"Coding Standard",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-coding-standard/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-coding-standard/issues",
"rss": "https://github.com/laminas/laminas-coding-standard/releases.atom",
"source": "https://github.com/laminas/laminas-coding-standard"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-08-24T17:45:47+00:00"
},
{
"name": "myclabs/deep-copy",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"conflict": {
"doctrine/collections": "<1.6.8",
"doctrine/common": "<2.13.3 || >=3,<3.2.2"
},
"require-dev": {
"doctrine/collections": "^1.6.8",
"doctrine/common": "^2.13.3 || ^3.2.2",
"phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
},
"type": "library",
"autoload": {
"files": [
"src/DeepCopy/deep_copy.php"
],
"psr-4": {
"DeepCopy\\": "src/DeepCopy/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Create deep copies (clones) of your objects",
"keywords": [
"clone",
"copy",
"duplicate",
"object",
"object graph"
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
},
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
"type": "tidelift"
}
],
"time": "2022-03-03T13:19:32+00:00"
},
{
"name": "nikic/php-parser",
"version": "v4.15.1",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=7.0"
},
"require-dev": {
"ircmaxell/php-yacc": "^0.0.7",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
},
"bin": [
"bin/php-parse"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.9-dev"
}
},
"autoload": {
"psr-4": {
"PhpParser\\": "lib/PhpParser"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov"
}
],
"description": "A PHP parser written in PHP",
"keywords": [
"parser",
"php"
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1"
},
"time": "2022-09-04T07:30:47+00:00"
},
{
"name": "phar-io/manifest",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-phar": "*",
"ext-xmlwriter": "*",
"phar-io/version": "^3.0.1",
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
"support": {
"issues": "https://github.com/phar-io/manifest/issues",
"source": "https://github.com/phar-io/manifest/tree/2.0.3"
},
"time": "2021-07-20T11:28:43+00:00"
},
{
"name": "phar-io/version",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/phar-io/version.git",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Library for handling version information and constraints",
"support": {
"issues": "https://github.com/phar-io/version/issues",
"source": "https://github.com/phar-io/version/tree/3.2.1"
},
"time": "2022-02-21T01:04:05+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "981cc368a216c988e862a75e526b6076987d1b50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/981cc368a216c988e862a75e526b6076987d1b50",
"reference": "981cc368a216c988e862a75e526b6076987d1b50",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.5.1"
},
"time": "2022-05-05T11:32:40+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.17",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
"nikic/php-parser": "^4.14",
"php": ">=7.3",
"phpunit/php-file-iterator": "^3.0.3",
"phpunit/php-text-template": "^2.0.2",
"sebastian/code-unit-reverse-lookup": "^2.0.2",
"sebastian/complexity": "^2.0",
"sebastian/environment": "^5.1.2",
"sebastian/lines-of-code": "^1.0.3",
"sebastian/version": "^3.0.1",
"theseer/tokenizer": "^1.2.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcov": "*",
"ext-xdebug": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-08-30T12:24:04+00:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "3.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2021-12-02T12:48:52+00:00"
},
{
"name": "phpunit/php-invoker",
"version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-invoker.git",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"ext-pcntl": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcntl": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Invoke callables with a timeout",
"homepage": "https://github.com/sebastianbergmann/php-invoker/",
"keywords": [
"process"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-invoker/issues",
"source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:58:55+00:00"
},
{
"name": "phpunit/php-text-template",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
"source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T05:33:50+00:00"
},
{
"name": "phpunit/php-timer",
"version": "5.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-timer/issues",
"source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:16:10+00:00"
},
{
"name": "phpunit/phpunit",
"version": "9.5.25",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
"reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.3.1",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
"myclabs/deep-copy": "^1.10.1",
"phar-io/manifest": "^2.0.3",
"phar-io/version": "^3.0.2",
"php": ">=7.3",
"phpunit/php-code-coverage": "^9.2.13",
"phpunit/php-file-iterator": "^3.0.5",
"phpunit/php-invoker": "^3.1.1",
"phpunit/php-text-template": "^2.0.3",
"phpunit/php-timer": "^5.0.2",
"sebastian/cli-parser": "^1.0.1",
"sebastian/code-unit": "^1.0.6",
"sebastian/comparator": "^4.0.8",
"sebastian/diff": "^4.0.3",
"sebastian/environment": "^5.1.3",
"sebastian/exporter": "^4.0.5",
"sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3",
"sebastian/type": "^3.2",
"sebastian/version": "^3.0.2"
},
"suggest": {
"ext-soap": "*",
"ext-xdebug": "*"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.5-dev"
}
},
"autoload": {
"files": [
"src/Framework/Assert/Functions.php"
],
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.25"
},
"funding": [
{
"url": "https://phpunit.de/sponsors.html",
"type": "custom"
},
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
"type": "tidelift"
}
],
"time": "2022-09-25T03:44:45+00:00"
},
{
"name": "sebastian/cli-parser",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for parsing CLI options",
"homepage": "https://github.com/sebastianbergmann/cli-parser",
"support": {
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
"source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:08:49+00:00"
},
{
"name": "sebastian/code-unit",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit.git",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the PHP code units",
"homepage": "https://github.com/sebastianbergmann/code-unit",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit/issues",
"source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:08:54+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
"source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:30:19+00:00"
},
{
"name": "sebastian/comparator",
"version": "4.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/diff": "^4.0",
"sebastian/exporter": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "https://github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
"source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T12:41:17+00:00"
},
{
"name": "sebastian/complexity",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.7",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for calculating the complexity of PHP code units",
"homepage": "https://github.com/sebastianbergmann/complexity",
"support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues",
"source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T15:52:27+00:00"
},
{
"name": "sebastian/diff",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3",
"symfony/process": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
}
],
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
"diff",
"udiff",
"unidiff",
"unified diff"
],
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:10:38+00:00"
},
{
"name": "sebastian/environment",
"version": "5.1.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-posix": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"support": {
"issues": "https://github.com/sebastianbergmann/environment/issues",
"source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-04-03T09:37:03+00:00"
},
{
"name": "sebastian/exporter",
"version": "4.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-mbstring": "*",
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "https://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T06:03:37+00:00"
},
{
"name": "sebastian/global-state",
"version": "5.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-dom": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-uopz": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-02-14T08:28:10+00:00"
},
{
"name": "sebastian/lines-of-code",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.6",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for counting the lines of code in PHP source code",
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
"support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-11-28T06:42:11+00:00"
},
{
"name": "sebastian/object-enumerator",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
"source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:12:34+00:00"
},
{
"name": "sebastian/object-reflector",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Allows reflection of object attributes, including inherited and non-public ones",
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-reflector/issues",
"source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:14:26+00:00"
},
{
"name": "sebastian/recursion-context",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
"source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:17:30+00:00"
},
{
"name": "sebastian/resource-operations",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"support": {
"issues": "https://github.com/sebastianbergmann/resource-operations/issues",
"source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:45:17+00:00"
},
{
"name": "sebastian/type",
"version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the types of the PHP type system",
"homepage": "https://github.com/sebastianbergmann/type",
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
"source": "https://github.com/sebastianbergmann/type/tree/3.2.0"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-12T14:47:03+00:00"
},
{
"name": "sebastian/version",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "c6c1022351a901512170118436c764e473f6de8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
"reference": "c6c1022351a901512170118436c764e473f6de8c",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"support": {
"issues": "https://github.com/sebastianbergmann/version/issues",
"source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:39:44+00:00"
},
{
"name": "slevomat/coding-standard",
"version": "7.2.1",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
"php": "^7.2 || ^8.0",
"phpstan/phpdoc-parser": "^1.5.1",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phing/phing": "2.17.3",
"php-parallel-lint/php-parallel-lint": "1.3.2",
"phpstan/phpstan": "1.4.10|1.7.1",
"phpstan/phpstan-deprecation-rules": "1.0.0",
"phpstan/phpstan-phpunit": "1.0.0|1.1.1",
"phpstan/phpstan-strict-rules": "1.2.3",
"phpunit/phpunit": "7.5.20|8.5.21|9.5.20"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "7.x-dev"
}
},
"autoload": {
"psr-4": {
"SlevomatCodingStandard\\": "SlevomatCodingStandard"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
"source": "https://github.com/slevomat/coding-standard/tree/7.2.1"
},
"funding": [
{
"url": "https://github.com/kukulich",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
"type": "tidelift"
}
],
"time": "2022-05-25T10:58:12+00:00"
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.7.1",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"bin/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2022-06-18T07:21:10+00:00"
},
{
"name": "theseer/tokenizer",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
}
],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/1.2.1"
},
"funding": [
{
"url": "https://github.com/theseer",
"type": "github"
}
],
"time": "2021-07-28T10:34:58+00:00"
},
{
"name": "webimpress/coding-standard",
"version": "1.2.4",
"source": {
"type": "git",
"url": "https://github.com/webimpress/coding-standard.git",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webimpress/coding-standard/zipball/cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"shasum": ""
},
"require": {
"php": "^7.3 || ^8.0",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phpunit/phpunit": "^9.5.13"
},
"type": "phpcodesniffer-standard",
"extra": {
"dev-master": "1.2.x-dev",
"dev-develop": "1.3.x-dev"
},
"autoload": {
"psr-4": {
"WebimpressCodingStandard\\": "src/WebimpressCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-2-Clause"
],
"description": "Webimpress Coding Standard",
"keywords": [
"Coding Standard",
"PSR-2",
"phpcs",
"psr-12",
"webimpress"
],
"support": {
"issues": "https://github.com/webimpress/coding-standard/issues",
"source": "https://github.com/webimpress/coding-standard/tree/1.2.4"
},
"funding": [
{
"url": "https://github.com/michalbundyra",
"type": "github"
}
],
"time": "2022-02-15T19:52:12+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"ext-mbstring": "*"
},
"platform-dev": [],
"plugin-api-version": "2.2.0"
}
laminas-math/LICENSE.md 0000644 00000002732 15240152640 0010526 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of Laminas Foundation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
laminas-mime/src/Mime.php 0000644 00000044405 15240152640 0011312 0 ustar 00 <?php
namespace Laminas\Mime;
use function base64_encode;
use function chunk_split;
use function count;
use function implode;
use function max;
use function md5;
use function microtime;
use function ord;
use function preg_match;
use function rtrim;
use function sprintf;
use function str_replace;
use function strcspn;
use function strlen;
use function strpos;
use function strrpos;
use function strtoupper;
use function substr;
use function substr_replace;
use function trim;
/**
* Support class for MultiPart Mime Messages
*/
class Mime
{
// phpcs:disable Generic.Files.LineLength.TooLong
public const TYPE_OCTETSTREAM = 'application/octet-stream';
public const TYPE_TEXT = 'text/plain';
public const TYPE_HTML = 'text/html';
public const TYPE_ENRICHED = 'text/enriched';
public const TYPE_XML = 'text/xml';
public const ENCODING_7BIT = '7bit';
public const ENCODING_8BIT = '8bit';
public const ENCODING_QUOTEDPRINTABLE = 'quoted-printable';
public const ENCODING_BASE64 = 'base64';
public const DISPOSITION_ATTACHMENT = 'attachment';
public const DISPOSITION_INLINE = 'inline';
public const LINELENGTH = 72;
public const LINEEND = "\n";
public const MULTIPART_ALTERNATIVE = 'multipart/alternative';
public const MULTIPART_MIXED = 'multipart/mixed';
public const MULTIPART_RELATED = 'multipart/related';
public const MULTIPART_RELATIVE = 'multipart/relative';
public const MULTIPART_REPORT = 'multipart/report';
public const MESSAGE_RFC822 = 'message/rfc822';
public const MESSAGE_DELIVERY_STATUS = 'message/delivery-status';
public const CHARSET_REGEX = '#=\?(?P<charset>[\x21\x23-\x26\x2a\x2b\x2d\x5e\5f\60\x7b-\x7ea-zA-Z0-9]+)\?(?P<encoding>[\x21\x23-\x26\x2a\x2b\x2d\x5e\5f\60\x7b-\x7ea-zA-Z0-9]+)\?(?P<text>[\x21-\x3e\x40-\x7e]+)#';
// phpcs:enable
/** @var null|string */
protected $boundary;
/** @var int */
protected static $makeUnique = 0;
/**
* Lookup-tables for QuotedPrintable
*
* @var string[]
*/
public static $qpKeys = [
"\x00",
"\x01",
"\x02",
"\x03",
"\x04",
"\x05",
"\x06",
"\x07",
"\x08",
"\x09",
"\x0A",
"\x0B",
"\x0C",
"\x0D",
"\x0E",
"\x0F",
"\x10",
"\x11",
"\x12",
"\x13",
"\x14",
"\x15",
"\x16",
"\x17",
"\x18",
"\x19",
"\x1A",
"\x1B",
"\x1C",
"\x1D",
"\x1E",
"\x1F",
"\x7F",
"\x80",
"\x81",
"\x82",
"\x83",
"\x84",
"\x85",
"\x86",
"\x87",
"\x88",
"\x89",
"\x8A",
"\x8B",
"\x8C",
"\x8D",
"\x8E",
"\x8F",
"\x90",
"\x91",
"\x92",
"\x93",
"\x94",
"\x95",
"\x96",
"\x97",
"\x98",
"\x99",
"\x9A",
"\x9B",
"\x9C",
"\x9D",
"\x9E",
"\x9F",
"\xA0",
"\xA1",
"\xA2",
"\xA3",
"\xA4",
"\xA5",
"\xA6",
"\xA7",
"\xA8",
"\xA9",
"\xAA",
"\xAB",
"\xAC",
"\xAD",
"\xAE",
"\xAF",
"\xB0",
"\xB1",
"\xB2",
"\xB3",
"\xB4",
"\xB5",
"\xB6",
"\xB7",
"\xB8",
"\xB9",
"\xBA",
"\xBB",
"\xBC",
"\xBD",
"\xBE",
"\xBF",
"\xC0",
"\xC1",
"\xC2",
"\xC3",
"\xC4",
"\xC5",
"\xC6",
"\xC7",
"\xC8",
"\xC9",
"\xCA",
"\xCB",
"\xCC",
"\xCD",
"\xCE",
"\xCF",
"\xD0",
"\xD1",
"\xD2",
"\xD3",
"\xD4",
"\xD5",
"\xD6",
"\xD7",
"\xD8",
"\xD9",
"\xDA",
"\xDB",
"\xDC",
"\xDD",
"\xDE",
"\xDF",
"\xE0",
"\xE1",
"\xE2",
"\xE3",
"\xE4",
"\xE5",
"\xE6",
"\xE7",
"\xE8",
"\xE9",
"\xEA",
"\xEB",
"\xEC",
"\xED",
"\xEE",
"\xEF",
"\xF0",
"\xF1",
"\xF2",
"\xF3",
"\xF4",
"\xF5",
"\xF6",
"\xF7",
"\xF8",
"\xF9",
"\xFA",
"\xFB",
"\xFC",
"\xFD",
"\xFE",
"\xFF",
];
/** @var string[] */
public static $qpReplaceValues = [
"=00",
"=01",
"=02",
"=03",
"=04",
"=05",
"=06",
"=07",
"=08",
"=09",
"=0A",
"=0B",
"=0C",
"=0D",
"=0E",
"=0F",
"=10",
"=11",
"=12",
"=13",
"=14",
"=15",
"=16",
"=17",
"=18",
"=19",
"=1A",
"=1B",
"=1C",
"=1D",
"=1E",
"=1F",
"=7F",
"=80",
"=81",
"=82",
"=83",
"=84",
"=85",
"=86",
"=87",
"=88",
"=89",
"=8A",
"=8B",
"=8C",
"=8D",
"=8E",
"=8F",
"=90",
"=91",
"=92",
"=93",
"=94",
"=95",
"=96",
"=97",
"=98",
"=99",
"=9A",
"=9B",
"=9C",
"=9D",
"=9E",
"=9F",
"=A0",
"=A1",
"=A2",
"=A3",
"=A4",
"=A5",
"=A6",
"=A7",
"=A8",
"=A9",
"=AA",
"=AB",
"=AC",
"=AD",
"=AE",
"=AF",
"=B0",
"=B1",
"=B2",
"=B3",
"=B4",
"=B5",
"=B6",
"=B7",
"=B8",
"=B9",
"=BA",
"=BB",
"=BC",
"=BD",
"=BE",
"=BF",
"=C0",
"=C1",
"=C2",
"=C3",
"=C4",
"=C5",
"=C6",
"=C7",
"=C8",
"=C9",
"=CA",
"=CB",
"=CC",
"=CD",
"=CE",
"=CF",
"=D0",
"=D1",
"=D2",
"=D3",
"=D4",
"=D5",
"=D6",
"=D7",
"=D8",
"=D9",
"=DA",
"=DB",
"=DC",
"=DD",
"=DE",
"=DF",
"=E0",
"=E1",
"=E2",
"=E3",
"=E4",
"=E5",
"=E6",
"=E7",
"=E8",
"=E9",
"=EA",
"=EB",
"=EC",
"=ED",
"=EE",
"=EF",
"=F0",
"=F1",
"=F2",
"=F3",
"=F4",
"=F5",
"=F6",
"=F7",
"=F8",
"=F9",
"=FA",
"=FB",
"=FC",
"=FD",
"=FE",
"=FF",
];
// @codingStandardsIgnoreStart
public static $qpKeysString =
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF";
// @codingStandardsIgnoreEnd
/**
* Check if the given string is "printable"
*
* Checks that a string contains no unprintable characters. If this returns
* false, encode the string for secure delivery.
*
* @param string $str
* @return bool
*/
public static function isPrintable($str)
{
return strcspn($str, static::$qpKeysString) === strlen($str);
}
/**
* Encode a given string with the QUOTED_PRINTABLE mechanism and wrap the lines.
*
* @param string $str
* @param int $lineLength Defaults to {@link LINELENGTH}
* @param string $lineEnd Defaults to {@link LINEEND}
* @return string
*/
public static function encodeQuotedPrintable(
$str,
$lineLength = self::LINELENGTH,
$lineEnd = self::LINEEND
) {
$out = '';
$str = self::_encodeQuotedPrintable($str);
// Split encoded text into separate lines
$initialPtr = 0;
$strLength = strlen($str);
while ($initialPtr < $strLength) {
$continueAt = $strLength - $initialPtr;
if ($continueAt > $lineLength) {
$continueAt = $lineLength;
}
$chunk = substr($str, $initialPtr, $continueAt);
// Ensure we are not splitting across an encoded character
$endingMarkerPos = strrpos($chunk, '=');
if ($endingMarkerPos !== false && $endingMarkerPos >= strlen($chunk) - 2) {
$chunk = substr($chunk, 0, $endingMarkerPos);
$continueAt = $endingMarkerPos;
}
if (ord($chunk[0]) === 0x2E) { // 0x2E is a dot
$chunk = '=2E' . substr($chunk, 1);
}
// copied from swiftmailer https://git.io/vAXU1
switch (ord(substr($chunk, strlen($chunk) - 1))) {
case 0x09: // Horizontal Tab
$chunk = substr_replace($chunk, '=09', strlen($chunk) - 1, 1);
break;
case 0x20: // Space
$chunk = substr_replace($chunk, '=20', strlen($chunk) - 1, 1);
break;
}
// Add string and continue
$out .= $chunk . '=' . $lineEnd;
$initialPtr += $continueAt;
}
$out = rtrim($out, $lineEnd);
$out = rtrim($out, '=');
return $out;
}
/**
* Converts a string into quoted printable format.
*
* @param string $str
* @return string
*/
// @codingStandardsIgnoreStart
private static function _encodeQuotedPrintable($str)
{
// @codingStandardsIgnoreEnd
$str = str_replace('=', '=3D', $str);
$str = str_replace(static::$qpKeys, static::$qpReplaceValues, $str);
$str = rtrim($str);
return $str;
}
/**
* Encode a given string with the QUOTED_PRINTABLE mechanism for Mail Headers.
*
* Mail headers depend on an extended quoted printable algorithm otherwise
* a range of bugs can occur.
*
* @param string $str
* @param string $charset
* @param int $lineLength Defaults to {@link LINELENGTH}
* @param string $lineEnd Defaults to {@link LINEEND}
* @param positive-int|0 $headerNameSize When folding a line, it is necessary to calculate
* the length of the entire line (together with the header name).
* Therefore, you can specify the header name and colon length
* in this argument to fold the string properly.
* @return string
*/
public static function encodeQuotedPrintableHeader(
$str,
$charset,
$lineLength = self::LINELENGTH,
$lineEnd = self::LINEEND,
$headerNameSize = 0
) {
// Reduce line-length by the length of the required delimiter, charsets and encoding
$prefix = sprintf('=?%s?Q?', $charset);
$lineLength = $lineLength - strlen($prefix) - 3;
$str = self::_encodeQuotedPrintable($str);
// Mail-Header required chars have to be encoded also:
$str = str_replace(['?', ',', ' ', '_'], ['=3F', '=2C', '=20', '=5F'], $str);
// initialize first line, we need it anyways
$lines = [0 => ''];
// Split encoded text into separate lines
$tmp = '';
while (strlen($str) > 0) {
$currentLine = max(count($lines) - 1, 0);
$token = static::getNextQuotedPrintableToken($str);
$substr = substr($str, strlen($token));
$str = false === $substr ? '' : $substr;
$tmp .= $token;
if ($token === '=20') {
// only if we have a single char token or space, we can append the
// tempstring it to the current line or start a new line if necessary.
if ($currentLine === 0) {
// The size of the first line should be calculated with the header name.
$currentLineLength = strlen($lines[$currentLine] . $tmp) + $headerNameSize;
} else {
$currentLineLength = strlen($lines[$currentLine] . $tmp);
}
$lineLimitReached = $currentLineLength > $lineLength;
$noCurrentLine = $lines[$currentLine] === '';
if ($noCurrentLine && $lineLimitReached) {
$lines[$currentLine] = $tmp;
$lines[$currentLine + 1] = '';
} elseif ($lineLimitReached) {
$lines[$currentLine + 1] = $tmp;
} else {
$lines[$currentLine] .= $tmp;
}
$tmp = '';
}
// don't forget to append the rest to the last line
if (strlen($str) === 0) {
$lines[$currentLine] .= $tmp;
}
}
// assemble the lines together by pre- and appending delimiters, charset, encoding.
for ($i = 0, $count = count($lines); $i < $count; $i++) {
$lines[$i] = " " . $prefix . $lines[$i] . "?=";
}
$str = trim(implode($lineEnd, $lines));
return $str;
}
/**
* Retrieves the first token from a quoted printable string.
*
* @param string $str
* @return string
*/
private static function getNextQuotedPrintableToken($str)
{
if (0 === strpos($str, '=')) {
$token = substr($str, 0, 3);
} else {
$token = substr($str, 0, 1);
}
return $token;
}
/**
* Encode a given string in mail header compatible base64 encoding.
*
* @param string $str
* @param string $charset
* @param int $lineLength Defaults to {@link LINELENGTH}
* @param string $lineEnd Defaults to {@link LINEEND}
* @return string
*/
public static function encodeBase64Header(
$str,
$charset,
$lineLength = self::LINELENGTH,
$lineEnd = self::LINEEND
) {
$prefix = '=?' . $charset . '?B?';
$suffix = '?=';
$remainingLength = $lineLength - strlen($prefix) - strlen($suffix);
$encodedValue = static::encodeBase64($str, $remainingLength, $lineEnd);
$encodedValue = str_replace($lineEnd, $suffix . $lineEnd . ' ' . $prefix, $encodedValue);
$encodedValue = $prefix . $encodedValue . $suffix;
return $encodedValue;
}
/**
* Encode a given string in base64 encoding and break lines
* according to the maximum linelength.
*
* @param string $str
* @param int $lineLength Defaults to {@link LINELENGTH}
* @param string $lineEnd Defaults to {@link LINEEND}
* @return string
*/
public static function encodeBase64(
$str,
$lineLength = self::LINELENGTH,
$lineEnd = self::LINEEND
) {
$lineLength = $lineLength - ($lineLength % 4);
return rtrim(chunk_split(base64_encode($str), $lineLength, $lineEnd));
}
/**
* Constructor
*
* @param null|string $boundary
* @access public
*/
public function __construct($boundary = null)
{
// This string needs to be somewhat unique
if ($boundary === null) {
$this->boundary = '=_' . md5(microtime(1) . static::$makeUnique++);
} else {
$this->boundary = $boundary;
}
}
// phpcs:disable WebimpressCodingStandard.NamingConventions.ValidVariableName.NotCamelCaps
/**
* Encode the given string with the given encoding.
*
* @param string $str
* @param string $encoding
* @param string $EOL EOL string; defaults to {@link LINEEND}
* @return string
*/
public static function encode($str, $encoding, $EOL = self::LINEEND)
{
switch ($encoding) {
case self::ENCODING_BASE64:
return static::encodeBase64($str, self::LINELENGTH, $EOL);
case self::ENCODING_QUOTEDPRINTABLE:
return static::encodeQuotedPrintable($str, self::LINELENGTH, $EOL);
default:
/**
* @todo 7Bit and 8Bit is currently handled the same way.
*/
return $str;
}
}
/**
* Return a MIME boundary
*
* @access public
* @return string
*/
public function boundary()
{
return $this->boundary;
}
/**
* Return a MIME boundary line
*
* @param string $EOL Defaults to {@link LINEEND}
* @access public
* @return string
*/
public function boundaryLine($EOL = self::LINEEND)
{
return $EOL . '--' . $this->boundary . $EOL;
}
/**
* Return MIME ending
*
* @param string $EOL Defaults to {@link LINEEND}
* @access public
* @return string
*/
public function mimeEnd($EOL = self::LINEEND)
{
return $EOL . '--' . $this->boundary . '--' . $EOL;
}
/**
* Detect MIME charset
*
* Extract parts according to https://tools.ietf.org/html/rfc2047#section-2
*
* @param string $str
* @return string
*/
public static function mimeDetectCharset($str)
{
if (preg_match(self::CHARSET_REGEX, $str, $matches)) {
return strtoupper($matches['charset']);
}
return 'ASCII';
}
}
laminas-mime/src/Message.php 0000644 00000022646 15240152640 0012012 0 ustar 00 <?php // phpcs:disable WebimpressCodingStandard.NamingConventions.ValidVariableName.NotCamelCaps,PSR12.Files.FileHeader.SpacingAfterBlock,PSR2.Methods.MethodDeclaration.Underscore
namespace Laminas\Mime;
use Laminas\Mail\Header\HeaderInterface;
use Laminas\Mime\Mime;
use Laminas\Mime\Part;
use function array_keys;
use function base64_decode;
use function count;
use function current;
use function quoted_printable_decode;
use function sprintf;
use function strlen;
use function strpos;
use function strtolower;
use function substr;
use function trim;
class Message
{
/** @var Part[] */
protected $parts = [];
/** @var null|Mime */
protected $mime;
/**
* Returns the list of all Laminas\Mime\Part in the message
*
* @return Part[]
*/
public function getParts()
{
return $this->parts;
}
/**
* Sets the given array of Laminas\Mime\Part as the array for the message
*
* @param array $parts
* @return self
*/
public function setParts($parts)
{
$this->parts = $parts;
return $this;
}
/**
* Append a new Laminas\Mime\Part to the current message
*
* @throws Exception\InvalidArgumentException
* @return self
*/
public function addPart(Part $part)
{
foreach ($this->getParts() as $row) {
if ($part === $row) {
throw new Exception\InvalidArgumentException(sprintf(
'Provided part %s already defined.',
$part->getId()
));
}
}
$this->parts[] = $part;
return $this;
}
/**
* Check if message needs to be sent as multipart
* MIME message or if it has only one part.
*
* @return bool
*/
public function isMultiPart()
{
return count($this->parts) > 1;
}
/**
* Set Laminas\Mime\Mime object for the message
*
* This can be used to set the boundary specifically or to use a subclass of
* Laminas\Mime for generating the boundary.
*
* @return self
*/
public function setMime(Mime $mime)
{
$this->mime = $mime;
return $this;
}
/**
* Returns the Laminas\Mime\Mime object in use by the message
*
* If the object was not present, it is created and returned. Can be used to
* determine the boundary used in this message.
*
* @return Mime
*/
public function getMime()
{
if ($this->mime === null) {
$this->mime = new Mime();
}
return $this->mime;
}
/**
* Generate MIME-compliant message from the current configuration
*
* This can be a multipart message if more than one MIME part was added. If
* only one part is present, the content of this part is returned. If no
* part had been added, an empty string is returned.
*
* Parts are separated by the mime boundary as defined in Laminas\Mime\Mime. If
* {@link setMime()} has been called before this method, the Laminas\Mime\Mime
* object set by this call will be used. Otherwise, a new Laminas\Mime\Mime object
* is generated and used.
*
* @param string $EOL EOL string; defaults to {@link Laminas\Mime\Mime::LINEEND}
* @return string
*/
public function generateMessage($EOL = Mime::LINEEND)
{
if (! $this->isMultiPart()) {
if (empty($this->parts)) {
return '';
}
$part = current($this->parts);
$body = $part->getContent($EOL);
} else {
$mime = $this->getMime();
$boundaryLine = $mime->boundaryLine($EOL);
$body = 'This is a message in Mime Format. If you see this, '
. "your mail reader does not support this format." . $EOL;
foreach (array_keys($this->parts) as $p) {
$body .= $boundaryLine
. $this->getPartHeaders($p, $EOL)
. $EOL
. $this->getPartContent($p, $EOL);
}
$body .= $mime->mimeEnd($EOL);
}
return trim($body);
}
/**
* Get the headers of a given part as an array
*
* @param int $partnum
* @return array
*/
public function getPartHeadersArray($partnum)
{
return $this->parts[$partnum]->getHeadersArray();
}
/**
* Get the headers of a given part as a string
*
* @param int $partnum
* @param string $EOL
* @return string
*/
public function getPartHeaders($partnum, $EOL = Mime::LINEEND)
{
return $this->parts[$partnum]->getHeaders($EOL);
}
/**
* Get the (encoded) content of a given part as a string
*
* @param int $partnum
* @param string $EOL
* @return string
*/
public function getPartContent($partnum, $EOL = Mime::LINEEND)
{
return $this->parts[$partnum]->getContent($EOL);
}
/**
* Explode MIME multipart string into separate parts
*
* Parts consist of the header and the body of each MIME part.
*
* @param string $body
* @param string $boundary
* @throws Exception\RuntimeException
* @return array
*/
protected static function _disassembleMime($body, $boundary)
{
$start = 0;
$res = [];
// find every mime part limiter and cut out the
// string before it.
// the part before the first boundary string is discarded:
$p = strpos($body, '--' . $boundary . "\n", $start);
if ($p === false) {
// no parts found!
return [];
}
// position after first boundary line
$start = $p + 3 + strlen($boundary);
while (($p = strpos($body, '--' . $boundary . "\n", $start)) !== false) {
$res[] = substr($body, $start, $p - $start);
$start = $p + 3 + strlen($boundary);
}
// no more parts, find end boundary
$p = strpos($body, '--' . $boundary . '--', $start);
if ($p === false) {
throw new Exception\RuntimeException('Not a valid Mime Message: End Missing');
}
// the remaining part also needs to be parsed:
$res[] = substr($body, $start, $p - $start);
return $res;
}
/**
* Decodes a MIME encoded string and returns a Laminas\Mime\Message object with
* all the MIME parts set according to the given string
*
* @param string $message
* @param string $boundary Multipart boundary; if omitted, $message will be
* treated as a single part.
* @param string $EOL EOL string; defaults to {@link Laminas\Mime\Mime::LINEEND}
* @throws Exception\RuntimeException
* @return Message
*/
public static function createFromMessage($message, $boundary = null, $EOL = Mime::LINEEND)
{
if ($boundary) {
$parts = Decode::splitMessageStruct($message, $boundary, $EOL);
} else {
Decode::splitMessage($message, $headers, $body, $EOL);
$parts = [
[
'header' => $headers,
'body' => $body,
],
];
}
$res = new static();
foreach ($parts as $part) {
// now we build a new MimePart for the current Message Part:
$properties = [];
foreach ($part['header'] as $header) {
/** @var HeaderInterface $header */
/**
* @todo check for characterset and filename
*/
$fieldName = $header->getFieldName();
$fieldValue = $header->getFieldValue();
switch (strtolower($fieldName)) {
case 'content-type':
$properties['type'] = $fieldValue;
break;
case 'content-transfer-encoding':
$properties['encoding'] = $fieldValue;
break;
case 'content-id':
$properties['id'] = trim($fieldValue, '<>');
break;
case 'content-disposition':
$properties['disposition'] = $fieldValue;
break;
case 'content-description':
$properties['description'] = $fieldValue;
break;
case 'content-location':
$properties['location'] = $fieldValue;
break;
case 'content-language':
$properties['language'] = $fieldValue;
break;
default:
// Ignore unknown header
break;
}
}
$body = $part['body'];
if (isset($properties['encoding'])) {
switch ($properties['encoding']) {
case 'quoted-printable':
$body = quoted_printable_decode($body);
break;
case 'base64':
$body = base64_decode($body);
break;
}
}
$newPart = new Part($body);
foreach ($properties as $key => $value) {
$newPart->$key = $value;
}
$res->addPart($newPart);
}
return $res;
}
}
laminas-mime/src/Decode.php 0000644 00000021407 15240152640 0011603 0 ustar 00 <?php // phpcs:disable WebimpressCodingStandard.NamingConventions.ValidVariableName.NotCamelCaps
namespace Laminas\Mime;
use Laminas\Mail\Headers;
use Laminas\Stdlib\ErrorHandler;
use function count;
use function explode;
use function iconv_mime_decode;
use function preg_match;
use function preg_match_all;
use function preg_split;
use function str_replace;
use function strcasecmp;
use function strlen;
use function strpos;
use function strtok;
use function strtolower;
use function substr;
use const E_NOTICE;
use const E_WARNING;
use const ICONV_MIME_DECODE_CONTINUE_ON_ERROR;
class Decode
{
/**
* Explode MIME multipart string into separate parts
*
* Parts consist of the header and the body of each MIME part.
*
* @param string $body raw body of message
* @param string $boundary boundary as found in content-type
* @return array parts with content of each part, empty if no parts found
* @throws Exception\RuntimeException
*/
public static function splitMime($body, $boundary)
{
// TODO: we're ignoring \r for now - is this function fast enough and is it safe to assume noone needs \r?
$body = str_replace("\r", '', $body);
$start = 0;
$res = [];
// find every mime part limiter and cut out the
// string before it.
// the part before the first boundary string is discarded:
$p = strpos($body, '--' . $boundary . "\n", $start);
if ($p === false) {
// no parts found!
return [];
}
// position after first boundary line
$start = $p + 3 + strlen($boundary);
while (($p = strpos($body, '--' . $boundary . "\n", $start)) !== false) {
$res[] = substr($body, $start, $p - $start);
$start = $p + 3 + strlen($boundary);
}
// no more parts, find end boundary
$p = strpos($body, '--' . $boundary . '--', $start);
if ($p === false) {
throw new Exception\RuntimeException('Not a valid Mime Message: End Missing');
}
// the remaining part also needs to be parsed:
$res[] = substr($body, $start, $p - $start);
return $res;
}
/**
* decodes a mime encoded String and returns a
* struct of parts with header and body
*
* @param string $message raw message content
* @param string $boundary boundary as found in content-type
* @param string $EOL EOL string; defaults to {@link Laminas\Mime\Mime::LINEEND}
* @return array|null parts as array('header' => array(name => value), 'body' => content), null if no parts found
* @throws Exception\RuntimeException
*/
public static function splitMessageStruct($message, $boundary, $EOL = Mime::LINEEND)
{
$parts = static::splitMime($message, $boundary);
if (! $parts) {
return;
}
$result = [];
$headers = null; // "Declare" variable before the first usage "for reading"
$body = null; // "Declare" variable before the first usage "for reading"
foreach ($parts as $part) {
static::splitMessage($part, $headers, $body, $EOL);
$result[] = [
'header' => $headers,
'body' => $body,
];
}
return $result;
}
/**
* split a message in header and body part, if no header or an
* invalid header is found $headers is empty
*
* The charset of the returned headers depend on your iconv settings.
*
* @param string|Headers $message raw message with header and optional content
* @param Headers $headers output param, headers container
* @param string $body output param, content of message
* @param string $EOL EOL string; defaults to {@link Laminas\Mime\Mime::LINEEND}
* @param bool $strict enable strict mode for parsing message
* @return null
*/
public static function splitMessage($message, &$headers, &$body, $EOL = Mime::LINEEND, $strict = false)
{
if ($message instanceof Headers) {
$message = $message->toString();
}
// check for valid header at first line
$firstlinePos = strpos($message, "\n");
$firstline = $firstlinePos === false ? $message : substr($message, 0, $firstlinePos);
if (! preg_match('%^[^\s]+[^:]*:%', $firstline)) {
$headers = new Headers();
// TODO: we're ignoring \r for now - is this function fast enough and is it safe to assume noone needs \r?
$body = str_replace(["\r", "\n"], ['', $EOL], $message);
return;
}
// see @Laminas-372, pops the first line off a message if it doesn't contain a header
if (! $strict) {
$parts = explode(':', $firstline, 2);
if (count($parts) !== 2) {
$message = substr($message, strpos($message, $EOL) + 1);
}
}
// @todo splitMime removes "\r" sequences, which breaks valid mime
// messages as returned by many mail servers
$headersEOL = $EOL;
// find an empty line between headers and body
// default is set new line
// @todo Maybe this is too much "magic"; we should be more strict here
if (strpos($message, $EOL . $EOL)) {
[$headers, $body] = explode($EOL . $EOL, $message, 2);
// next is the standard new line
} elseif ($EOL !== "\r\n" && strpos($message, "\r\n\r\n")) {
[$headers, $body] = explode("\r\n\r\n", $message, 2);
$headersEOL = "\r\n"; // Headers::fromString will fail with incorrect EOL
// next is the other "standard" new line
} elseif ($EOL !== "\n" && strpos($message, "\n\n")) {
[$headers, $body] = explode("\n\n", $message, 2);
$headersEOL = "\n";
// at last resort find anything that looks like a new line
} else {
ErrorHandler::start(E_NOTICE | E_WARNING);
[$headers, $body] = preg_split("%([\r\n]+)\\1%U", $message, 2);
ErrorHandler::stop();
}
$headers = Headers::fromString($headers, $headersEOL);
}
/**
* split a content type in its different parts
*
* @param string $type content-type
* @param string $wantedPart the wanted part, else an array with all parts is returned
* @return string|array wanted part or all parts as array('type' => content-type, partname => value)
*/
public static function splitContentType($type, $wantedPart = null)
{
return static::splitHeaderField($type, $wantedPart, 'type');
}
/**
* split a header field like content type in its different parts
*
* @param string $field header field
* @param string $wantedPart the wanted part, else an array with all parts is returned
* @param string $firstName key name for the first part
* @return string|array wanted part or all parts as array($firstName => firstPart, partname => value)
* @throws Exception\RuntimeException
*/
public static function splitHeaderField($field, $wantedPart = null, $firstName = '0')
{
$wantedPart = strtolower($wantedPart ?? '');
$firstName = strtolower($firstName);
// special case - a bit optimized
if ($firstName === $wantedPart) {
$field = strtok($field, ';');
return $field[0] === '"' ? substr($field, 1, -1) : $field;
}
$field = $firstName . '=' . $field;
if (! preg_match_all('%([^=\s]+)\s*=\s*("[^"]+"|[^;]+)(;\s*|$)%', $field, $matches)) {
throw new Exception\RuntimeException('not a valid header field');
}
if ($wantedPart) {
foreach ($matches[1] as $key => $name) {
if (strcasecmp($name, $wantedPart)) {
continue;
}
if ($matches[2][$key][0] !== '"') {
return $matches[2][$key];
}
return substr($matches[2][$key], 1, -1);
}
return;
}
$split = [];
foreach ($matches[1] as $key => $name) {
$name = strtolower($name);
if ($matches[2][$key][0] === '"') {
$split[$name] = substr($matches[2][$key], 1, -1);
} else {
$split[$name] = $matches[2][$key];
}
}
return $split;
}
/**
* decode a quoted printable encoded string
*
* The charset of the returned string depends on your iconv settings.
*
* @param string $string encoded string
* @return string decoded string
*/
public static function decodeQuotedPrintable($string)
{
return iconv_mime_decode($string, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, 'UTF-8');
}
}
laminas-mime/src/Exception/InvalidArgumentException.php 0000644 00000000221 15240152640 0017315 0 ustar 00 <?php
namespace Laminas\Mime\Exception;
class InvalidArgumentException extends \InvalidArgumentException implements
ExceptionInterface
{
}
laminas-mime/src/Exception/ExceptionInterface.php 0000644 00000000113 15240152640 0016124 0 ustar 00 <?php
namespace Laminas\Mime\Exception;
interface ExceptionInterface
{
}
laminas-mime/src/Exception/RuntimeException.php 0000644 00000000256 15240152640 0015657 0 ustar 00 <?php
namespace Laminas\Mime\Exception;
/**
* Exception for Laminas\Mime component.
*/
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
laminas-mime/src/Part.php 0000644 00000027677 15240152640 0011345 0 ustar 00 <?php
namespace Laminas\Mime;
use function array_key_exists;
use function gettype;
use function is_object;
use function is_resource;
use function is_string;
use function rewind;
use function sprintf;
use function stream_filter_append;
use function stream_filter_remove;
use function stream_get_contents;
use function stream_get_meta_data;
use const STREAM_FILTER_READ;
/**
* Class representing a MIME part.
*/
class Part
{
/** @var string */
public $type = Mime::TYPE_OCTETSTREAM;
/** @var string */
public $encoding = Mime::ENCODING_8BIT;
/** @var null|string */
public $id;
/** @var null|string */
public $disposition;
/** @var null|string */
public $filename;
/** @var null|string */
public $description;
/** @var null|string */
public $charset;
/** @var null|string */
public $boundary;
/** @var null|string */
public $location;
/** @var null|string */
public $language;
/**
* String or stream containing the content
*
* @var string|resource
*/
protected $content;
/** @var bool */
protected $isStream = false;
/** @var array<array-key, resource> */
protected $filters = [];
/**
* create a new Mime Part.
* The (unencoded) content of the Part as passed
* as a string or stream
*
* @param mixed $content String or Stream containing the content
* @throws Exception\InvalidArgumentException
*/
public function __construct($content = '')
{
$this->setContent($content);
}
/**
* @todo error checking for setting $type
* @todo error checking for setting $encoding
*/
/**
* Set type
*
* @param string $type
* @return self
*/
public function setType($type = Mime::TYPE_OCTETSTREAM)
{
$this->type = $type;
return $this;
}
/**
* Get type
*
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* Set encoding
*
* @param string $encoding
* @return self
*/
public function setEncoding($encoding = Mime::ENCODING_8BIT)
{
$this->encoding = $encoding;
return $this;
}
/**
* Get encoding
*
* @return string
*/
public function getEncoding()
{
return $this->encoding;
}
/**
* Set id
*
* @param string $id
* @return self
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Get id
*
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* Set disposition
*
* @param string $disposition
* @return self
*/
public function setDisposition($disposition)
{
$this->disposition = $disposition;
return $this;
}
/**
* Get disposition
*
* @return string
*/
public function getDisposition()
{
return $this->disposition;
}
/**
* Set description
*
* @param string $description
* @return self
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set filename
*
* @param string $fileName
* @return self
*/
public function setFileName($fileName)
{
$this->filename = $fileName;
return $this;
}
/**
* Get filename
*
* @return string
*/
public function getFileName()
{
return $this->filename;
}
/**
* Set charset
*
* @param string $charset
* @return self
*/
public function setCharset($charset)
{
$this->charset = $charset;
return $this;
}
/**
* Get charset
*
* @return string
*/
public function getCharset()
{
return $this->charset;
}
/**
* Set boundary
*
* @param string $boundary
* @return self
*/
public function setBoundary($boundary)
{
$this->boundary = $boundary;
return $this;
}
/**
* Get boundary
*
* @return string
*/
public function getBoundary()
{
return $this->boundary;
}
/**
* Set location
*
* @param string $location
* @return self
*/
public function setLocation($location)
{
$this->location = $location;
return $this;
}
/**
* Get location
*
* @return string
*/
public function getLocation()
{
return $this->location;
}
/**
* Set language
*
* @param string $language
* @return self
*/
public function setLanguage($language)
{
$this->language = $language;
return $this;
}
/**
* Get language
*
* @return string
*/
public function getLanguage()
{
return $this->language;
}
/**
* Set content
*
* @param mixed $content String or Stream containing the content
* @throws Exception\InvalidArgumentException
* @return self
*/
public function setContent($content)
{
if (! is_string($content) && ! is_resource($content)) {
throw new Exception\InvalidArgumentException(sprintf(
'Content must be string or resource; received "%s"',
is_object($content) ? $content::class : gettype($content)
));
}
$this->content = $content;
if (is_resource($content)) {
$this->isStream = true;
}
return $this;
}
/**
* Set isStream
*
* @param bool $isStream
* @return self
*/
public function setIsStream($isStream = false)
{
$this->isStream = (bool) $isStream;
return $this;
}
/**
* Get isStream
*
* @return bool
*/
public function getIsStream()
{
return $this->isStream;
}
/**
* Set filters
*
* @param array<array-key, resource> $filters
* @return self
*/
public function setFilters($filters = [])
{
$this->filters = $filters;
return $this;
}
/**
* Get Filters
*
* @return array<array-key, resource>
*/
public function getFilters()
{
return $this->filters;
}
/**
* check if this part can be read as a stream.
* if true, getEncodedStream can be called, otherwise
* only getContent can be used to fetch the encoded
* content of the part
*
* @return bool
*/
public function isStream()
{
return $this->isStream;
}
// phpcs:disable WebimpressCodingStandard.NamingConventions.ValidVariableName.NotCamelCaps
/**
* if this was created with a stream, return a filtered stream for
* reading the content. very useful for large file attachments.
*
* @param string $EOL
* @return resource
* @throws Exception\RuntimeException If not a stream or unable to append filter.
*/
public function getEncodedStream($EOL = Mime::LINEEND)
{
if (! $this->isStream) {
throw new Exception\RuntimeException('Attempt to get a stream from a string part');
}
//stream_filter_remove(); // ??? is that right?
switch ($this->encoding) {
case Mime::ENCODING_QUOTEDPRINTABLE:
if (array_key_exists(Mime::ENCODING_QUOTEDPRINTABLE, $this->filters)) {
stream_filter_remove($this->filters[Mime::ENCODING_QUOTEDPRINTABLE]);
}
$filter = stream_filter_append(
$this->content,
'convert.quoted-printable-encode',
STREAM_FILTER_READ,
[
'line-length' => 76,
'line-break-chars' => $EOL,
]
);
$this->filters[Mime::ENCODING_QUOTEDPRINTABLE] = $filter;
if (! is_resource($filter)) {
throw new Exception\RuntimeException('Failed to append quoted-printable filter');
}
break;
case Mime::ENCODING_BASE64:
if (array_key_exists(Mime::ENCODING_BASE64, $this->filters)) {
stream_filter_remove($this->filters[Mime::ENCODING_BASE64]);
}
$filter = stream_filter_append(
$this->content,
'convert.base64-encode',
STREAM_FILTER_READ,
[
'line-length' => 76,
'line-break-chars' => $EOL,
]
);
$this->filters[Mime::ENCODING_BASE64] = $filter;
if (! is_resource($filter)) {
throw new Exception\RuntimeException('Failed to append base64 filter');
}
break;
default:
}
return $this->content;
}
/**
* Get the Content of the current Mime Part in the given encoding.
*
* @param string $EOL
* @return string
*/
public function getContent($EOL = Mime::LINEEND)
{
if ($this->isStream) {
$encodedStream = $this->getEncodedStream($EOL);
$encodedStreamContents = stream_get_contents($encodedStream);
$streamMetaData = stream_get_meta_data($encodedStream);
if (isset($streamMetaData['seekable']) && $streamMetaData['seekable']) {
rewind($encodedStream);
}
return $encodedStreamContents;
}
return Mime::encode($this->content, $this->encoding, $EOL);
}
/**
* Get the RAW unencoded content from this part
*
* @return string
*/
public function getRawContent()
{
if ($this->isStream) {
return stream_get_contents($this->content);
}
return $this->content;
}
/**
* Create and return the array of headers for this MIME part
*
* @access public
* @param string $EOL
* @return array
*/
public function getHeadersArray($EOL = Mime::LINEEND)
{
$headers = [];
$contentType = $this->type;
if ($this->charset) {
$contentType .= '; charset=' . $this->charset;
}
if ($this->boundary) {
$contentType .= ';' . $EOL
. " boundary=\"" . $this->boundary . '"';
}
$headers[] = ['Content-Type', $contentType];
if ($this->encoding) {
$headers[] = ['Content-Transfer-Encoding', $this->encoding];
}
if ($this->id) {
$headers[] = ['Content-ID', '<' . $this->id . '>'];
}
if ($this->disposition) {
$disposition = $this->disposition;
if ($this->filename) {
$disposition .= '; filename="' . $this->filename . '"';
}
$headers[] = ['Content-Disposition', $disposition];
}
if ($this->description) {
$headers[] = ['Content-Description', $this->description];
}
if ($this->location) {
$headers[] = ['Content-Location', $this->location];
}
if ($this->language) {
$headers[] = ['Content-Language', $this->language];
}
return $headers;
}
/**
* Return the headers for this part as a string
*
* @param string $EOL
* @return String
*/
public function getHeaders($EOL = Mime::LINEEND)
{
$res = '';
foreach ($this->getHeadersArray($EOL) as $header) {
$res .= $header[0] . ': ' . $header[1] . $EOL;
}
return $res;
}
}
laminas-mime/README.md 0000644 00000010373 15240152640 0010377 0 ustar 00 # laminas-mime
> ## 🇷🇺 Русским гражданам
>
> Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм.
>
> У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую.
>
> Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!"
>
> ## 🇺🇸 To Citizens of Russia
>
> We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism.
>
> One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences.
>
> You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!"
> This package is considered feature-complete, and is now in **security-only** maintenance mode, following a [decision by the Technical Steering Committee](https://github.com/laminas/technical-steering-committee/blob/2b55453e172a1b8c9c4c212be7cf7e7a58b9352c/meetings/minutes/2020-08-03-TSC-Minutes.md#vote-on-components-to-mark-as-security-only).
> If you have a security issue, please [follow our security reporting guidelines](https://getlaminas.org/security/).
> If you wish to take on the role of maintainer, please [nominate yourself](https://github.com/laminas/technical-steering-committee/issues/new?assignees=&labels=Nomination&template=Maintainer_Nomination.md&title=%5BNOMINATION%5D%5BMAINTAINER%5D%3A+%7Bname+of+person+being+nominated%7D)
>
> If you are looking for an actively maintained package alternative, we recommend:
>
> - [symfony/mime](https://symfony.com/doc/current/components/mime.html)
[](https://github.com/laminas/laminas-mime/actions?query=workflow%3A"Continuous+Integration")
`Laminas\Mime` is a support class for handling multipart MIME messages.
It is used by `Laminas\Mail` and `Laminas\Mime\Message` and may be used by applications requiring MIME support.
## Installation
Run the following to install this library:
```bash
$ composer require laminas/laminas-mime
```
## Documentation
Browse the documentation online at https://docs.laminas.dev/laminas-mime/
## Support
- [Issues](https://github.com/laminas/laminas-mime/issues/)
- [Chat](https://laminas.dev/chat/)
- [Forum](https://discourse.laminas.dev/)
laminas-mime/composer.json 0000644 00000003312 15240152640 0011635 0 ustar 00 {
"name": "laminas/laminas-mime",
"description": "Create and parse MIME messages and parts",
"license": "BSD-3-Clause",
"keywords": [
"laminas",
"mime"
],
"homepage": "https://laminas.dev",
"support": {
"docs": "https://docs.laminas.dev/laminas-mime/",
"issues": "https://github.com/laminas/laminas-mime/issues",
"source": "https://github.com/laminas/laminas-mime",
"rss": "https://github.com/laminas/laminas-mime/releases.atom",
"chat": "https://laminas.dev/chat",
"forum": "https://discourse.laminas.dev"
},
"config": {
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"laminas/laminas-stdlib": "^2.7 || ^3.0"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"laminas/laminas-mail": "^2.19.0",
"phpunit/phpunit": "~9.5.25"
},
"suggest": {
"laminas/laminas-mail": "Laminas\\Mail component"
},
"autoload": {
"psr-4": {
"Laminas\\Mime\\": "src/"
}
},
"autoload-dev": {
"files": [
"test/TestAsset/Mail/Headers.php"
],
"psr-4": {
"LaminasTest\\Mime\\": "test/"
}
},
"scripts": {
"check": [
"@cs-check",
"@test"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
},
"conflict": {
"zendframework/zend-mime": "*"
}
}
laminas-mime/COPYRIGHT.md 0000644 00000000133 15240152640 0011003 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/)
laminas-mime/composer.lock 0000644 00000321147 15240152641 0011626 0 ustar 00 {
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "00a80a7fc74e8f70b9c97ea3791a1d84",
"packages": [
{
"name": "laminas/laminas-stdlib",
"version": "3.15.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-stdlib.git",
"reference": "63b66bd4b696f024f42616b9d95cdb10e5109c27"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/63b66bd4b696f024f42616b9d95cdb10e5109c27",
"reference": "63b66bd4b696f024f42616b9d95cdb10e5109c27",
"shasum": ""
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-stdlib": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "^2.4.0",
"phpbench/phpbench": "^1.2.6",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.28"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Stdlib\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "SPL extensions, array utilities, error handlers, and more",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"stdlib"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-stdlib/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-stdlib/issues",
"rss": "https://github.com/laminas/laminas-stdlib/releases.atom",
"source": "https://github.com/laminas/laminas-stdlib"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-10T19:10:24+00:00"
}
],
"packages-dev": [
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
"version": "v0.7.2",
"source": {
"type": "git",
"url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
"phpcompatibility/php-compatibility": "^9.0"
},
"type": "composer-plugin",
"extra": {
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
"Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Franck Nijhof",
"email": "franck.nijhof@dealerdirect.com",
"homepage": "http://www.frenck.nl",
"role": "Developer / IT Manager"
},
{
"name": "Contributors",
"homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
"homepage": "http://www.dealerdirect.com",
"keywords": [
"PHPCodeSniffer",
"PHP_CodeSniffer",
"code quality",
"codesniffer",
"composer",
"installer",
"phpcbf",
"phpcs",
"plugin",
"qa",
"quality",
"standard",
"standards",
"style guide",
"stylecheck",
"tests"
],
"support": {
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
"time": "2022-02-04T12:51:07+00:00"
},
{
"name": "doctrine/instantiator",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9",
"ext-pdo": "*",
"ext-phar": "*",
"phpbench/phpbench": "^0.16 || ^1",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-phpunit": "^1",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"vimeo/psalm": "^4.22"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "https://ocramius.github.io/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://www.doctrine-project.org/projects/instantiator.html",
"keywords": [
"constructor",
"instantiate"
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/1.4.1"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
"type": "tidelift"
}
],
"time": "2022-03-03T08:28:38+00:00"
},
{
"name": "laminas/laminas-coding-standard",
"version": "2.4.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-coding-standard.git",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7",
"php": "^7.4 || ^8.0",
"slevomat/coding-standard": "^7.0",
"squizlabs/php_codesniffer": "^3.6",
"webimpress/coding-standard": "^1.2"
},
"conflict": {
"phpstan/phpdoc-parser": ">=1.6.0"
},
"type": "phpcodesniffer-standard",
"autoload": {
"psr-4": {
"LaminasCodingStandard\\": "src/LaminasCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Laminas Coding Standard",
"homepage": "https://laminas.dev",
"keywords": [
"Coding Standard",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-coding-standard/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-coding-standard/issues",
"rss": "https://github.com/laminas/laminas-coding-standard/releases.atom",
"source": "https://github.com/laminas/laminas-coding-standard"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-08-24T17:45:47+00:00"
},
{
"name": "laminas/laminas-loader",
"version": "2.9.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-loader.git",
"reference": "51ed9c3fa42d1098a9997571730c0cbf42d078d3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-loader/zipball/51ed9c3fa42d1098a9997571730c0cbf42d078d3",
"reference": "51ed9c3fa42d1098a9997571730c0cbf42d078d3",
"shasum": ""
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-loader": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"phpunit/phpunit": "~9.5.25"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Loader\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Autoloading and plugin loading strategies",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"loader"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-loader/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-loader/issues",
"rss": "https://github.com/laminas/laminas-loader/releases.atom",
"source": "https://github.com/laminas/laminas-loader"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-16T12:50:49+00:00"
},
{
"name": "laminas/laminas-mail",
"version": "2.19.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-mail.git",
"reference": "edf3832c05165775589af2fc698b5f9984d4c5f1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-mail/zipball/edf3832c05165775589af2fc698b5f9984d4c5f1",
"reference": "edf3832c05165775589af2fc698b5f9984d4c5f1",
"shasum": ""
},
"require": {
"ext-iconv": "*",
"laminas/laminas-loader": "^2.8.0",
"laminas/laminas-mime": "^2.10.0",
"laminas/laminas-stdlib": "^3.11.0",
"laminas/laminas-validator": "^2.23.0",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"symfony/polyfill-intl-idn": "^1.26.0",
"symfony/polyfill-mbstring": "^1.16.0",
"webmozart/assert": "^1.11.0"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"laminas/laminas-crypt": "^3.8.0",
"laminas/laminas-db": "^2.15.0",
"laminas/laminas-servicemanager": "^3.19",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"symfony/process": "^6.0.11",
"vimeo/psalm": "^4.29"
},
"suggest": {
"laminas/laminas-crypt": "^3.8 Crammd5 support in SMTP Auth",
"laminas/laminas-servicemanager": "^3.16 when using SMTP to deliver messages"
},
"type": "library",
"extra": {
"laminas": {
"component": "Laminas\\Mail",
"config-provider": "Laminas\\Mail\\ConfigProvider"
}
},
"autoload": {
"psr-4": {
"Laminas\\Mail\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Provides generalized functionality to compose and send both text and MIME-compliant multipart e-mail messages",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"mail"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-mail/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-mail/issues",
"rss": "https://github.com/laminas/laminas-mail/releases.atom",
"source": "https://github.com/laminas/laminas-mail"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-14T13:05:29+00:00"
},
{
"name": "laminas/laminas-servicemanager",
"version": "3.19.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-servicemanager.git",
"reference": "ed160729bb8721127efdaac799f9a298963345b1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/ed160729bb8721127efdaac799f9a298963345b1",
"reference": "ed160729bb8721127efdaac799f9a298963345b1",
"shasum": ""
},
"require": {
"laminas/laminas-stdlib": "^3.2.1",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"psr/container": "^1.0"
},
"conflict": {
"ext-psr": "*",
"laminas/laminas-code": "<3.3.1",
"zendframework/zend-code": "<3.3.1",
"zendframework/zend-servicemanager": "*"
},
"provide": {
"psr/container-implementation": "^1.0"
},
"replace": {
"container-interop/container-interop": "^1.2.0"
},
"require-dev": {
"composer/package-versions-deprecated": "^1.11.99.5",
"laminas/laminas-coding-standard": "~2.4.0",
"laminas/laminas-container-config-test": "^0.7",
"laminas/laminas-dependency-plugin": "^2.2",
"mikey179/vfsstream": "^1.6.11@alpha",
"ocramius/proxy-manager": "^2.14.1",
"phpbench/phpbench": "^1.2.6",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.28"
},
"suggest": {
"ocramius/proxy-manager": "ProxyManager ^2.1.1 to handle lazy initialization of services"
},
"bin": [
"bin/generate-deps-for-config-factory",
"bin/generate-factory-for-class"
],
"type": "library",
"autoload": {
"files": [
"src/autoload.php"
],
"psr-4": {
"Laminas\\ServiceManager\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Factory-Driven Dependency Injection Container",
"homepage": "https://laminas.dev",
"keywords": [
"PSR-11",
"dependency-injection",
"di",
"dic",
"laminas",
"service-manager",
"servicemanager"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-servicemanager/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-servicemanager/issues",
"rss": "https://github.com/laminas/laminas-servicemanager/releases.atom",
"source": "https://github.com/laminas/laminas-servicemanager"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-10T20:59:22+00:00"
},
{
"name": "laminas/laminas-validator",
"version": "2.26.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-validator.git",
"reference": "a995b21d18c63cd1f5d123d0d2cd31a1c2d828dc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-validator/zipball/a995b21d18c63cd1f5d123d0d2cd31a1c2d828dc",
"reference": "a995b21d18c63cd1f5d123d0d2cd31a1c2d828dc",
"shasum": ""
},
"require": {
"laminas/laminas-servicemanager": "^3.12.0",
"laminas/laminas-stdlib": "^3.13",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-validator": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "^2.4.0",
"laminas/laminas-db": "^2.15.0",
"laminas/laminas-filter": "^2.22",
"laminas/laminas-http": "^2.16.0",
"laminas/laminas-i18n": "^2.19",
"laminas/laminas-session": "^2.13.0",
"laminas/laminas-uri": "^2.9.1",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"psr/http-client": "^1.0.1",
"psr/http-factory": "^1.0.1",
"psr/http-message": "^1.0.1",
"vimeo/psalm": "^4.28"
},
"suggest": {
"laminas/laminas-db": "Laminas\\Db component, required by the (No)RecordExists validator",
"laminas/laminas-filter": "Laminas\\Filter component, required by the Digits validator",
"laminas/laminas-i18n": "Laminas\\I18n component to allow translation of validation error messages",
"laminas/laminas-i18n-resources": "Translations of validator messages",
"laminas/laminas-servicemanager": "Laminas\\ServiceManager component to allow using the ValidatorPluginManager and validator chains",
"laminas/laminas-session": "Laminas\\Session component, ^2.8; required by the Csrf validator",
"laminas/laminas-uri": "Laminas\\Uri component, required by the Uri and Sitemap\\Loc validators",
"psr/http-message": "psr/http-message, required when validating PSR-7 UploadedFileInterface instances via the Upload and UploadFile validators"
},
"type": "library",
"extra": {
"laminas": {
"component": "Laminas\\Validator",
"config-provider": "Laminas\\Validator\\ConfigProvider"
}
},
"autoload": {
"psr-4": {
"Laminas\\Validator\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Validation classes for a wide range of domains, and the ability to chain validators to create complex validation criteria",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"validator"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-validator/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-validator/issues",
"rss": "https://github.com/laminas/laminas-validator/releases.atom",
"source": "https://github.com/laminas/laminas-validator"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-11T12:58:36+00:00"
},
{
"name": "myclabs/deep-copy",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"conflict": {
"doctrine/collections": "<1.6.8",
"doctrine/common": "<2.13.3 || >=3,<3.2.2"
},
"require-dev": {
"doctrine/collections": "^1.6.8",
"doctrine/common": "^2.13.3 || ^3.2.2",
"phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
},
"type": "library",
"autoload": {
"files": [
"src/DeepCopy/deep_copy.php"
],
"psr-4": {
"DeepCopy\\": "src/DeepCopy/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Create deep copies (clones) of your objects",
"keywords": [
"clone",
"copy",
"duplicate",
"object",
"object graph"
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
},
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
"type": "tidelift"
}
],
"time": "2022-03-03T13:19:32+00:00"
},
{
"name": "nikic/php-parser",
"version": "v4.15.1",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=7.0"
},
"require-dev": {
"ircmaxell/php-yacc": "^0.0.7",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
},
"bin": [
"bin/php-parse"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.9-dev"
}
},
"autoload": {
"psr-4": {
"PhpParser\\": "lib/PhpParser"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov"
}
],
"description": "A PHP parser written in PHP",
"keywords": [
"parser",
"php"
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1"
},
"time": "2022-09-04T07:30:47+00:00"
},
{
"name": "phar-io/manifest",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-phar": "*",
"ext-xmlwriter": "*",
"phar-io/version": "^3.0.1",
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
"support": {
"issues": "https://github.com/phar-io/manifest/issues",
"source": "https://github.com/phar-io/manifest/tree/2.0.3"
},
"time": "2021-07-20T11:28:43+00:00"
},
{
"name": "phar-io/version",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/phar-io/version.git",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Library for handling version information and constraints",
"support": {
"issues": "https://github.com/phar-io/version/issues",
"source": "https://github.com/phar-io/version/tree/3.2.1"
},
"time": "2022-02-21T01:04:05+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "981cc368a216c988e862a75e526b6076987d1b50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/981cc368a216c988e862a75e526b6076987d1b50",
"reference": "981cc368a216c988e862a75e526b6076987d1b50",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.5.1"
},
"time": "2022-05-05T11:32:40+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.17",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
"nikic/php-parser": "^4.14",
"php": ">=7.3",
"phpunit/php-file-iterator": "^3.0.3",
"phpunit/php-text-template": "^2.0.2",
"sebastian/code-unit-reverse-lookup": "^2.0.2",
"sebastian/complexity": "^2.0",
"sebastian/environment": "^5.1.2",
"sebastian/lines-of-code": "^1.0.3",
"sebastian/version": "^3.0.1",
"theseer/tokenizer": "^1.2.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcov": "*",
"ext-xdebug": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-08-30T12:24:04+00:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "3.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2021-12-02T12:48:52+00:00"
},
{
"name": "phpunit/php-invoker",
"version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-invoker.git",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"ext-pcntl": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcntl": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Invoke callables with a timeout",
"homepage": "https://github.com/sebastianbergmann/php-invoker/",
"keywords": [
"process"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-invoker/issues",
"source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:58:55+00:00"
},
{
"name": "phpunit/php-text-template",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
"source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T05:33:50+00:00"
},
{
"name": "phpunit/php-timer",
"version": "5.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-timer/issues",
"source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:16:10+00:00"
},
{
"name": "phpunit/phpunit",
"version": "9.5.25",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
"reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.3.1",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
"myclabs/deep-copy": "^1.10.1",
"phar-io/manifest": "^2.0.3",
"phar-io/version": "^3.0.2",
"php": ">=7.3",
"phpunit/php-code-coverage": "^9.2.13",
"phpunit/php-file-iterator": "^3.0.5",
"phpunit/php-invoker": "^3.1.1",
"phpunit/php-text-template": "^2.0.3",
"phpunit/php-timer": "^5.0.2",
"sebastian/cli-parser": "^1.0.1",
"sebastian/code-unit": "^1.0.6",
"sebastian/comparator": "^4.0.8",
"sebastian/diff": "^4.0.3",
"sebastian/environment": "^5.1.3",
"sebastian/exporter": "^4.0.5",
"sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3",
"sebastian/type": "^3.2",
"sebastian/version": "^3.0.2"
},
"suggest": {
"ext-soap": "*",
"ext-xdebug": "*"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.5-dev"
}
},
"autoload": {
"files": [
"src/Framework/Assert/Functions.php"
],
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.25"
},
"funding": [
{
"url": "https://phpunit.de/sponsors.html",
"type": "custom"
},
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
"type": "tidelift"
}
],
"time": "2022-09-25T03:44:45+00:00"
},
{
"name": "psr/container",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
"shasum": ""
},
"require": {
"php": ">=7.4.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
"homepage": "https://github.com/php-fig/container",
"keywords": [
"PSR-11",
"container",
"container-interface",
"container-interop",
"psr"
],
"support": {
"issues": "https://github.com/php-fig/container/issues",
"source": "https://github.com/php-fig/container/tree/1.1.2"
},
"time": "2021-11-05T16:50:12+00:00"
},
{
"name": "sebastian/cli-parser",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for parsing CLI options",
"homepage": "https://github.com/sebastianbergmann/cli-parser",
"support": {
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
"source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:08:49+00:00"
},
{
"name": "sebastian/code-unit",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit.git",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the PHP code units",
"homepage": "https://github.com/sebastianbergmann/code-unit",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit/issues",
"source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:08:54+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
"source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:30:19+00:00"
},
{
"name": "sebastian/comparator",
"version": "4.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/diff": "^4.0",
"sebastian/exporter": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "https://github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
"source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T12:41:17+00:00"
},
{
"name": "sebastian/complexity",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.7",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for calculating the complexity of PHP code units",
"homepage": "https://github.com/sebastianbergmann/complexity",
"support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues",
"source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T15:52:27+00:00"
},
{
"name": "sebastian/diff",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3",
"symfony/process": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
}
],
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
"diff",
"udiff",
"unidiff",
"unified diff"
],
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:10:38+00:00"
},
{
"name": "sebastian/environment",
"version": "5.1.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-posix": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"support": {
"issues": "https://github.com/sebastianbergmann/environment/issues",
"source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-04-03T09:37:03+00:00"
},
{
"name": "sebastian/exporter",
"version": "4.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-mbstring": "*",
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "https://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T06:03:37+00:00"
},
{
"name": "sebastian/global-state",
"version": "5.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-dom": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-uopz": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-02-14T08:28:10+00:00"
},
{
"name": "sebastian/lines-of-code",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.6",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for counting the lines of code in PHP source code",
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
"support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-11-28T06:42:11+00:00"
},
{
"name": "sebastian/object-enumerator",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
"source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:12:34+00:00"
},
{
"name": "sebastian/object-reflector",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Allows reflection of object attributes, including inherited and non-public ones",
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-reflector/issues",
"source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:14:26+00:00"
},
{
"name": "sebastian/recursion-context",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
"source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:17:30+00:00"
},
{
"name": "sebastian/resource-operations",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"support": {
"issues": "https://github.com/sebastianbergmann/resource-operations/issues",
"source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:45:17+00:00"
},
{
"name": "sebastian/type",
"version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the types of the PHP type system",
"homepage": "https://github.com/sebastianbergmann/type",
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
"source": "https://github.com/sebastianbergmann/type/tree/3.2.0"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-12T14:47:03+00:00"
},
{
"name": "sebastian/version",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "c6c1022351a901512170118436c764e473f6de8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
"reference": "c6c1022351a901512170118436c764e473f6de8c",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"support": {
"issues": "https://github.com/sebastianbergmann/version/issues",
"source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:39:44+00:00"
},
{
"name": "slevomat/coding-standard",
"version": "7.2.1",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
"php": "^7.2 || ^8.0",
"phpstan/phpdoc-parser": "^1.5.1",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phing/phing": "2.17.3",
"php-parallel-lint/php-parallel-lint": "1.3.2",
"phpstan/phpstan": "1.4.10|1.7.1",
"phpstan/phpstan-deprecation-rules": "1.0.0",
"phpstan/phpstan-phpunit": "1.0.0|1.1.1",
"phpstan/phpstan-strict-rules": "1.2.3",
"phpunit/phpunit": "7.5.20|8.5.21|9.5.20"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "7.x-dev"
}
},
"autoload": {
"psr-4": {
"SlevomatCodingStandard\\": "SlevomatCodingStandard"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
"source": "https://github.com/slevomat/coding-standard/tree/7.2.1"
},
"funding": [
{
"url": "https://github.com/kukulich",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
"type": "tidelift"
}
],
"time": "2022-05-25T10:58:12+00:00"
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.7.1",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"bin/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2022-06-18T07:21:10+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
"shasum": ""
},
"require": {
"php": ">=7.1",
"symfony/polyfill-intl-normalizer": "^1.10",
"symfony/polyfill-php72": "^1.10"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Idn\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Laurent Bassin",
"email": "laurent@bassin.info"
},
{
"name": "Trevor Rowbotham",
"email": "trevor.rowbotham@pm.me"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"idn",
"intl",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.26.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's Normalizer class and related functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"intl",
"normalizer",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-mbstring": "*"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2",
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php72\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "theseer/tokenizer",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
}
],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/1.2.1"
},
"funding": [
{
"url": "https://github.com/theseer",
"type": "github"
}
],
"time": "2021-07-28T10:34:58+00:00"
},
{
"name": "webimpress/coding-standard",
"version": "1.2.4",
"source": {
"type": "git",
"url": "https://github.com/webimpress/coding-standard.git",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webimpress/coding-standard/zipball/cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"shasum": ""
},
"require": {
"php": "^7.3 || ^8.0",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phpunit/phpunit": "^9.5.13"
},
"type": "phpcodesniffer-standard",
"extra": {
"dev-master": "1.2.x-dev",
"dev-develop": "1.3.x-dev"
},
"autoload": {
"psr-4": {
"WebimpressCodingStandard\\": "src/WebimpressCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-2-Clause"
],
"description": "Webimpress Coding Standard",
"keywords": [
"Coding Standard",
"PSR-2",
"phpcs",
"psr-12",
"webimpress"
],
"support": {
"issues": "https://github.com/webimpress/coding-standard/issues",
"source": "https://github.com/webimpress/coding-standard/tree/1.2.4"
},
"funding": [
{
"url": "https://github.com/michalbundyra",
"type": "github"
}
],
"time": "2022-02-15T19:52:12+00:00"
},
{
"name": "webmozart/assert",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/webmozarts/assert.git",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"php": "^7.2 || ^8.0"
},
"conflict": {
"phpstan/phpstan": "<0.12.20",
"vimeo/psalm": "<4.6.1 || 4.6.2"
},
"require-dev": {
"phpunit/phpunit": "^8.5.13"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.10-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\Assert\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Assertions to validate method input/output with nice error messages.",
"keywords": [
"assert",
"check",
"validate"
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.11.0"
},
"time": "2022-06-03T18:03:27+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"platform-dev": [],
"plugin-api-version": "2.2.0"
}
laminas-mime/LICENSE.md 0000644 00000002732 15240152641 0010525 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of Laminas Foundation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
laminas-mime/.laminas-ci/pre-install.sh 0000644 00000000250 15240152641 0013773 0 ustar 00 #!/bin/bash
# Temporary workaround for cyclic dependencies - can be removed once 3.0 has been released
echo "Branch as 2.99.x in Pre-Install"
git checkout -b 2.99.x
laminas-loader/src/SplAutoloader.php 0000644 00000002526 15240152641 0013517 0 ustar 00 <?php // phpcs:disable WebimpressCodingStandard.NamingConventions.Interface.Suffix
namespace Laminas\Loader;
use Traversable;
use function interface_exists;
if (interface_exists(SplAutoloader::class)) {
return;
}
/**
* Defines an interface for classes that may register with the spl_autoload
* registry
*/
interface SplAutoloader
{
/**
* Constructor
*
* Allow configuration of the autoloader via the constructor.
*
* @param null|array|Traversable $options
*/
public function __construct($options = null);
/**
* Configure the autoloader
*
* In most cases, $options should be either an associative array or
* Traversable object.
*
* @param array|Traversable $options
* @return SplAutoloader
*/
public function setOptions($options);
/**
* Autoload a class
*
* @param string $class
* @return mixed
* False [if unable to load $class]
* get_class($class) [if $class is successfully loaded]
*/
public function autoload($class);
/**
* Register the autoloader with spl_autoload registry
*
* Typically, the body of this will simply be:
* <code>
* spl_autoload_register(array($this, 'autoload'));
* </code>
*
* @return void
*/
public function register();
}
laminas-loader/src/ShortNameLocator.php 0000644 00000001216 15240152641 0014160 0 ustar 00 <?php // phpcs:disable WebimpressCodingStandard.NamingConventions.Interface.Suffix
namespace Laminas\Loader;
/**
* Short name locator interface
*/
interface ShortNameLocator
{
/**
* Whether or not a Helper by a specific name
*
* @param string $name
* @return bool
*/
public function isLoaded($name);
/**
* Return full class name for a named helper
*
* @param string $name
* @return string
*/
public function getClassName($name);
/**
* Load a helper via the name provided
*
* @param string $name
* @return string
*/
public function load($name);
}
laminas-loader/src/ModuleAutoloader.php 0000644 00000032172 15240152641 0014206 0 ustar 00 <?php
namespace Laminas\Loader;
// Grab SplAutoloader interface
require_once __DIR__ . '/SplAutoloader.php';
use GlobIterator;
use InvalidArgumentException;
use Phar;
use PharFileInfo;
use SplFileInfo;
use Traversable;
use function array_map;
use function class_exists;
use function count;
use function extension_loaded;
use function getcwd;
use function gettype;
use function implode;
use function in_array;
use function is_array;
use function is_string;
use function pathinfo;
use function preg_match;
use function realpath;
use function rtrim;
use function spl_autoload_register;
use function spl_autoload_unregister;
use function sprintf;
use function str_replace;
use function strpos;
use function substr;
use const DIRECTORY_SEPARATOR;
class ModuleAutoloader implements SplAutoloader
{
/** @var array An array of module paths to scan */
protected $paths = [];
/** @var array An array of modulename => path */
protected $explicitPaths = [];
/** @var array An array of namespaceName => namespacePath */
protected $namespacedPaths = [];
/** @var string Will contain the absolute phar:// path to the executable when packaged as phar file */
protected $pharBasePath = "";
/** @var array An array of supported phar extensions (filled on constructor) */
protected $pharExtensions = [];
/** @var array An array of module classes to their containing files */
protected $moduleClassMap = [];
/**
* Constructor
*
* Allow configuration of the autoloader via the constructor.
*
* @param null|array|Traversable $options
*/
public function __construct($options = null)
{
if (extension_loaded('phar')) {
$this->pharBasePath = Phar::running(true);
$this->pharExtensions = [
'phar',
'phar.tar',
'tar',
];
// ext/zlib enabled -> phar can read gzip & zip compressed files
if (extension_loaded('zlib')) {
$this->pharExtensions[] = 'phar.gz';
$this->pharExtensions[] = 'phar.tar.gz';
$this->pharExtensions[] = 'tar.gz';
$this->pharExtensions[] = 'phar.zip';
$this->pharExtensions[] = 'zip';
}
// ext/bzip2 enabled -> phar can read bz2 compressed files
if (extension_loaded('bzip2')) {
$this->pharExtensions[] = 'phar.bz2';
$this->pharExtensions[] = 'phar.tar.bz2';
$this->pharExtensions[] = 'tar.bz2';
}
}
if (null !== $options) {
$this->setOptions($options);
}
}
/**
* Configure the autoloader
*
* In most cases, $options should be either an associative array or
* Traversable object.
*
* @param array|Traversable $options
* @return ModuleAutoloader
*/
public function setOptions($options)
{
$this->registerPaths($options);
return $this;
}
/**
* Retrieves the class map for all loaded modules.
*
* @return array
*/
public function getModuleClassMap()
{
return $this->moduleClassMap;
}
/**
* Sets the class map used to speed up the module autoloading.
*
* @param array $classmap
* @return ModuleAutoloader
*/
public function setModuleClassMap(array $classmap)
{
$this->moduleClassMap = $classmap;
return $this;
}
/**
* Autoload a class
*
* @param string $class
* @return mixed
* False [if unable to load $class]
* get_class($class) [if $class is successfully loaded]
*/
public function autoload($class)
{
// Limit scope of this autoloader
if (substr($class, -7) !== '\Module') {
return false;
}
if (isset($this->moduleClassMap[$class])) {
require_once $this->moduleClassMap[$class];
return $class;
}
$moduleName = substr($class, 0, -7);
if (isset($this->explicitPaths[$moduleName])) {
$classLoaded = $this->loadModuleFromDir($this->explicitPaths[$moduleName], $class);
if ($classLoaded) {
return $classLoaded;
}
$classLoaded = $this->loadModuleFromPhar($this->explicitPaths[$moduleName], $class);
if ($classLoaded) {
return $classLoaded;
}
}
if (count($this->namespacedPaths) >= 1) {
foreach ($this->namespacedPaths as $namespace => $path) {
if (false === strpos($moduleName, $namespace)) {
continue;
}
$moduleNameBuffer = str_replace($namespace . "\\", "", $moduleName);
$path .= DIRECTORY_SEPARATOR . $moduleNameBuffer . DIRECTORY_SEPARATOR;
$classLoaded = $this->loadModuleFromDir($path, $class);
if ($classLoaded) {
return $classLoaded;
}
$classLoaded = $this->loadModuleFromPhar($path, $class);
if ($classLoaded) {
return $classLoaded;
}
}
}
$moduleClassPath = str_replace('\\', DIRECTORY_SEPARATOR, $moduleName);
$pharSuffixPattern = null;
if ($this->pharExtensions) {
$pharSuffixPattern = '(' . implode('|', array_map('preg_quote', $this->pharExtensions)) . ')';
}
foreach ($this->paths as $path) {
$path .= $moduleClassPath;
if ($path === '.' || substr($path, 0, 2) === './' || substr($path, 0, 2) === '.\\') {
if (! $basePath = $this->pharBasePath) {
$basePath = realpath('.');
}
if (false === $basePath) {
$basePath = getcwd();
}
$path = rtrim($basePath, '\/\\') . substr($path, 1);
}
$classLoaded = $this->loadModuleFromDir($path, $class);
if ($classLoaded) {
return $classLoaded;
}
// No directory with Module.php, searching for phars
if ($pharSuffixPattern) {
foreach (new GlobIterator($path . '.*') as $entry) {
if ($entry->isDir()) {
continue;
}
if (! preg_match('#.+\.' . $pharSuffixPattern . '$#', $entry->getPathname())) {
continue;
}
$classLoaded = $this->loadModuleFromPhar($entry->getPathname(), $class);
if ($classLoaded) {
return $classLoaded;
}
}
}
}
return false;
}
/**
* loadModuleFromDir
*
* @param string $dirPath
* @param string $class
* @return mixed
* False [if unable to load $class]
* get_class($class) [if $class is successfully loaded]
*/
protected function loadModuleFromDir($dirPath, $class)
{
$modulePath = $dirPath . '/Module.php';
if (substr($modulePath, 0, 7) === 'phar://') {
$file = new PharFileInfo($modulePath);
} else {
$file = new SplFileInfo($modulePath);
}
if ($file->isReadable() && $file->isFile()) {
// Found directory with Module.php in it
$absModulePath = $this->pharBasePath ? (string) $file : $file->getRealPath();
require_once $absModulePath;
if (class_exists($class)) {
$this->moduleClassMap[$class] = $absModulePath;
return $class;
}
}
return false;
}
/**
* loadModuleFromPhar
*
* @param string $pharPath
* @param string $class
* @return mixed
* False [if unable to load $class]
* get_class($class) [if $class is successfully loaded]
*/
protected function loadModuleFromPhar($pharPath, $class)
{
$pharPath = static::normalizePath($pharPath, false);
$file = new SplFileInfo($pharPath);
if (! $file->isReadable() || ! $file->isFile()) {
return false;
}
$fileRealPath = $file->getRealPath();
// Phase 0: Check for executable phar with Module class in stub
if (strpos($fileRealPath, '.phar') !== false) {
// First see if the stub makes the Module class available
require_once $fileRealPath;
if (class_exists($class)) {
$this->moduleClassMap[$class] = $fileRealPath;
return $class;
}
}
// Phase 1: Not executable phar, no stub, or stub did not provide Module class; try Module.php directly
$moduleClassFile = 'phar://' . $fileRealPath . '/Module.php';
$moduleFile = new SplFileInfo($moduleClassFile);
if ($moduleFile->isReadable() && $moduleFile->isFile()) {
require_once $moduleClassFile;
if (class_exists($class)) {
$this->moduleClassMap[$class] = $moduleClassFile;
return $class;
}
}
// Phase 2: Check for nested module directory within archive
// Checks for /path/to/MyModule.tar/MyModule/Module.php
// (shell-integrated zip/tar utilities wrap directories like this)
$pharBaseName = $this->pharFileToModuleName($fileRealPath);
$moduleClassFile = 'phar://' . $fileRealPath . '/' . $pharBaseName . '/Module.php';
$moduleFile = new SplFileInfo($moduleClassFile);
if ($moduleFile->isReadable() && $moduleFile->isFile()) {
require_once $moduleClassFile;
if (class_exists($class)) {
$this->moduleClassMap[$class] = $moduleClassFile;
return $class;
}
}
return false;
}
/**
* Register the autoloader with spl_autoload registry
*
* @return void
*/
public function register()
{
spl_autoload_register([$this, 'autoload']);
}
/**
* Unregister the autoloader with spl_autoload registry
*
* @return void
*/
public function unregister()
{
spl_autoload_unregister([$this, 'autoload']);
}
/**
* registerPaths
*
* @param array|Traversable $paths
* @throws InvalidArgumentException
* @return ModuleAutoloader
*/
public function registerPaths($paths)
{
if (! is_array($paths) && ! $paths instanceof Traversable) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(
'Parameter to \\Laminas\\Loader\\ModuleAutoloader\'s '
. 'registerPaths method must be an array or '
. 'implement the Traversable interface'
);
}
foreach ($paths as $module => $path) {
if (is_string($module)) {
$this->registerPath($path, $module);
} else {
$this->registerPath($path);
}
}
return $this;
}
/**
* registerPath
*
* @param string $path
* @param bool|string $moduleName
* @throws InvalidArgumentException
* @return ModuleAutoloader
*/
public function registerPath($path, $moduleName = false)
{
if (! is_string($path)) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(sprintf(
'Invalid path provided; must be a string, received %s',
gettype($path)
));
}
if ($moduleName) {
if (in_array(substr($moduleName, -2), ['\\*', '\\%'])) {
$this->namespacedPaths[substr($moduleName, 0, -2)] = static::normalizePath($path);
} else {
$this->explicitPaths[$moduleName] = static::normalizePath($path);
}
} else {
$this->paths[] = static::normalizePath($path);
}
return $this;
}
/**
* getPaths
*
* This is primarily for unit testing, but could have other uses.
*
* @return array
*/
public function getPaths()
{
return $this->paths;
}
/**
* Returns the base module name from the path to a phar
*
* @param string $pharPath
* @return string
*/
protected function pharFileToModuleName($pharPath)
{
do {
$pathinfo = pathinfo($pharPath);
$pharPath = $pathinfo['filename'];
} while (isset($pathinfo['extension']));
return $pathinfo['filename'];
}
/**
* Normalize a path for insertion in the stack
*
* @param string $path
* @param bool $trailingSlash Whether trailing slash should be included
* @return string
*/
public static function normalizePath($path, $trailingSlash = true)
{
$path = rtrim($path, '/');
$path = rtrim($path, '\\');
if ($trailingSlash) {
$path .= DIRECTORY_SEPARATOR;
}
return $path;
}
}
laminas-loader/src/Exception/PluginLoaderException.php 0000644 00000000276 15240152641 0017143 0 ustar 00 <?php
namespace Laminas\Loader\Exception;
require_once __DIR__ . '/DomainException.php';
/**
* Plugin class loader exceptions
*/
class PluginLoaderException extends DomainException
{
}
laminas-loader/src/Exception/InvalidPathException.php 0000644 00000000276 15240152641 0016761 0 ustar 00 <?php
namespace Laminas\Loader\Exception;
use Exception;
require_once __DIR__ . '/ExceptionInterface.php';
class InvalidPathException extends Exception implements ExceptionInterface
{
}
laminas-loader/src/Exception/InvalidArgumentException.php 0000644 00000000302 15240152641 0017635 0 ustar 00 <?php
namespace Laminas\Loader\Exception;
require_once __DIR__ . '/ExceptionInterface.php';
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
laminas-loader/src/Exception/SecurityException.php 0000644 00000000220 15240152642 0016353 0 ustar 00 <?php
namespace Laminas\Loader\Exception;
require_once __DIR__ . '/DomainException.php';
class SecurityException extends DomainException
{
}
laminas-loader/src/Exception/ExceptionInterface.php 0000644 00000000115 15240152642 0016447 0 ustar 00 <?php
namespace Laminas\Loader\Exception;
interface ExceptionInterface
{
}
laminas-loader/src/Exception/DomainException.php 0000644 00000000260 15240152642 0015757 0 ustar 00 <?php
namespace Laminas\Loader\Exception;
require_once __DIR__ . '/ExceptionInterface.php';
class DomainException extends \DomainException implements ExceptionInterface
{
}
laminas-loader/src/Exception/BadMethodCallException.php 0000644 00000000302 15240152642 0017170 0 ustar 00 <?php
namespace Laminas\Loader\Exception;
require_once __DIR__ . '/ExceptionInterface.php';
class BadMethodCallException extends \BadMethodCallException implements
ExceptionInterface
{
}
laminas-loader/src/Exception/RuntimeException.php 0000644 00000000262 15240152642 0016175 0 ustar 00 <?php
namespace Laminas\Loader\Exception;
require_once __DIR__ . '/ExceptionInterface.php';
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
laminas-loader/src/Exception/MissingResourceNamespaceException.php 0000644 00000000313 15240152642 0021505 0 ustar 00 <?php
namespace Laminas\Loader\Exception;
use Exception;
require_once __DIR__ . '/ExceptionInterface.php';
class MissingResourceNamespaceException extends Exception implements ExceptionInterface
{
}
laminas-loader/src/PluginClassLocator.php 0000644 00000001451 15240152642 0014506 0 ustar 00 <?php // phpcs:disable WebimpressCodingStandard.NamingConventions.Interface.Suffix
namespace Laminas\Loader;
use IteratorAggregate;
use Traversable;
/**
* Plugin class locator interface
*/
interface PluginClassLocator extends ShortNameLocator, IteratorAggregate
{
/**
* Register a class to a given short name
*
* @param string $shortName
* @param string $className
* @return PluginClassLocator
*/
public function registerPlugin($shortName, $className);
/**
* Unregister a short name lookup
*
* @param mixed $shortName
* @return void
*/
public function unregisterPlugin($shortName);
/**
* Get a list of all registered plugins
*
* @return array|Traversable
*/
public function getRegisteredPlugins();
}
laminas-loader/src/StandardAutoloader.php 0000644 00000024125 15240152642 0014521 0 ustar 00 <?php
namespace Laminas\Loader;
use Traversable;
use function dirname;
use function file_exists;
use function in_array;
use function is_array;
use function preg_match;
use function rtrim;
use function spl_autoload_register;
use function str_replace;
use function stream_resolve_include_path;
use function strlen;
use function strpos;
use function substr;
use const DIRECTORY_SEPARATOR;
// Grab SplAutoloader interface
require_once __DIR__ . '/SplAutoloader.php';
/**
* PSR-0 compliant autoloader
*
* Allows autoloading both namespaced and vendor-prefixed classes. Class
* lookups are performed on the filesystem. If a class file for the referenced
* class is not found, a PHP warning will be raised by include().
*/
class StandardAutoloader implements SplAutoloader
{
public const NS_SEPARATOR = '\\';
public const PREFIX_SEPARATOR = '_';
public const LOAD_NS = 'namespaces';
public const LOAD_PREFIX = 'prefixes';
public const ACT_AS_FALLBACK = 'fallback_autoloader';
/** @deprecated Use AUTOREGISTER_LAMINAS instead */
public const AUTOREGISTER_ZF = 'autoregister_laminas';
public const AUTOREGISTER_LAMINAS = 'autoregister_laminas';
/** @var array Namespace/directory pairs to search; Laminas library added by default */
protected $namespaces = [];
/** @var array Prefix/directory pairs to search */
protected $prefixes = [];
/** @var bool Whether or not the autoloader should also act as a fallback autoloader */
protected $fallbackAutoloaderFlag = false;
/**
* Constructor
*
* @param null|array|Traversable $options
*/
public function __construct($options = null)
{
if (null !== $options) {
$this->setOptions($options);
}
}
/**
* Configure autoloader
*
* Allows specifying both "namespace" and "prefix" pairs, using the
* following structure:
* <code>
* array(
* 'namespaces' => array(
* 'Laminas' => '/path/to/Laminas/library',
* 'Doctrine' => '/path/to/Doctrine/library',
* ),
* 'prefixes' => array(
* 'Phly_' => '/path/to/Phly/library',
* ),
* 'fallback_autoloader' => true,
* )
* </code>
*
* @param array|Traversable $options
* @throws Exception\InvalidArgumentException
* @return StandardAutoloader
*/
public function setOptions($options)
{
if (! is_array($options) && ! $options instanceof Traversable) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException('Options must be either an array or Traversable');
}
foreach ($options as $type => $pairs) {
switch ($type) {
case self::AUTOREGISTER_LAMINAS:
if ($pairs) {
$this->registerNamespace('Laminas', dirname(__DIR__));
}
break;
case self::LOAD_NS:
if (is_array($pairs) || $pairs instanceof Traversable) {
$this->registerNamespaces($pairs);
}
break;
case self::LOAD_PREFIX:
if (is_array($pairs) || $pairs instanceof Traversable) {
$this->registerPrefixes($pairs);
}
break;
case self::ACT_AS_FALLBACK:
$this->setFallbackAutoloader($pairs);
break;
default:
// ignore
}
}
return $this;
}
/**
* Set flag indicating fallback autoloader status
*
* @param bool $flag
* @return StandardAutoloader
*/
public function setFallbackAutoloader($flag)
{
$this->fallbackAutoloaderFlag = (bool) $flag;
return $this;
}
/**
* Is this autoloader acting as a fallback autoloader?
*
* @return bool
*/
public function isFallbackAutoloader()
{
return $this->fallbackAutoloaderFlag;
}
/**
* Register a namespace/directory pair
*
* @param string $namespace
* @param string $directory
* @return StandardAutoloader
*/
public function registerNamespace($namespace, $directory)
{
$namespace = rtrim($namespace, self::NS_SEPARATOR) . self::NS_SEPARATOR;
$this->namespaces[$namespace] = $this->normalizeDirectory($directory);
return $this;
}
/**
* Register many namespace/directory pairs at once
*
* @param array $namespaces
* @throws Exception\InvalidArgumentException
* @return StandardAutoloader
*/
public function registerNamespaces($namespaces)
{
if (! is_array($namespaces) && ! $namespaces instanceof Traversable) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException('Namespace pairs must be either an array or Traversable');
}
foreach ($namespaces as $namespace => $directory) {
$this->registerNamespace($namespace, $directory);
}
return $this;
}
/**
* Register a prefix/directory pair
*
* @param string $prefix
* @param string $directory
* @return StandardAutoloader
*/
public function registerPrefix($prefix, $directory)
{
$prefix = rtrim($prefix, self::PREFIX_SEPARATOR) . self::PREFIX_SEPARATOR;
$this->prefixes[$prefix] = $this->normalizeDirectory($directory);
return $this;
}
/**
* Register many namespace/directory pairs at once
*
* @param array $prefixes
* @throws Exception\InvalidArgumentException
* @return StandardAutoloader
*/
public function registerPrefixes($prefixes)
{
if (! is_array($prefixes) && ! $prefixes instanceof Traversable) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException('Prefix pairs must be either an array or Traversable');
}
foreach ($prefixes as $prefix => $directory) {
$this->registerPrefix($prefix, $directory);
}
return $this;
}
/**
* Defined by Autoloadable; autoload a class
*
* @param string $class
* @return false|string
*/
public function autoload($class)
{
$isFallback = $this->isFallbackAutoloader();
if (false !== strpos($class, self::NS_SEPARATOR)) {
if ($this->loadClass($class, self::LOAD_NS)) {
return $class;
} elseif ($isFallback) {
return $this->loadClass($class, self::ACT_AS_FALLBACK);
}
return false;
}
if (false !== strpos($class, self::PREFIX_SEPARATOR)) {
if ($this->loadClass($class, self::LOAD_PREFIX)) {
return $class;
} elseif ($isFallback) {
return $this->loadClass($class, self::ACT_AS_FALLBACK);
}
return false;
}
if ($isFallback) {
return $this->loadClass($class, self::ACT_AS_FALLBACK);
}
return false;
}
/**
* Register the autoloader with spl_autoload
*
* @return void
*/
public function register()
{
spl_autoload_register([$this, 'autoload']);
}
/**
* Transform the class name to a filename
*
* @param string $class
* @param string $directory
* @return string
*/
protected function transformClassNameToFilename($class, $directory)
{
// $class may contain a namespace portion, in which case we need
// to preserve any underscores in that portion.
$matches = [];
preg_match('/(?P<namespace>.+\\\)?(?P<class>[^\\\]+$)/', $class, $matches);
$class = $matches['class'] ?? '';
$namespace = $matches['namespace'] ?? '';
return $directory
. str_replace(self::NS_SEPARATOR, '/', $namespace)
. str_replace(self::PREFIX_SEPARATOR, '/', $class)
. '.php';
}
/**
* Load a class, based on its type (namespaced or prefixed)
*
* @param string $class
* @param string $type
* @return bool|string
* @throws Exception\InvalidArgumentException
*/
protected function loadClass($class, $type)
{
if (! in_array($type, [self::LOAD_NS, self::LOAD_PREFIX, self::ACT_AS_FALLBACK])) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException();
}
// Fallback autoloading
if ($type === self::ACT_AS_FALLBACK) {
// create filename
$filename = $this->transformClassNameToFilename($class, '');
$resolvedName = stream_resolve_include_path($filename);
if ($resolvedName !== false) {
return include $resolvedName;
}
return false;
}
// Namespace and/or prefix autoloading
foreach ($this->$type as $leader => $path) {
if (0 === strpos($class, $leader)) {
// Trim off leader (namespace or prefix)
$trimmedClass = substr($class, strlen($leader));
// create filename
$filename = $this->transformClassNameToFilename($trimmedClass, $path);
if (file_exists($filename)) {
return include $filename;
}
}
}
return false;
}
/**
* Normalize the directory to include a trailing directory separator
*
* @param string $directory
* @return string
*/
protected function normalizeDirectory($directory)
{
$last = $directory[strlen($directory) - 1];
if (in_array($last, ['/', '\\'])) {
$directory[strlen($directory) - 1] = DIRECTORY_SEPARATOR;
return $directory;
}
$directory .= DIRECTORY_SEPARATOR;
return $directory;
}
}
laminas-loader/src/ClassMapAutoloader.php 0000644 00000013654 15240152642 0014471 0 ustar 00 <?php
namespace Laminas\Loader;
use Traversable;
use function array_filter;
use function array_values;
use function array_walk;
use function explode;
use function file_exists;
use function gettype;
use function implode;
use function in_array;
use function is_array;
use function is_string;
use function preg_match;
use function realpath;
use function spl_autoload_register;
use function sprintf;
use function str_pad;
use function str_replace;
use function strlen;
use function substr;
// Grab SplAutoloader interface
require_once __DIR__ . '/SplAutoloader.php';
/**
* Class-map autoloader
*
* Utilizes class-map files to lookup classfile locations.
*/
class ClassMapAutoloader implements SplAutoloader
{
/**
* Registry of map files that have already been loaded
*
* @var array
*/
protected $mapsLoaded = [];
/**
* Class name/filename map
*
* @var array
*/
protected $map = [];
/**
* Constructor
*
* Create a new instance, and optionally configure the autoloader.
*
* @param null|array|Traversable $options
*/
public function __construct($options = null)
{
if (null !== $options) {
$this->setOptions($options);
}
}
/**
* Configure the autoloader
*
* Proxies to {@link registerAutoloadMaps()}.
*
* @param array|Traversable $options
* @return ClassMapAutoloader
*/
public function setOptions($options)
{
$this->registerAutoloadMaps($options);
return $this;
}
/**
* Register an autoload map
*
* An autoload map may be either an associative array, or a file returning
* an associative array.
*
* An autoload map should be an associative array containing
* classname/file pairs.
*
* @param string|array $map
* @throws Exception\InvalidArgumentException
* @return ClassMapAutoloader
*/
public function registerAutoloadMap($map)
{
if (is_string($map)) {
$location = $map;
if ($this === ($map = $this->loadMapFromFile($location))) {
return $this;
}
}
if (! is_array($map)) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(sprintf(
'Map file provided does not return a map. Map file: "%s"',
isset($location) && is_string($location) ? $location : 'unexpected type: ' . gettype($map)
));
}
$this->map = $map + $this->map;
if (isset($location)) {
$this->mapsLoaded[] = $location;
}
return $this;
}
/**
* Register many autoload maps at once
*
* @param array $locations
* @throws Exception\InvalidArgumentException
* @return ClassMapAutoloader
*/
public function registerAutoloadMaps($locations)
{
if (! is_array($locations) && ! $locations instanceof Traversable) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException('Map list must be an array or implement Traversable');
}
foreach ($locations as $location) {
$this->registerAutoloadMap($location);
}
return $this;
}
/**
* Retrieve current autoload map
*
* @return array
*/
public function getAutoloadMap()
{
return $this->map;
}
/**
* {@inheritDoc}
*/
public function autoload($class)
{
if (isset($this->map[$class])) {
require_once $this->map[$class];
return $class;
}
return false;
}
/**
* Register the autoloader with spl_autoload registry
*
* @return void
*/
public function register()
{
spl_autoload_register([$this, 'autoload'], true, true);
}
/**
* Load a map from a file
*
* If the map has been previously loaded, returns the current instance;
* otherwise, returns whatever was returned by calling include() on the
* location.
*
* @param string $location
* @return ClassMapAutoloader|mixed
* @throws Exception\InvalidArgumentException For nonexistent locations.
*/
protected function loadMapFromFile($location)
{
if (! file_exists($location)) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(sprintf(
'Map file provided does not exist. Map file: "%s"',
is_string($location) ? $location : 'unexpected type: ' . gettype($location)
));
}
if (! $path = static::realPharPath($location)) {
$path = realpath($location);
}
if (in_array($path, $this->mapsLoaded)) {
// Already loaded this map
return $this;
}
return include $path;
}
/**
* Resolve the real_path() to a file within a phar.
*
* @see https://bugs.php.net/bug.php?id=52769
*
* @param string $path
* @return string
*/
public static function realPharPath($path)
{
if (! preg_match('|^phar:(/{2,3})|', $path, $match)) {
return;
}
$prefixLength = 5 + strlen($match[1]);
$parts = explode('/', str_replace(['/', '\\'], '/', substr($path, $prefixLength)));
$parts = array_values(array_filter($parts, function ($p) {
return $p !== '' && $p !== '.';
}));
array_walk($parts, function ($value, $key) use (&$parts) {
if ($value === '..') {
unset($parts[$key], $parts[$key - 1]);
$parts = array_values($parts);
}
});
if (file_exists($realPath = str_pad('phar:', $prefixLength, '/') . implode('/', $parts))) {
return $realPath;
}
}
}
laminas-loader/src/AutoloaderFactory.php 0000644 00000016107 15240152642 0014371 0 ustar 00 <?php
namespace Laminas\Loader;
use Laminas\Loader\SplAutoloader;
use Laminas\Loader\StandardAutoloader;
use Traversable;
use function class_exists;
use function is_array;
use function is_subclass_of;
use function spl_autoload_unregister;
use function sprintf;
use function strrchr;
use function substr;
if (class_exists(AutoloaderFactory::class)) {
return;
}
// phpcs:ignore WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix
abstract class AutoloaderFactory
{
public const STANDARD_AUTOLOADER = StandardAutoloader::class;
/** @var array All autoloaders registered using the factory */
protected static $loaders = [];
/**
* @var StandardAutoloader StandardAutoloader instance for resolving
* autoloader classes via the include_path
*/
protected static $standardAutoloader;
/**
* Factory for autoloaders
*
* Options should be an array or Traversable object of the following structure:
* <code>
* array(
* '<autoloader class name>' => $autoloaderOptions,
* )
* </code>
*
* The factory will then loop through and instantiate each autoloader with
* the specified options, and register each with the spl_autoloader.
*
* You may retrieve the concrete autoloader instances later using
* {@link getRegisteredAutoloaders()}.
*
* Note that the class names must be resolvable on the include_path or via
* the Laminas library, using PSR-0 rules (unless the class has already been
* loaded).
*
* @param array|Traversable $options (optional) options to use. Defaults to Laminas\Loader\StandardAutoloader
* @return void
* @throws Exception\InvalidArgumentException For invalid options.
* @throws Exception\InvalidArgumentException For unloadable autoloader classes.
* @throws Exception\DomainException For autoloader classes not implementing SplAutoloader.
*/
public static function factory($options = null)
{
if (null === $options) {
if (! isset(static::$loaders[static::STANDARD_AUTOLOADER])) {
$autoloader = static::getStandardAutoloader();
$autoloader->register();
static::$loaders[static::STANDARD_AUTOLOADER] = $autoloader;
}
// Return so we don't hit the next check's exception (we're done here anyway)
return;
}
if (! is_array($options) && ! $options instanceof Traversable) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(
'Options provided must be an array or Traversable'
);
}
foreach ($options as $class => $autoloaderOptions) {
if (! isset(static::$loaders[$class])) {
$autoloader = static::getStandardAutoloader();
if (! class_exists($class) && ! $autoloader->autoload($class)) {
require_once 'Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(
sprintf('Autoloader class "%s" not loaded', $class)
);
}
if (! is_subclass_of($class, SplAutoloader::class)) {
require_once 'Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(
sprintf('Autoloader class %s must implement Laminas\\Loader\\SplAutoloader', $class)
);
}
if ($class === static::STANDARD_AUTOLOADER) {
$autoloader->setOptions($autoloaderOptions);
} else {
$autoloader = new $class($autoloaderOptions);
}
$autoloader->register();
static::$loaders[$class] = $autoloader;
} else {
static::$loaders[$class]->setOptions($autoloaderOptions);
}
}
}
/**
* Get a list of all autoloaders registered with the factory
*
* Returns an array of autoloader instances.
*
* @return array
*/
public static function getRegisteredAutoloaders()
{
return static::$loaders;
}
/**
* Retrieves an autoloader by class name
*
* @param string $class
* @return SplAutoloader
* @throws Exception\InvalidArgumentException For non-registered class.
*/
public static function getRegisteredAutoloader($class)
{
if (! isset(static::$loaders[$class])) {
require_once 'Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(sprintf('Autoloader class "%s" not loaded', $class));
}
return static::$loaders[$class];
}
/**
* Unregisters all autoloaders that have been registered via the factory.
* This will NOT unregister autoloaders registered outside of the fctory.
*
* @return void
*/
public static function unregisterAutoloaders()
{
foreach (static::getRegisteredAutoloaders() as $class => $autoloader) {
spl_autoload_unregister([$autoloader, 'autoload']);
unset(static::$loaders[$class]);
}
}
/**
* Unregister a single autoloader by class name
*
* @param string $autoloaderClass
* @return bool
*/
public static function unregisterAutoloader($autoloaderClass)
{
if (! isset(static::$loaders[$autoloaderClass])) {
return false;
}
$autoloader = static::$loaders[$autoloaderClass];
spl_autoload_unregister([$autoloader, 'autoload']);
unset(static::$loaders[$autoloaderClass]);
return true;
}
/**
* Get an instance of the standard autoloader
*
* Used to attempt to resolve autoloader classes, using the
* StandardAutoloader. The instance is marked as a fallback autoloader, to
* allow resolving autoloaders not under the "Laminas" namespace.
*
* @return SplAutoloader
*/
protected static function getStandardAutoloader()
{
if (null !== static::$standardAutoloader) {
return static::$standardAutoloader;
}
if (! class_exists(static::STANDARD_AUTOLOADER)) {
// Extract the filename from the classname
$stdAutoloader = substr(strrchr(static::STANDARD_AUTOLOADER, '\\'), 1);
require_once __DIR__ . "/$stdAutoloader.php";
}
$loader = new StandardAutoloader();
static::$standardAutoloader = $loader;
return static::$standardAutoloader;
}
/**
* Checks if the object has this class as one of its parents
*
* @deprecated since laminas 2.3 requires PHP >= 5.3.23
*
* @see https://bugs.php.net/bug.php?id=53727
* @see https://github.com/zendframework/zf2/pull/1807
*
* @param string $className
* @param string $type
* @return bool
*/
protected static function isSubclassOf($className, $type)
{
return is_subclass_of($className, $type);
}
}
laminas-loader/src/PluginClassLoader.php 0000644 00000013014 15240152642 0014307 0 ustar 00 <?php // phpcs:disable SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse
namespace Laminas\Loader;
use ArrayIterator;
use IteratorAggregate;
use ReturnTypeWillChange;
use Traversable;
use function array_key_exists;
use function class_exists;
use function is_array;
use function is_int;
use function is_numeric;
use function is_object;
use function is_string;
use function strtolower;
/**
* Plugin class locator interface
*/
class PluginClassLoader implements PluginClassLocator
{
/**
* List of plugin name => class name pairs
*
* @var array
*/
protected $plugins = [];
/**
* Static map allow global seeding of plugin loader
*
* @var array
*/
protected static $staticMap = [];
/**
* Constructor
*
* @param null|array|Traversable $map If provided, seeds the loader with a map
*/
public function __construct($map = null)
{
// Merge in static overrides
if (! empty(static::$staticMap)) {
$this->registerPlugins(static::$staticMap);
}
// Merge in constructor arguments
if ($map !== null) {
$this->registerPlugins($map);
}
}
/**
* Add a static map of plugins
*
* A null value will clear the static map.
*
* @param null|array|Traversable $map
* @throws Exception\InvalidArgumentException
* @return void
*/
public static function addStaticMap($map)
{
if (null === $map) {
static::$staticMap = [];
return;
}
if (! is_array($map) && ! $map instanceof Traversable) {
throw new Exception\InvalidArgumentException('Expects an array or Traversable object');
}
foreach ($map as $key => $value) {
static::$staticMap[$key] = $value;
}
}
/**
* Register a class to a given short name
*
* @param string $shortName
* @param string $className
* @return PluginClassLoader
*/
public function registerPlugin($shortName, $className)
{
$this->plugins[strtolower($shortName)] = $className;
return $this;
}
/**
* Register many plugins at once
*
* If $map is a string, assumes that the map is the class name of a
* Traversable object (likely a ShortNameLocator); it will then instantiate
* this class and use it to register plugins.
*
* If $map is an array or Traversable object, it will iterate it to
* register plugin names/classes.
*
* For all other arguments, or if the string $map is not a class or not a
* Traversable class, an exception will be raised.
*
* @param string|array|Traversable $map
* @return PluginClassLoader
* @throws Exception\InvalidArgumentException
*/
public function registerPlugins($map)
{
if (is_string($map)) {
if (! class_exists($map)) {
throw new Exception\InvalidArgumentException('Map class provided is invalid');
}
$map = new $map();
}
if (is_array($map)) {
$map = new ArrayIterator($map);
}
if (! $map instanceof Traversable) {
throw new Exception\InvalidArgumentException('Map provided is invalid; must be traversable');
}
// iterator_apply doesn't work as expected with IteratorAggregate
if ($map instanceof IteratorAggregate) {
$map = $map->getIterator();
}
foreach ($map as $name => $class) {
if (is_int($name) || is_numeric($name)) {
if (! is_object($class) && class_exists($class)) {
$class = new $class();
}
if ($class instanceof Traversable) {
$this->registerPlugins($class);
continue;
}
}
$this->registerPlugin($name, $class);
}
return $this;
}
/**
* Unregister a short name lookup
*
* @param mixed $shortName
* @return PluginClassLoader
*/
public function unregisterPlugin($shortName)
{
$lookup = strtolower($shortName);
if (array_key_exists($lookup, $this->plugins)) {
unset($this->plugins[$lookup]);
}
return $this;
}
/**
* Get a list of all registered plugins
*
* @return array|Traversable
*/
public function getRegisteredPlugins()
{
return $this->plugins;
}
/**
* Whether or not a plugin by a specific name has been registered
*
* @param string $name
* @return bool
*/
public function isLoaded($name)
{
$lookup = strtolower($name);
return isset($this->plugins[$lookup]);
}
/**
* Return full class name for a named helper
*
* @param string $name
* @return string|false
*/
public function getClassName($name)
{
return $this->load($name);
}
/**
* Load a helper via the name provided
*
* @param string $name
* @return string|false
*/
public function load($name)
{
if (! $this->isLoaded($name)) {
return false;
}
return $this->plugins[strtolower($name)];
}
/**
* Defined by IteratorAggregate
*
* Returns an instance of ArrayIterator, containing a map of
* all plugins
*
* @return ArrayIterator
*/
#[ReturnTypeWillChange]
public function getIterator()
{
return new ArrayIterator($this->plugins);
}
}
laminas-loader/README.md 0000644 00000007420 15240152642 0010717 0 ustar 00 # laminas-loader
> ## 🇷🇺 Русским гражданам
>
> Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм.
>
> У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую.
>
> Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!"
>
> ## 🇺🇸 To Citizens of Russia
>
> We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism.
>
> One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences.
>
> You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!"
> This package is considered feature-complete, and is now in **security-only** maintenance mode, following a [decision by the Technical Steering Committee](https://github.com/laminas/technical-steering-committee/blob/2b55453e172a1b8c9c4c212be7cf7e7a58b9352c/meetings/minutes/2020-08-03-TSC-Minutes.md#vote-on-components-to-mark-as-security-only).
> If you have a security issue, please [follow our security reporting guidelines](https://getlaminas.org/security/).
> If you wish to take on the role of maintainer, please [nominate yourself](https://github.com/laminas/technical-steering-committee/issues/new?assignees=&labels=Nomination&template=Maintainer_Nomination.md&title=%5BNOMINATION%5D%5BMAINTAINER%5D%3A+%7Bname+of+person+being+nominated%7D)
[](https://github.com/laminas/laminas-loader/actions?query=workflow%3A"Continuous+Integration")
laminas-loader provides different strategies for autoloading PHP classes.
- File issues at https://github.com/laminas/laminas-loader/issues
- Documentation is at https://docs.laminas.dev/laminas-loader/
laminas-loader/composer.json 0000644 00000002742 15240152642 0012164 0 ustar 00 {
"name": "laminas/laminas-loader",
"description": "Autoloading and plugin loading strategies",
"license": "BSD-3-Clause",
"keywords": [
"laminas",
"loader"
],
"homepage": "https://laminas.dev",
"support": {
"docs": "https://docs.laminas.dev/laminas-loader/",
"issues": "https://github.com/laminas/laminas-loader/issues",
"source": "https://github.com/laminas/laminas-loader",
"rss": "https://github.com/laminas/laminas-loader/releases.atom",
"chat": "https://laminas.dev/chat",
"forum": "https://discourse.laminas.dev"
},
"config": {
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"phpunit/phpunit": "~9.5.25"
},
"autoload": {
"psr-4": {
"Laminas\\Loader\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"LaminasTest\\Loader\\": "test/"
}
},
"scripts": {
"check": [
"@cs-check",
"@test"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
},
"conflict": {
"zendframework/zend-loader": "*"
}
}
laminas-loader/COPYRIGHT.md 0000644 00000000133 15240152642 0011324 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/)
laminas-loader/composer.lock 0000644 00000225404 15240152642 0012145 0 ustar 00 {
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "66f555baf92bb6bda8b28730fcceb30e",
"packages": [],
"packages-dev": [
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
"version": "v0.7.2",
"source": {
"type": "git",
"url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
"phpcompatibility/php-compatibility": "^9.0"
},
"type": "composer-plugin",
"extra": {
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
"Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Franck Nijhof",
"email": "franck.nijhof@dealerdirect.com",
"homepage": "http://www.frenck.nl",
"role": "Developer / IT Manager"
},
{
"name": "Contributors",
"homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
"homepage": "http://www.dealerdirect.com",
"keywords": [
"PHPCodeSniffer",
"PHP_CodeSniffer",
"code quality",
"codesniffer",
"composer",
"installer",
"phpcbf",
"phpcs",
"plugin",
"qa",
"quality",
"standard",
"standards",
"style guide",
"stylecheck",
"tests"
],
"support": {
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
"time": "2022-02-04T12:51:07+00:00"
},
{
"name": "doctrine/instantiator",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9",
"ext-pdo": "*",
"ext-phar": "*",
"phpbench/phpbench": "^0.16 || ^1",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-phpunit": "^1",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"vimeo/psalm": "^4.22"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "https://ocramius.github.io/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://www.doctrine-project.org/projects/instantiator.html",
"keywords": [
"constructor",
"instantiate"
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/1.4.1"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
"type": "tidelift"
}
],
"time": "2022-03-03T08:28:38+00:00"
},
{
"name": "laminas/laminas-coding-standard",
"version": "2.4.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-coding-standard.git",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7",
"php": "^7.4 || ^8.0",
"slevomat/coding-standard": "^7.0",
"squizlabs/php_codesniffer": "^3.6",
"webimpress/coding-standard": "^1.2"
},
"conflict": {
"phpstan/phpdoc-parser": ">=1.6.0"
},
"type": "phpcodesniffer-standard",
"autoload": {
"psr-4": {
"LaminasCodingStandard\\": "src/LaminasCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Laminas Coding Standard",
"homepage": "https://laminas.dev",
"keywords": [
"Coding Standard",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-coding-standard/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-coding-standard/issues",
"rss": "https://github.com/laminas/laminas-coding-standard/releases.atom",
"source": "https://github.com/laminas/laminas-coding-standard"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-08-24T17:45:47+00:00"
},
{
"name": "myclabs/deep-copy",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"conflict": {
"doctrine/collections": "<1.6.8",
"doctrine/common": "<2.13.3 || >=3,<3.2.2"
},
"require-dev": {
"doctrine/collections": "^1.6.8",
"doctrine/common": "^2.13.3 || ^3.2.2",
"phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
},
"type": "library",
"autoload": {
"files": [
"src/DeepCopy/deep_copy.php"
],
"psr-4": {
"DeepCopy\\": "src/DeepCopy/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Create deep copies (clones) of your objects",
"keywords": [
"clone",
"copy",
"duplicate",
"object",
"object graph"
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
},
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
"type": "tidelift"
}
],
"time": "2022-03-03T13:19:32+00:00"
},
{
"name": "nikic/php-parser",
"version": "v4.15.1",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=7.0"
},
"require-dev": {
"ircmaxell/php-yacc": "^0.0.7",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
},
"bin": [
"bin/php-parse"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.9-dev"
}
},
"autoload": {
"psr-4": {
"PhpParser\\": "lib/PhpParser"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov"
}
],
"description": "A PHP parser written in PHP",
"keywords": [
"parser",
"php"
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1"
},
"time": "2022-09-04T07:30:47+00:00"
},
{
"name": "phar-io/manifest",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-phar": "*",
"ext-xmlwriter": "*",
"phar-io/version": "^3.0.1",
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
"support": {
"issues": "https://github.com/phar-io/manifest/issues",
"source": "https://github.com/phar-io/manifest/tree/2.0.3"
},
"time": "2021-07-20T11:28:43+00:00"
},
{
"name": "phar-io/version",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/phar-io/version.git",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Library for handling version information and constraints",
"support": {
"issues": "https://github.com/phar-io/version/issues",
"source": "https://github.com/phar-io/version/tree/3.2.1"
},
"time": "2022-02-21T01:04:05+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "981cc368a216c988e862a75e526b6076987d1b50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/981cc368a216c988e862a75e526b6076987d1b50",
"reference": "981cc368a216c988e862a75e526b6076987d1b50",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.5.1"
},
"time": "2022-05-05T11:32:40+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.17",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
"nikic/php-parser": "^4.14",
"php": ">=7.3",
"phpunit/php-file-iterator": "^3.0.3",
"phpunit/php-text-template": "^2.0.2",
"sebastian/code-unit-reverse-lookup": "^2.0.2",
"sebastian/complexity": "^2.0",
"sebastian/environment": "^5.1.2",
"sebastian/lines-of-code": "^1.0.3",
"sebastian/version": "^3.0.1",
"theseer/tokenizer": "^1.2.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcov": "*",
"ext-xdebug": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-08-30T12:24:04+00:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "3.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2021-12-02T12:48:52+00:00"
},
{
"name": "phpunit/php-invoker",
"version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-invoker.git",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"ext-pcntl": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcntl": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Invoke callables with a timeout",
"homepage": "https://github.com/sebastianbergmann/php-invoker/",
"keywords": [
"process"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-invoker/issues",
"source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:58:55+00:00"
},
{
"name": "phpunit/php-text-template",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
"source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T05:33:50+00:00"
},
{
"name": "phpunit/php-timer",
"version": "5.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-timer/issues",
"source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:16:10+00:00"
},
{
"name": "phpunit/phpunit",
"version": "9.5.25",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
"reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.3.1",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
"myclabs/deep-copy": "^1.10.1",
"phar-io/manifest": "^2.0.3",
"phar-io/version": "^3.0.2",
"php": ">=7.3",
"phpunit/php-code-coverage": "^9.2.13",
"phpunit/php-file-iterator": "^3.0.5",
"phpunit/php-invoker": "^3.1.1",
"phpunit/php-text-template": "^2.0.3",
"phpunit/php-timer": "^5.0.2",
"sebastian/cli-parser": "^1.0.1",
"sebastian/code-unit": "^1.0.6",
"sebastian/comparator": "^4.0.8",
"sebastian/diff": "^4.0.3",
"sebastian/environment": "^5.1.3",
"sebastian/exporter": "^4.0.5",
"sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3",
"sebastian/type": "^3.2",
"sebastian/version": "^3.0.2"
},
"suggest": {
"ext-soap": "*",
"ext-xdebug": "*"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.5-dev"
}
},
"autoload": {
"files": [
"src/Framework/Assert/Functions.php"
],
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.25"
},
"funding": [
{
"url": "https://phpunit.de/sponsors.html",
"type": "custom"
},
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
"type": "tidelift"
}
],
"time": "2022-09-25T03:44:45+00:00"
},
{
"name": "sebastian/cli-parser",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for parsing CLI options",
"homepage": "https://github.com/sebastianbergmann/cli-parser",
"support": {
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
"source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:08:49+00:00"
},
{
"name": "sebastian/code-unit",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit.git",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the PHP code units",
"homepage": "https://github.com/sebastianbergmann/code-unit",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit/issues",
"source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:08:54+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
"source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:30:19+00:00"
},
{
"name": "sebastian/comparator",
"version": "4.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/diff": "^4.0",
"sebastian/exporter": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "https://github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
"source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T12:41:17+00:00"
},
{
"name": "sebastian/complexity",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.7",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for calculating the complexity of PHP code units",
"homepage": "https://github.com/sebastianbergmann/complexity",
"support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues",
"source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T15:52:27+00:00"
},
{
"name": "sebastian/diff",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3",
"symfony/process": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
}
],
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
"diff",
"udiff",
"unidiff",
"unified diff"
],
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:10:38+00:00"
},
{
"name": "sebastian/environment",
"version": "5.1.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-posix": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"support": {
"issues": "https://github.com/sebastianbergmann/environment/issues",
"source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-04-03T09:37:03+00:00"
},
{
"name": "sebastian/exporter",
"version": "4.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-mbstring": "*",
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "https://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T06:03:37+00:00"
},
{
"name": "sebastian/global-state",
"version": "5.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-dom": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-uopz": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-02-14T08:28:10+00:00"
},
{
"name": "sebastian/lines-of-code",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.6",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for counting the lines of code in PHP source code",
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
"support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-11-28T06:42:11+00:00"
},
{
"name": "sebastian/object-enumerator",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
"source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:12:34+00:00"
},
{
"name": "sebastian/object-reflector",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Allows reflection of object attributes, including inherited and non-public ones",
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-reflector/issues",
"source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:14:26+00:00"
},
{
"name": "sebastian/recursion-context",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
"source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:17:30+00:00"
},
{
"name": "sebastian/resource-operations",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"support": {
"issues": "https://github.com/sebastianbergmann/resource-operations/issues",
"source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:45:17+00:00"
},
{
"name": "sebastian/type",
"version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the types of the PHP type system",
"homepage": "https://github.com/sebastianbergmann/type",
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
"source": "https://github.com/sebastianbergmann/type/tree/3.2.0"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-12T14:47:03+00:00"
},
{
"name": "sebastian/version",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "c6c1022351a901512170118436c764e473f6de8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
"reference": "c6c1022351a901512170118436c764e473f6de8c",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"support": {
"issues": "https://github.com/sebastianbergmann/version/issues",
"source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:39:44+00:00"
},
{
"name": "slevomat/coding-standard",
"version": "7.2.1",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
"php": "^7.2 || ^8.0",
"phpstan/phpdoc-parser": "^1.5.1",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phing/phing": "2.17.3",
"php-parallel-lint/php-parallel-lint": "1.3.2",
"phpstan/phpstan": "1.4.10|1.7.1",
"phpstan/phpstan-deprecation-rules": "1.0.0",
"phpstan/phpstan-phpunit": "1.0.0|1.1.1",
"phpstan/phpstan-strict-rules": "1.2.3",
"phpunit/phpunit": "7.5.20|8.5.21|9.5.20"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "7.x-dev"
}
},
"autoload": {
"psr-4": {
"SlevomatCodingStandard\\": "SlevomatCodingStandard"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
"source": "https://github.com/slevomat/coding-standard/tree/7.2.1"
},
"funding": [
{
"url": "https://github.com/kukulich",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
"type": "tidelift"
}
],
"time": "2022-05-25T10:58:12+00:00"
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.7.1",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"bin/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2022-06-18T07:21:10+00:00"
},
{
"name": "theseer/tokenizer",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
}
],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/1.2.1"
},
"funding": [
{
"url": "https://github.com/theseer",
"type": "github"
}
],
"time": "2021-07-28T10:34:58+00:00"
},
{
"name": "webimpress/coding-standard",
"version": "1.2.4",
"source": {
"type": "git",
"url": "https://github.com/webimpress/coding-standard.git",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webimpress/coding-standard/zipball/cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"shasum": ""
},
"require": {
"php": "^7.3 || ^8.0",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phpunit/phpunit": "^9.5.13"
},
"type": "phpcodesniffer-standard",
"extra": {
"dev-master": "1.2.x-dev",
"dev-develop": "1.3.x-dev"
},
"autoload": {
"psr-4": {
"WebimpressCodingStandard\\": "src/WebimpressCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-2-Clause"
],
"description": "Webimpress Coding Standard",
"keywords": [
"Coding Standard",
"PSR-2",
"phpcs",
"psr-12",
"webimpress"
],
"support": {
"issues": "https://github.com/webimpress/coding-standard/issues",
"source": "https://github.com/webimpress/coding-standard/tree/1.2.4"
},
"funding": [
{
"url": "https://github.com/michalbundyra",
"type": "github"
}
],
"time": "2022-02-15T19:52:12+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"platform-dev": [],
"plugin-api-version": "2.2.0"
}
laminas-loader/LICENSE.md 0000644 00000002732 15240152642 0011045 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of Laminas Foundation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
laminas-stdlib/src/ParameterObjectInterface.php 0000644 00000000765 15240152642 0015650 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
interface ParameterObjectInterface
{
/**
* @param string $key
* @return void
*/
public function __set($key, mixed $value);
/**
* @param string $key
* @return mixed
*/
public function __get($key);
/**
* @param string $key
* @return bool
*/
public function __isset($key);
/**
* @param string $key
* @return void
*/
public function __unset($key);
}
laminas-stdlib/src/SplStack.php 0000644 00000003471 15240152642 0012501 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
use ReturnTypeWillChange;
use Serializable;
use UnexpectedValueException;
use function is_array;
use function serialize;
use function sprintf;
use function unserialize;
/**
* Serializable version of SplStack
*
* @template TValue
* @extends \SplStack<TValue>
*/
class SplStack extends \SplStack implements Serializable
{
/**
* Serialize to an array representing the stack
*
* @return list<TValue>
*/
public function toArray()
{
$array = [];
foreach ($this as $item) {
$array[] = $item;
}
return $array;
}
/**
* Serialize
*
* @return string
*/
#[ReturnTypeWillChange]
public function serialize()
{
return serialize($this->__serialize());
}
/**
* Magic method used for serializing of an instance.
*
* @return list<TValue>
*/
#[ReturnTypeWillChange]
public function __serialize()
{
return $this->toArray();
}
/**
* Unserialize
*
* @param string $data
* @return void
*/
#[ReturnTypeWillChange]
public function unserialize($data)
{
$toUnserialize = unserialize($data);
if (! is_array($toUnserialize)) {
throw new UnexpectedValueException(sprintf(
'Cannot deserialize %s instance; corrupt serialization data',
self::class
));
}
$this->__unserialize($toUnserialize);
}
/**
* Magic method used to rebuild an instance.
*
* @param array<array-key, TValue> $data Data array.
* @return void
*/
#[ReturnTypeWillChange]
public function __unserialize($data)
{
foreach ($data as $item) {
$this->unshift($item);
}
}
}
laminas-stdlib/src/ErrorHandler.php 0000644 00000004753 15240152642 0013350 0 ustar 00 <?php // phpcs:disable WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix
declare(strict_types=1);
namespace Laminas\Stdlib;
use ErrorException;
use function array_pop;
use function count;
use function restore_error_handler;
use function set_error_handler;
use const E_WARNING;
/**
* ErrorHandler that can be used to catch internal PHP errors
* and convert to an ErrorException instance.
*/
abstract class ErrorHandler
{
/**
* Active stack
*
* @var array
*/
protected static $stack = [];
/**
* Check if this error handler is active
*
* @return bool
*/
public static function started()
{
return (bool) static::getNestedLevel();
}
/**
* Get the current nested level
*
* @return int
*/
public static function getNestedLevel()
{
return count(static::$stack);
}
/**
* Starting the error handler
*
* @param int $errorLevel
* @return void
*/
public static function start($errorLevel = E_WARNING)
{
if (! static::$stack) {
set_error_handler([static::class, 'addError'], $errorLevel);
}
static::$stack[] = null;
}
/**
* Stopping the error handler
*
* @param bool $throw Throw the ErrorException if any
* @return null|ErrorException
* @throws ErrorException If an error has been caught and $throw is true.
*/
public static function stop($throw = false)
{
$errorException = null;
if (static::$stack) {
$errorException = array_pop(static::$stack);
if (! static::$stack) {
restore_error_handler();
}
if ($errorException && $throw) {
throw $errorException;
}
}
return $errorException;
}
/**
* Stop all active handler
*
* @return void
*/
public static function clean()
{
if (static::$stack) {
restore_error_handler();
}
static::$stack = [];
}
/**
* Add an error to the stack
*
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
* @return void
*/
public static function addError($errno, $errstr = '', $errfile = '', $errline = 0)
{
$stack = &static::$stack[count(static::$stack) - 1];
$stack = new ErrorException($errstr, 0, $errno, $errfile, $errline, $stack);
}
}
laminas-stdlib/src/Message.php 0000644 00000005226 15240152642 0012341 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
use Traversable;
use function array_key_exists;
use function get_debug_type;
use function is_array;
use function is_scalar;
use function sprintf;
class Message implements MessageInterface
{
/** @var array */
protected $metadata = [];
/** @var mixed */
protected $content = '';
/**
* Set message metadata
*
* Non-destructive setting of message metadata; always adds to the metadata, never overwrites
* the entire metadata container.
*
* @param string|int|array|Traversable $spec
* @param mixed $value
* @throws Exception\InvalidArgumentException
* @return Message
*/
public function setMetadata($spec, $value = null)
{
if (is_scalar($spec)) {
$this->metadata[$spec] = $value;
return $this;
}
if (! is_array($spec) && ! $spec instanceof Traversable) {
throw new Exception\InvalidArgumentException(sprintf(
'Expected a string, array, or Traversable argument in first position; received "%s"',
get_debug_type($spec)
));
}
foreach ($spec as $key => $value) {
$this->metadata[$key] = $value;
}
return $this;
}
/**
* Retrieve all metadata or a single metadatum as specified by key
*
* @param null|string|int $key
* @param null|mixed $default
* @throws Exception\InvalidArgumentException
* @return mixed
*/
public function getMetadata($key = null, $default = null)
{
if (null === $key) {
return $this->metadata;
}
if (! is_scalar($key)) {
throw new Exception\InvalidArgumentException('Non-scalar argument provided for key');
}
if (array_key_exists($key, $this->metadata)) {
return $this->metadata[$key];
}
return $default;
}
/**
* Set message content
*
* @param mixed $value
* @return Message
*/
public function setContent($value)
{
$this->content = $value;
return $this;
}
/**
* Get message content
*
* @return mixed
*/
public function getContent()
{
return $this->content;
}
/**
* @return string
*/
public function toString()
{
$request = '';
foreach ($this->getMetadata() as $key => $value) {
$request .= sprintf(
"%s: %s\r\n",
(string) $key,
(string) $value
);
}
$request .= "\r\n" . $this->getContent();
return $request;
}
}
laminas-stdlib/src/Response.php 0000644 00000000243 15240152642 0012545 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
class Response extends Message implements ResponseInterface
{
// generic response implementation
}
laminas-stdlib/src/DispatchableInterface.php 0000644 00000000415 15240152643 0015155 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
interface DispatchableInterface
{
/**
* Dispatch a request
*
* @return Response|mixed
*/
public function dispatch(RequestInterface $request, ?ResponseInterface $response = null);
}
laminas-stdlib/src/InitializableInterface.php 0000644 00000000401 15240152643 0015345 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
/**
* Interface to allow objects to have initialization logic
*/
interface InitializableInterface
{
/**
* Init an object
*
* @return void
*/
public function init();
}
laminas-stdlib/src/Exception/InvalidArgumentException.php 0000644 00000000317 15240152643 0017660 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\Exception;
/**
* Invalid Argument Exception
*/
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
laminas-stdlib/src/Exception/ExceptionInterface.php 0000644 00000000215 15240152643 0016464 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\Exception;
/**
* Exception marker interface
*/
interface ExceptionInterface
{
}
laminas-stdlib/src/Exception/LogicException.php 0000644 00000000260 15240152643 0015621 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\Exception;
/**
* Logic exception
*/
class LogicException extends \LogicException implements ExceptionInterface
{
}
laminas-stdlib/src/Exception/DomainException.php 0000644 00000000263 15240152643 0015776 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\Exception;
/**
* Domain exception
*/
class DomainException extends \DomainException implements ExceptionInterface
{
}
laminas-stdlib/src/Exception/BadMethodCallException.php 0000644 00000000312 15240152643 0017205 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\Exception;
/**
* Bad method call exception
*/
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
}
laminas-stdlib/src/Exception/ExtensionNotLoadedException.php 0000644 00000000257 15240152643 0020340 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\Exception;
/**
* Extension not loaded exception
*/
class ExtensionNotLoadedException extends RuntimeException
{
}
laminas-stdlib/src/Exception/RuntimeException.php 0000644 00000000266 15240152643 0016215 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\Exception;
/**
* Runtime exception
*/
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
laminas-stdlib/src/Guard/AllGuardsTrait.php 0000644 00000000337 15240152643 0014700 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\Guard;
/**
* An aggregate for all guard traits
*/
trait AllGuardsTrait
{
use ArrayOrTraversableGuardTrait;
use EmptyGuardTrait;
use NullGuardTrait;
}
laminas-stdlib/src/Guard/NullGuardTrait.php 0000644 00000001477 15240152643 0014725 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\Guard;
use Exception;
use Laminas\Stdlib\Exception\InvalidArgumentException;
use function sprintf;
/**
* Provide a guard method against null data
*/
trait NullGuardTrait
{
/**
* Verify that the data is not null
*
* @param mixed $data the data to verify
* @param string $dataName the data name
* @param string $exceptionClass FQCN for the exception
* @return void
* @throws Exception
*/
protected function guardAgainstNull(
mixed $data,
$dataName = 'Argument',
$exceptionClass = InvalidArgumentException::class
) {
if (null === $data) {
$message = sprintf('%s cannot be null', $dataName);
throw new $exceptionClass($message);
}
}
}
laminas-stdlib/src/Guard/EmptyGuardTrait.php 0000644 00000001502 15240152644 0015077 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\Guard;
use Exception;
use Laminas\Stdlib\Exception\InvalidArgumentException;
use function sprintf;
/**
* Provide a guard method against empty data
*/
trait EmptyGuardTrait
{
/**
* Verify that the data is not empty
*
* @param mixed $data the data to verify
* @param string $dataName the data name
* @param string $exceptionClass FQCN for the exception
* @return void
* @throws Exception
*/
protected function guardAgainstEmpty(
mixed $data,
$dataName = 'Argument',
$exceptionClass = InvalidArgumentException::class
) {
if (empty($data)) {
$message = sprintf('%s cannot be empty', $dataName);
throw new $exceptionClass($message);
}
}
}
laminas-stdlib/src/Guard/ArrayOrTraversableGuardTrait.php 0000644 00000002120 15240152644 0017550 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\Guard;
use Exception;
use Laminas\Stdlib\Exception\InvalidArgumentException;
use Traversable;
use function get_debug_type;
use function is_array;
use function sprintf;
/**
* Provide a guard method for array or Traversable data
*/
trait ArrayOrTraversableGuardTrait
{
/**
* Verifies that the data is an array or Traversable
*
* @param mixed $data the data to verify
* @param string $dataName the data name
* @param string $exceptionClass FQCN for the exception
* @return void
* @throws Exception
*/
protected function guardForArrayOrTraversable(
mixed $data,
$dataName = 'Argument',
$exceptionClass = InvalidArgumentException::class
) {
if (! is_array($data) && ! $data instanceof Traversable) {
$message = sprintf(
"%s must be an array or Traversable, [%s] given",
$dataName,
get_debug_type($data)
);
throw new $exceptionClass($message);
}
}
}
laminas-stdlib/src/ArrayObject.php 0000644 00000026333 15240152644 0013166 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
use AllowDynamicProperties;
use ArrayAccess;
use Countable;
use Iterator;
use IteratorAggregate;
use ReturnTypeWillChange;
use Serializable;
use UnexpectedValueException;
use function array_key_exists;
use function array_keys;
use function asort;
use function class_exists;
use function count;
use function get_debug_type;
use function get_object_vars;
use function gettype;
use function in_array;
use function is_array;
use function is_callable;
use function is_object;
use function is_string;
use function ksort;
use function natcasesort;
use function natsort;
use function serialize;
use function sprintf;
use function str_starts_with;
use function uasort;
use function uksort;
use function unserialize;
/**
* Custom framework ArrayObject implementation
*
* Extends version-specific "abstract" implementation.
*/
#[AllowDynamicProperties]
class ArrayObject implements IteratorAggregate, ArrayAccess, Serializable, Countable
{
/**
* Properties of the object have their normal functionality
* when accessed as list (var_dump, foreach, etc.).
*/
public const STD_PROP_LIST = 1;
/**
* Entries can be accessed as properties (read and write).
*/
public const ARRAY_AS_PROPS = 2;
/** @var array */
protected $storage;
/** @var int */
protected $flag;
/** @var string */
protected $iteratorClass;
/** @var array */
protected $protectedProperties;
/**
* Constructor
*
* @param array|object $input Object values must act like ArrayAccess
* @param int $flags
* @param string $iteratorClass
*/
public function __construct($input = [], $flags = self::STD_PROP_LIST, $iteratorClass = 'ArrayIterator')
{
$this->setFlags($flags);
$this->storage = $input;
$this->setIteratorClass($iteratorClass);
$this->protectedProperties = array_keys(get_object_vars($this));
}
/**
* Returns whether the requested key exists
*
* @return bool
*/
public function __isset(mixed $key)
{
if ($this->flag === self::ARRAY_AS_PROPS) {
return $this->offsetExists($key);
}
if (in_array($key, $this->protectedProperties)) {
throw new Exception\InvalidArgumentException("$key is a protected property, use a different key");
}
return isset($this->$key);
}
/**
* Sets the value at the specified key to value
*
* @return void
*/
public function __set(mixed $key, mixed $value)
{
if ($this->flag === self::ARRAY_AS_PROPS) {
$this->offsetSet($key, $value);
return;
}
if (in_array($key, $this->protectedProperties)) {
throw new Exception\InvalidArgumentException("$key is a protected property, use a different key");
}
$this->$key = $value;
}
/**
* Unsets the value at the specified key
*
* @return void
*/
public function __unset(mixed $key)
{
if ($this->flag === self::ARRAY_AS_PROPS) {
$this->offsetUnset($key);
return;
}
if (in_array($key, $this->protectedProperties)) {
throw new Exception\InvalidArgumentException("$key is a protected property, use a different key");
}
unset($this->$key);
}
/**
* Returns the value at the specified key by reference
*
* @return mixed
*/
public function &__get(mixed $key)
{
if ($this->flag === self::ARRAY_AS_PROPS) {
$ret = &$this->offsetGet($key);
return $ret;
}
if (in_array($key, $this->protectedProperties, true)) {
throw new Exception\InvalidArgumentException("$key is a protected property, use a different key");
}
return $this->$key;
}
/**
* Appends the value
*
* @return void
*/
public function append(mixed $value)
{
$this->storage[] = $value;
}
/**
* Sort the entries by value
*
* @return void
*/
public function asort()
{
asort($this->storage);
}
/**
* Get the number of public properties in the ArrayObject
*
* @return int
*/
#[ReturnTypeWillChange]
public function count()
{
return count($this->storage);
}
/**
* Exchange the array for another one.
*
* @param array|ArrayObject|ArrayIterator|object $data
* @return array
*/
public function exchangeArray($data)
{
if (! is_array($data) && ! is_object($data)) {
throw new Exception\InvalidArgumentException(
'Passed variable is not an array or object, using empty array instead'
);
}
if (is_object($data) && ($data instanceof self || $data instanceof \ArrayObject)) {
$data = $data->getArrayCopy();
}
if (! is_array($data)) {
$data = (array) $data;
}
$storage = $this->storage;
$this->storage = $data;
return $storage;
}
/**
* Creates a copy of the ArrayObject.
*
* @return array
*/
public function getArrayCopy()
{
return $this->storage;
}
/**
* Gets the behavior flags.
*
* @return int
*/
public function getFlags()
{
return $this->flag;
}
/**
* Create a new iterator from an ArrayObject instance
*
* @return Iterator
*/
#[ReturnTypeWillChange]
public function getIterator()
{
$class = $this->iteratorClass;
return new $class($this->storage);
}
/**
* Gets the iterator classname for the ArrayObject.
*
* @return string
*/
public function getIteratorClass()
{
return $this->iteratorClass;
}
/**
* Sort the entries by key
*
* @return void
*/
public function ksort()
{
ksort($this->storage);
}
/**
* Sort an array using a case insensitive "natural order" algorithm
*
* @return void
*/
public function natcasesort()
{
natcasesort($this->storage);
}
/**
* Sort entries using a "natural order" algorithm
*
* @return void
*/
public function natsort()
{
natsort($this->storage);
}
/**
* Returns whether the requested key exists
*
* @return bool
*/
#[ReturnTypeWillChange]
public function offsetExists(mixed $key)
{
return isset($this->storage[$key]);
}
/**
* Returns the value at the specified key
*
* @return mixed
*/
#[ReturnTypeWillChange]
public function &offsetGet(mixed $key)
{
$ret = null;
if (! $this->offsetExists($key)) {
return $ret;
}
$ret = &$this->storage[$key];
return $ret;
}
/**
* Sets the value at the specified key to value
*
* @return void
*/
#[ReturnTypeWillChange]
public function offsetSet(mixed $key, mixed $value)
{
$this->storage[$key] = $value;
}
/**
* Unsets the value at the specified key
*
* @return void
*/
#[ReturnTypeWillChange]
public function offsetUnset(mixed $key)
{
if ($this->offsetExists($key)) {
unset($this->storage[$key]);
}
}
/**
* Serialize an ArrayObject
*
* @return string
*/
public function serialize()
{
return serialize($this->__serialize());
}
/**
* Magic method used for serializing of an instance.
*
* @return array
*/
public function __serialize()
{
return get_object_vars($this);
}
/**
* Sets the behavior flags
*
* @param int $flags
* @return void
*/
public function setFlags($flags)
{
$this->flag = $flags;
}
/**
* Sets the iterator classname for the ArrayObject
*
* @param string $class
* @return void
*/
public function setIteratorClass($class)
{
if (class_exists($class)) {
$this->iteratorClass = $class;
return;
}
if (str_starts_with($class, '\\')) {
$class = '\\' . $class;
if (class_exists($class)) {
$this->iteratorClass = $class;
return;
}
}
throw new Exception\InvalidArgumentException('The iterator class does not exist');
}
/**
* Sort the entries with a user-defined comparison function and maintain key association
*
* @param callable $function
* @return void
*/
public function uasort($function)
{
if (is_callable($function)) {
uasort($this->storage, $function);
}
}
/**
* Sort the entries by keys using a user-defined comparison function
*
* @param callable $function
* @return void
*/
public function uksort($function)
{
if (is_callable($function)) {
uksort($this->storage, $function);
}
}
/**
* Unserialize an ArrayObject
*
* @param string $data
* @return void
*/
public function unserialize($data)
{
$toUnserialize = unserialize($data);
if (! is_array($toUnserialize)) {
throw new UnexpectedValueException(sprintf(
'Cannot deserialize %s instance; corrupt serialization data',
self::class
));
}
$this->__unserialize($toUnserialize);
}
/**
* Magic method used to rebuild an instance.
*
* @param array $data Data array.
* @return void
*/
public function __unserialize($data)
{
$this->protectedProperties = array_keys(get_object_vars($this));
// Unserialize protected internal properties first
if (array_key_exists('flag', $data)) {
$this->setFlags((int) $data['flag']);
unset($data['flag']);
}
if (array_key_exists('storage', $data)) {
if (! is_array($data['storage']) && ! is_object($data['storage'])) {
throw new UnexpectedValueException(sprintf(
'Cannot deserialize %s instance: corrupt storage data; expected array or object, received %s',
self::class,
gettype($data['storage'])
));
}
$this->exchangeArray($data['storage']);
unset($data['storage']);
}
if (array_key_exists('iteratorClass', $data)) {
if (! is_string($data['iteratorClass'])) {
throw new UnexpectedValueException(sprintf(
'Cannot deserialize %s instance: invalid iteratorClass; expected string, received %s',
self::class,
get_debug_type($data['iteratorClass'])
));
}
$this->setIteratorClass($data['iteratorClass']);
unset($data['iteratorClass']);
}
unset($data['protectedProperties']);
// Unserialize array keys after resolving protected properties to ensure configuration is used.
foreach ($data as $k => $v) {
$this->__set($k, $v);
}
}
}
laminas-stdlib/src/FastPriorityQueue.php 0000644 00000023756 15240152644 0014433 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
use Countable;
use Iterator;
use ReturnTypeWillChange;
use Serializable;
use SplPriorityQueue as PhpSplPriorityQueue;
use UnexpectedValueException;
use function current;
use function in_array;
use function is_array;
use function is_int;
use function key;
use function max;
use function next;
use function reset;
use function serialize;
use function sprintf;
use function unserialize;
/**
* This is an efficient implementation of an integer priority queue in PHP
*
* This class acts like a queue with insert() and extract(), removing the
* elements from the queue and it also acts like an Iterator without removing
* the elements. This behaviour can be used in mixed scenarios with high
* performance boost.
*/
class FastPriorityQueue implements Iterator, Countable, Serializable
{
public const EXTR_DATA = PhpSplPriorityQueue::EXTR_DATA;
public const EXTR_PRIORITY = PhpSplPriorityQueue::EXTR_PRIORITY;
public const EXTR_BOTH = PhpSplPriorityQueue::EXTR_BOTH;
/** @var integer */
protected $extractFlag = self::EXTR_DATA;
/**
* Elements of the queue, divided by priorities
*
* @var array
*/
protected $values = [];
/**
* Array of priorities
*
* @var array
*/
protected $priorities = [];
/**
* Array of priorities used for the iteration
*
* @var array
*/
protected $subPriorities = [];
/**
* Max priority
*
* @var int|null
*/
protected $maxPriority;
/**
* Total number of elements in the queue
*
* @var int
*/
protected $count = 0;
/**
* Index of the current element in the queue
*
* @var int
*/
protected $index = 0;
/**
* Sub index of the current element in the same priority level
*
* @var int
*/
protected $subIndex = 0;
public function __serialize(): array
{
$clone = clone $this;
$clone->setExtractFlags(self::EXTR_BOTH);
$data = [];
foreach ($clone as $item) {
$data[] = $item;
}
return $data;
}
public function __unserialize(array $data): void
{
foreach ($data as $item) {
$this->insert($item['data'], $item['priority']);
}
}
/**
* Insert an element in the queue with a specified priority
*
* @param int $priority
* @return void
*/
public function insert(mixed $value, $priority)
{
if (! is_int($priority)) {
throw new Exception\InvalidArgumentException('The priority must be an integer');
}
$this->values[$priority][] = $value;
if (! isset($this->priorities[$priority])) {
$this->priorities[$priority] = $priority;
$this->maxPriority = $this->maxPriority === null ? $priority : max($priority, $this->maxPriority);
}
++$this->count;
}
/**
* Extract an element in the queue according to the priority and the
* order of insertion
*
* @return mixed
*/
public function extract()
{
if (! $this->valid()) {
return false;
}
$value = $this->current();
$this->nextAndRemove();
return $value;
}
/**
* Remove an item from the queue
*
* This is different than {@link extract()}; its purpose is to dequeue an
* item.
*
* Note: this removes the first item matching the provided item found. If
* the same item has been added multiple times, it will not remove other
* instances.
*
* @return bool False if the item was not found, true otherwise.
*/
public function remove(mixed $datum)
{
$currentIndex = $this->index;
$currentSubIndex = $this->subIndex;
$currentPriority = $this->maxPriority;
$this->rewind();
while ($this->valid()) {
if (current($this->values[$this->maxPriority]) === $datum) {
$index = key($this->values[$this->maxPriority]);
unset($this->values[$this->maxPriority][$index]);
// The `next()` method advances the internal array pointer, so we need to use the `reset()` function,
// otherwise we would lose all elements before the place the pointer points.
reset($this->values[$this->maxPriority]);
$this->index = $currentIndex;
$this->subIndex = $currentSubIndex;
// If the array is empty we need to destroy the unnecessary priority,
// otherwise we would end up with an incorrect value of `$this->count`
// {@see \Laminas\Stdlib\FastPriorityQueue::nextAndRemove()}.
if (empty($this->values[$this->maxPriority])) {
unset($this->values[$this->maxPriority]);
unset($this->priorities[$this->maxPriority]);
if ($this->maxPriority === $currentPriority) {
$this->subIndex = 0;
}
}
$this->maxPriority = empty($this->priorities) ? null : max($this->priorities);
--$this->count;
return true;
}
$this->next();
}
return false;
}
/**
* Get the total number of elements in the queue
*
* @return int
*/
#[ReturnTypeWillChange]
public function count()
{
return $this->count;
}
/**
* Get the current element in the queue
*
* @return mixed
*/
#[ReturnTypeWillChange]
public function current()
{
switch ($this->extractFlag) {
case self::EXTR_DATA:
return current($this->values[$this->maxPriority]);
case self::EXTR_PRIORITY:
return $this->maxPriority;
case self::EXTR_BOTH:
return [
'data' => current($this->values[$this->maxPriority]),
'priority' => $this->maxPriority,
];
}
}
/**
* Get the index of the current element in the queue
*
* @return int
*/
#[ReturnTypeWillChange]
public function key()
{
return $this->index;
}
/**
* Set the iterator pointer to the next element in the queue
* removing the previous element
*
* @return void
*/
protected function nextAndRemove()
{
$key = key($this->values[$this->maxPriority]);
if (false === next($this->values[$this->maxPriority])) {
unset($this->priorities[$this->maxPriority]);
unset($this->values[$this->maxPriority]);
$this->maxPriority = empty($this->priorities) ? null : max($this->priorities);
$this->subIndex = -1;
} else {
unset($this->values[$this->maxPriority][$key]);
}
++$this->index;
++$this->subIndex;
--$this->count;
}
/**
* Set the iterator pointer to the next element in the queue
* without removing the previous element
*/
#[ReturnTypeWillChange]
public function next()
{
if (false === next($this->values[$this->maxPriority])) {
unset($this->subPriorities[$this->maxPriority]);
reset($this->values[$this->maxPriority]);
$this->maxPriority = empty($this->subPriorities) ? null : max($this->subPriorities);
$this->subIndex = -1;
}
++$this->index;
++$this->subIndex;
}
/**
* Check if the current iterator is valid
*
* @return bool
*/
#[ReturnTypeWillChange]
public function valid()
{
return isset($this->values[$this->maxPriority]);
}
/**
* Rewind the current iterator
*/
#[ReturnTypeWillChange]
public function rewind()
{
$this->subPriorities = $this->priorities;
$this->maxPriority = empty($this->priorities) ? 0 : max($this->priorities);
$this->index = 0;
$this->subIndex = 0;
}
/**
* Serialize to an array
*
* Array will be priority => data pairs
*
* @return array
*/
public function toArray()
{
$array = [];
foreach (clone $this as $item) {
$array[] = $item;
}
return $array;
}
/**
* Serialize
*
* @return string
*/
public function serialize()
{
return serialize($this->__serialize());
}
/**
* Deserialize
*
* @param string $data
* @return void
*/
public function unserialize($data)
{
$toUnserialize = unserialize($data);
if (! is_array($toUnserialize)) {
throw new UnexpectedValueException(sprintf(
'Cannot deserialize %s instance; corrupt serialization data',
self::class
));
}
$this->__unserialize($toUnserialize);
}
/**
* Set the extract flag
*
* @param int $flag
* @return void
*/
public function setExtractFlags($flag)
{
$this->extractFlag = match ($flag) {
self::EXTR_DATA, self::EXTR_PRIORITY, self::EXTR_BOTH => $flag,
default => throw new Exception\InvalidArgumentException("The extract flag specified is not valid"),
};
}
/**
* Check if the queue is empty
*
* @return bool
*/
public function isEmpty()
{
return empty($this->values);
}
/**
* Does the queue contain the given datum?
*
* @return bool
*/
public function contains(mixed $datum)
{
foreach ($this->values as $values) {
if (in_array($datum, $values)) {
return true;
}
}
return false;
}
/**
* Does the queue have an item with the given priority?
*
* @param int $priority
* @return bool
*/
public function hasPriority($priority)
{
return isset($this->values[$priority]);
}
}
laminas-stdlib/src/ArrayUtils/MergeRemoveKey.php 0000644 00000000146 15240152644 0015740 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\ArrayUtils;
final class MergeRemoveKey
{
}
laminas-stdlib/src/ArrayUtils/MergeReplaceKey.php 0000644 00000000472 15240152644 0016060 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\ArrayUtils;
final class MergeReplaceKey implements MergeReplaceKeyInterface
{
public function __construct(protected mixed $data)
{
}
/**
* {@inheritDoc}
*/
public function getData()
{
return $this->data;
}
}
laminas-stdlib/src/ArrayUtils/MergeReplaceKeyInterface.php 0000644 00000000437 15240152644 0017702 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\ArrayUtils;
/**
* Marker interface: can be used to replace keys completely in {@see ArrayUtils::merge()} operations
*/
interface MergeReplaceKeyInterface
{
/**
* @return mixed
*/
public function getData();
}
laminas-stdlib/src/JsonSerializable.php 0000644 00000000421 15240152644 0014207 0 ustar 00 <?php // phpcs:disable WebimpressCodingStandard.NamingConventions.Interface.Suffix
declare(strict_types=1);
namespace Laminas\Stdlib;
/**
* @deprecated Since 3.1.0; use the native JsonSerializable interface
*/
interface JsonSerializable extends \JsonSerializable
{
}
laminas-stdlib/src/Glob.php 0000644 00000014031 15240152644 0011634 0 ustar 00 <?php // phpcs:disable WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix,Generic.NamingConventions.ConstructorName.OldStyle
declare(strict_types=1);
namespace Laminas\Stdlib;
use function array_merge;
use function array_unique;
use function defined;
use function glob;
use function strlen;
use function strpos;
use function substr;
use const GLOB_BRACE;
use const GLOB_ERR;
use const GLOB_MARK;
use const GLOB_NOCHECK;
use const GLOB_NOESCAPE;
use const GLOB_NOSORT;
use const GLOB_ONLYDIR;
/**
* Wrapper for glob with fallback if GLOB_BRACE is not available.
*/
abstract class Glob
{
/**#@+
* Glob constants.
*/
public const GLOB_MARK = 0x01;
public const GLOB_NOSORT = 0x02;
public const GLOB_NOCHECK = 0x04;
public const GLOB_NOESCAPE = 0x08;
public const GLOB_BRACE = 0x10;
public const GLOB_ONLYDIR = 0x20;
public const GLOB_ERR = 0x40;
/**#@-*/
/**
* Find pathnames matching a pattern.
*
* @see http://docs.php.net/glob
*
* @param string $pattern
* @param int $flags
* @param bool $forceFallback
* @return array
* @throws Exception\RuntimeException
*/
public static function glob($pattern, $flags = 0, $forceFallback = false)
{
if (! defined('GLOB_BRACE') || $forceFallback) {
return static::fallbackGlob($pattern, $flags);
}
return static::systemGlob($pattern, $flags);
}
/**
* Use the glob function provided by the system.
*
* @param string $pattern
* @param int $flags
* @return array
* @throws Exception\RuntimeException
*/
protected static function systemGlob($pattern, $flags)
{
if ($flags) {
$flagMap = [
self::GLOB_MARK => GLOB_MARK,
self::GLOB_NOSORT => GLOB_NOSORT,
self::GLOB_NOCHECK => GLOB_NOCHECK,
self::GLOB_NOESCAPE => GLOB_NOESCAPE,
self::GLOB_BRACE => defined('GLOB_BRACE') ? GLOB_BRACE : 0,
self::GLOB_ONLYDIR => GLOB_ONLYDIR,
self::GLOB_ERR => GLOB_ERR,
];
$globFlags = 0;
foreach ($flagMap as $internalFlag => $globFlag) {
if ($flags & $internalFlag) {
$globFlags |= $globFlag;
}
}
} else {
$globFlags = 0;
}
ErrorHandler::start();
$res = glob($pattern, $globFlags);
$err = ErrorHandler::stop();
if ($res === false) {
throw new Exception\RuntimeException("glob('{$pattern}', {$globFlags}) failed", 0, $err);
}
return $res;
}
/**
* Expand braces manually, then use the system glob.
*
* @param string $pattern
* @param int $flags
* @return array
* @throws Exception\RuntimeException
*/
protected static function fallbackGlob($pattern, $flags)
{
if (! self::flagsIsEqualTo($flags, self::GLOB_BRACE)) {
return static::systemGlob($pattern, $flags);
}
$flags &= ~self::GLOB_BRACE;
$length = strlen($pattern);
$paths = [];
if ($flags & self::GLOB_NOESCAPE) {
$begin = strpos($pattern, '{');
} else {
$begin = 0;
while (true) {
if ($begin === $length) {
$begin = false;
break;
} elseif ($pattern[$begin] === '\\' && ($begin + 1) < $length) {
$begin++;
} elseif ($pattern[$begin] === '{') {
break;
}
$begin++;
}
}
if ($begin === false) {
return static::systemGlob($pattern, $flags);
}
$next = static::nextBraceSub($pattern, $begin + 1, $flags);
if ($next === null) {
return static::systemGlob($pattern, $flags);
}
$rest = $next;
while ($pattern[$rest] !== '}') {
$rest = static::nextBraceSub($pattern, $rest + 1, $flags);
if ($rest === null) {
return static::systemGlob($pattern, $flags);
}
}
$p = $begin + 1;
while (true) {
$subPattern = substr($pattern, 0, $begin)
. substr($pattern, $p, $next - $p)
. substr($pattern, $rest + 1);
$result = static::fallbackGlob($subPattern, $flags | self::GLOB_BRACE);
if ($result) {
$paths = array_merge($paths, $result);
}
if ($pattern[$next] === '}') {
break;
}
$p = $next + 1;
$next = static::nextBraceSub($pattern, $p, $flags);
}
return array_unique($paths);
}
/**
* Find the end of the sub-pattern in a brace expression.
*
* @param string $pattern
* @param int $begin
* @param int $flags
* @return int|null
*/
protected static function nextBraceSub($pattern, $begin, $flags)
{
$length = strlen($pattern);
$depth = 0;
$current = $begin;
while ($current < $length) {
$flagsEqualsNoEscape = self::flagsIsEqualTo($flags, self::GLOB_NOESCAPE);
if ($flagsEqualsNoEscape && $pattern[$current] === '\\') {
if (++$current === $length) {
break;
}
$current++;
} else {
if (
($pattern[$current] === '}' && $depth-- === 0)
|| ($pattern[$current] === ',' && $depth === 0)
) {
break;
} elseif ($pattern[$current++] === '{') {
$depth++;
}
}
}
return $current < $length ? $current : null;
}
/** @internal */
public static function flagsIsEqualTo(int $flags, int $otherFlags): bool
{
return (bool) ($flags & $otherFlags);
}
}
laminas-stdlib/src/AbstractOptions.php 0000644 00000011501 15240152644 0014067 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
use Traversable;
use function array_shift;
use function is_array;
use function is_callable;
use function method_exists;
use function preg_replace_callback;
use function sprintf;
use function str_replace;
use function strtolower;
use function ucwords;
abstract class AbstractOptions implements ParameterObjectInterface
{
// phpcs:disable PSR2.Classes.PropertyDeclaration.Underscore,WebimpressCodingStandard.NamingConventions.ValidVariableName.NotCamelCapsProperty
/**
* We use the __ prefix to avoid collisions with properties in
* user-implementations.
*
* @var bool
*/
protected $__strictMode__ = true;
// phpcs:enable
/**
* Constructor
*
* @param array|Traversable|null $options
*/
public function __construct($options = null)
{
if (null !== $options) {
$this->setFromArray($options);
}
}
/**
* Set one or more configuration properties
*
* @param array|Traversable|AbstractOptions $options
* @throws Exception\InvalidArgumentException
* @return AbstractOptions Provides fluent interface
*/
public function setFromArray($options)
{
if ($options instanceof self) {
$options = $options->toArray();
}
if (! is_array($options) && ! $options instanceof Traversable) {
throw new Exception\InvalidArgumentException(
sprintf(
'Parameter provided to %s must be an %s, %s or %s',
__METHOD__,
'array',
'Traversable',
self::class
)
);
}
foreach ($options as $key => $value) {
$this->__set($key, $value);
}
return $this;
}
/**
* Cast to array
*
* @return array
*/
public function toArray()
{
$array = [];
/** @param string[] $letters */
$transform = static function (array $letters): string {
$letter = array_shift($letters);
return '_' . strtolower($letter);
};
foreach ($this as $key => $value) {
if ($key === '__strictMode__') {
continue;
}
$normalizedKey = preg_replace_callback('/([A-Z])/', $transform, $key);
$array[$normalizedKey] = $value;
}
return $array;
}
/**
* Set a configuration property
*
* @see ParameterObject::__set()
*
* @param string $key
* @param mixed $value
* @throws Exception\BadMethodCallException
* @return void
*/
public function __set($key, $value)
{
$setter = 'set' . str_replace('_', '', $key);
if (is_callable([$this, $setter])) {
$this->{$setter}($value);
return;
}
if ($this->__strictMode__) {
throw new Exception\BadMethodCallException(sprintf(
'The option "%s" does not have a callable "%s" ("%s") setter method which must be defined',
$key,
'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))),
$setter
));
}
}
/**
* Get a configuration property
*
* @see ParameterObject::__get()
*
* @param string $key
* @throws Exception\BadMethodCallException
* @return mixed
*/
public function __get($key)
{
$getter = 'get' . str_replace('_', '', $key);
if (is_callable([$this, $getter])) {
return $this->{$getter}();
}
throw new Exception\BadMethodCallException(sprintf(
'The option "%s" does not have a callable "%s" getter method which must be defined',
$key,
'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key)))
));
}
/**
* Test if a configuration property is null
*
* @see ParameterObject::__isset()
*
* @param string $key
* @return bool
*/
public function __isset($key)
{
$getter = 'get' . str_replace('_', '', $key);
return method_exists($this, $getter) && null !== $this->__get($key);
}
/**
* Set a configuration property to NULL
*
* @see ParameterObject::__unset()
*
* @param string $key
* @throws Exception\InvalidArgumentException
* @return void
*/
public function __unset($key)
{
try {
$this->__set($key, null);
} catch (Exception\BadMethodCallException $e) {
throw new Exception\InvalidArgumentException(
'The class property $' . $key . ' cannot be unset as'
. ' NULL is an invalid value for it',
0,
$e
);
}
}
}
laminas-stdlib/src/Request.php 0000644 00000000240 15240152644 0012376 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
class Request extends Message implements RequestInterface
{
// generic request implementation
}
laminas-stdlib/src/RequestInterface.php 0000644 00000000164 15240152644 0014224 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
interface RequestInterface extends MessageInterface
{
}
laminas-stdlib/src/MessageInterface.php 0000644 00000001231 15240152644 0014154 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
use Traversable;
interface MessageInterface
{
/**
* Set metadata
*
* @param string|int|array|Traversable $spec
* @param mixed $value
*/
public function setMetadata($spec, $value = null);
/**
* Get metadata
*
* @param null|string|int $key
* @return mixed
*/
public function getMetadata($key = null);
/**
* Set content
*
* @param mixed $content
* @return mixed
*/
public function setContent($content);
/**
* Get content
*
* @return mixed
*/
public function getContent();
}
laminas-stdlib/src/SplQueue.php 0000644 00000003517 15240152645 0012524 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
use ReturnTypeWillChange;
use Serializable;
use UnexpectedValueException;
use function is_array;
use function serialize;
use function sprintf;
use function unserialize;
/**
* Serializable version of SplQueue
*
* @template TKey of array-key
* @template TValue
* @extends \SplQueue<TValue>
*/
class SplQueue extends \SplQueue implements Serializable
{
/**
* Return an array representing the queue
*
* @return list<TValue>
*/
public function toArray()
{
$array = [];
foreach ($this as $item) {
$array[] = $item;
}
return $array;
}
/**
* Serialize
*
* @return string
*/
#[ReturnTypeWillChange]
public function serialize()
{
return serialize($this->__serialize());
}
/**
* Magic method used for serializing of an instance.
*
* @return list<TValue>
*/
#[ReturnTypeWillChange]
public function __serialize()
{
return $this->toArray();
}
/**
* Unserialize
*
* @param string $data
* @return void
*/
#[ReturnTypeWillChange]
public function unserialize($data)
{
$toUnserialize = unserialize($data);
if (! is_array($toUnserialize)) {
throw new UnexpectedValueException(sprintf(
'Cannot deserialize %s instance; corrupt serialization data',
self::class
));
}
$this->__unserialize($toUnserialize);
}
/**
* Magic method used to rebuild an instance.
*
* @param array<array-key, TValue> $data Data array.
* @return void
*/
#[ReturnTypeWillChange]
public function __unserialize($data)
{
foreach ($data as $item) {
$this->push($item);
}
}
}
laminas-stdlib/src/SplPriorityQueue.php 0000644 00000007046 15240152645 0014267 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
use Serializable;
use UnexpectedValueException;
use function array_key_exists;
use function get_debug_type;
use function is_array;
use function serialize;
use function sprintf;
use function unserialize;
use const PHP_INT_MAX;
/**
* Serializable version of SplPriorityQueue
*
* Also, provides predictable heap order for datums added with the same priority
* (i.e., they will be emitted in the same order they are enqueued).
*
* @template TValue
* @template TPriority of int
* @extends \SplPriorityQueue<TPriority, TValue>
*/
class SplPriorityQueue extends \SplPriorityQueue implements Serializable
{
/** @var int Seed used to ensure queue order for items of the same priority */
protected $serial = PHP_INT_MAX;
/**
* Insert a value with a given priority
*
* Utilizes {@var $serial} to ensure that values of equal priority are
* emitted in the same order in which they are inserted.
*
* @param TValue $datum
* @param TPriority $priority
* @return void
*/
public function insert($datum, $priority)
{
if (! is_array($priority)) {
$priority = [$priority, $this->serial--];
}
parent::insert($datum, $priority);
}
/**
* Serialize to an array
*
* Array will be priority => data pairs
*
* @return list<TValue>
*/
public function toArray()
{
$array = [];
foreach (clone $this as $item) {
$array[] = $item;
}
return $array;
}
/**
* Serialize
*
* @return string
*/
public function serialize()
{
return serialize($this->__serialize());
}
/**
* Magic method used for serializing of an instance.
*
* @return array
*/
public function __serialize()
{
$clone = clone $this;
$clone->setExtractFlags(self::EXTR_BOTH);
$data = [];
foreach ($clone as $item) {
$data[] = $item;
}
return $data;
}
/**
* Deserialize
*
* @param string $data
* @return void
*/
public function unserialize($data)
{
$toUnserialize = unserialize($data);
if (! is_array($toUnserialize)) {
throw new UnexpectedValueException(sprintf(
'Cannot deserialize %s instance; corrupt serialization data',
self::class
));
}
$this->__unserialize($toUnserialize);
}
/**
* Magic method used to rebuild an instance.
*
* @param array<array-key, mixed> $data Data array.
* @return void
*/
public function __unserialize($data)
{
$this->serial = PHP_INT_MAX;
foreach ($data as $item) {
if (! is_array($item)) {
throw new UnexpectedValueException(sprintf(
'Cannot deserialize %s instance: corrupt item; expected array, received %s',
self::class,
get_debug_type($item)
));
}
if (! array_key_exists('data', $item)) {
throw new UnexpectedValueException(sprintf(
'Cannot deserialize %s instance: corrupt item; missing "data" element',
self::class
));
}
$priority = 1;
if (array_key_exists('priority', $item)) {
$priority = (int) $item['priority'];
}
$this->insert($item['data'], $priority);
}
}
}
laminas-stdlib/src/ResponseInterface.php 0000644 00000000165 15240152645 0014374 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
interface ResponseInterface extends MessageInterface
{
}
laminas-stdlib/src/ArrayStack.php 0000644 00000001230 15240152645 0013013 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
use ArrayIterator;
use ArrayObject as PhpArrayObject;
use ReturnTypeWillChange;
use function array_reverse;
/**
* ArrayObject that acts as a stack with regards to iteration
*/
class ArrayStack extends PhpArrayObject
{
/**
* Retrieve iterator
*
* Retrieve an array copy of the object, reverse its order, and return an
* ArrayIterator with that reversed array.
*
* @return ArrayIterator
*/
#[ReturnTypeWillChange]
public function getIterator()
{
$array = $this->getArrayCopy();
return new ArrayIterator(array_reverse($array));
}
}
laminas-stdlib/src/ArraySerializableInterface.php 0000644 00000000572 15240152645 0016205 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
interface ArraySerializableInterface
{
/**
* Exchange internal values from provided array
*
* @return void
*/
public function exchangeArray(array $array);
/**
* Return an array representation of the object
*
* @return array
*/
public function getArrayCopy();
}
laminas-stdlib/src/PriorityList.php 0000644 00000012434 15240152645 0013434 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
use Countable;
use Exception;
use Iterator;
use ReturnTypeWillChange;
use function array_map;
use function current;
use function key;
use function next;
use function reset;
use function uasort;
class PriorityList implements Iterator, Countable
{
public const EXTR_DATA = 0x00000001;
public const EXTR_PRIORITY = 0x00000002;
public const EXTR_BOTH = 0x00000003;
/**
* Internal list of all items.
*
* @var array[]
*/
protected $items = [];
/**
* Serial assigned to items to preserve LIFO.
*
* @var int
*/
protected $serial = 0;
// phpcs:disable WebimpressCodingStandard.NamingConventions.ValidVariableName.NotCamelCapsProperty
/**
* Serial order mode
*
* @var integer
*/
protected $isLIFO = 1;
// phpcs:enable
/**
* Internal counter to avoid usage of count().
*
* @var int
*/
protected $count = 0;
/**
* Whether the list was already sorted.
*
* @var bool
*/
protected $sorted = false;
/**
* Insert a new item.
*
* @param string $name
* @param int $priority
* @return void
*/
public function insert($name, mixed $value, $priority = 0)
{
if (! isset($this->items[$name])) {
$this->count++;
}
$this->sorted = false;
$this->items[$name] = [
'data' => $value,
'priority' => (int) $priority,
'serial' => $this->serial++,
];
}
/**
* @param string $name
* @param int $priority
* @return $this
* @throws Exception
*/
public function setPriority($name, $priority)
{
if (! isset($this->items[$name])) {
throw new Exception("item $name not found");
}
$this->items[$name]['priority'] = (int) $priority;
$this->sorted = false;
return $this;
}
/**
* Remove a item.
*
* @param string $name
* @return void
*/
public function remove($name)
{
if (isset($this->items[$name])) {
$this->count--;
}
unset($this->items[$name]);
}
/**
* Remove all items.
*
* @return void
*/
public function clear()
{
$this->items = [];
$this->serial = 0;
$this->count = 0;
$this->sorted = false;
}
/**
* Get a item.
*
* @param string $name
* @return mixed
*/
public function get($name)
{
if (! isset($this->items[$name])) {
return;
}
return $this->items[$name]['data'];
}
/**
* Sort all items.
*
* @return void
*/
protected function sort()
{
if (! $this->sorted) {
uasort($this->items, [$this, 'compare']);
$this->sorted = true;
}
}
/**
* Compare the priority of two items.
*
* @param array $item1,
* @return int
*/
protected function compare(array $item1, array $item2)
{
return $item1['priority'] === $item2['priority']
? ($item1['serial'] > $item2['serial'] ? -1 : 1) * $this->isLIFO
: ($item1['priority'] > $item2['priority'] ? -1 : 1);
}
/**
* Get/Set serial order mode
*
* @param bool|null $flag
* @return bool
*/
public function isLIFO($flag = null)
{
if ($flag !== null) {
$isLifo = $flag === true ? 1 : -1;
if ($isLifo !== $this->isLIFO) {
$this->isLIFO = $isLifo;
$this->sorted = false;
}
}
return 1 === $this->isLIFO;
}
/**
* {@inheritDoc}
*/
#[ReturnTypeWillChange]
public function rewind()
{
$this->sort();
reset($this->items);
}
/**
* {@inheritDoc}
*/
#[ReturnTypeWillChange]
public function current()
{
$this->sorted || $this->sort();
$node = current($this->items);
return $node ? $node['data'] : false;
}
/**
* {@inheritDoc}
*/
#[ReturnTypeWillChange]
public function key()
{
$this->sorted || $this->sort();
return key($this->items);
}
/**
* {@inheritDoc}
*/
#[ReturnTypeWillChange]
public function next()
{
$node = next($this->items);
return $node ? $node['data'] : false;
}
/**
* {@inheritDoc}
*/
#[ReturnTypeWillChange]
public function valid()
{
return current($this->items) !== false;
}
/**
* @return self
*/
public function getIterator()
{
return clone $this;
}
/**
* {@inheritDoc}
*/
#[ReturnTypeWillChange]
public function count()
{
return $this->count;
}
/**
* Return list as array
*
* @param int $flag
* @return array
*/
public function toArray($flag = self::EXTR_DATA)
{
$this->sort();
if ($flag === self::EXTR_BOTH) {
return $this->items;
}
return array_map(
static fn($item) => $flag === self::EXTR_PRIORITY ? $item['priority'] : $item['data'],
$this->items
);
}
}
laminas-stdlib/src/StringWrapper/Iconv.php 0000644 00000015163 15240152645 0014646 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\StringWrapper;
use Laminas\Stdlib\Exception;
use function assert;
use function extension_loaded;
use function iconv;
use function iconv_strlen;
use function iconv_strpos;
use function iconv_substr;
class Iconv extends AbstractStringWrapper
{
/**
* List of supported character sets (upper case)
*
* @link http://www.gnu.org/software/libiconv/
*
* @var string[]
*/
protected static $encodings = [
// European languages
'ASCII',
'ISO-8859-1',
'ISO-8859-2',
'ISO-8859-3',
'ISO-8859-4',
'ISO-8859-5',
'ISO-8859-7',
'ISO-8859-9',
'ISO-8859-10',
'ISO-8859-13',
'ISO-8859-14',
'ISO-8859-15',
'ISO-8859-16',
'KOI8-R',
'KOI8-U',
'KOI8-RU',
'CP1250',
'CP1251',
'CP1252',
'CP1253',
'CP1254',
'CP1257',
'CP850',
'CP866',
'CP1131',
'MACROMAN',
'MACCENTRALEUROPE',
'MACICELAND',
'MACCROATIAN',
'MACROMANIA',
'MACCYRILLIC',
'MACUKRAINE',
'MACGREEK',
'MACTURKISH',
'MACINTOSH',
// Semitic languages
'ISO-8859-6',
'ISO-8859-8',
'CP1255',
'CP1256',
'CP862',
'MACHEBREW',
'MACARABIC',
// Japanese
'EUC-JP',
'SHIFT_JIS',
'CP932',
'ISO-2022-JP',
'ISO-2022-JP-2',
'ISO-2022-JP-1',
// Chinese
'EUC-CN',
'HZ',
'GBK',
'CP936',
'GB18030',
'EUC-TW',
'BIG5',
'CP950',
'BIG5-HKSCS',
'BIG5-HKSCS:2004',
'BIG5-HKSCS:2001',
'BIG5-HKSCS:1999',
'ISO-2022-CN',
'ISO-2022-CN-EXT',
// Korean
'EUC-KR',
'CP949',
'ISO-2022-KR',
'JOHAB',
// Armenian
'ARMSCII-8',
// Georgian
'GEORGIAN-ACADEMY',
'GEORGIAN-PS',
// Tajik
'KOI8-T',
// Kazakh
'PT154',
'RK1048',
// Thai
'ISO-8859-11',
'TIS-620',
'CP874',
'MACTHAI',
// Laotian
'MULELAO-1',
'CP1133',
// Vietnamese
'VISCII',
'TCVN',
'CP1258',
// Platform specifics
'HP-ROMAN8',
'NEXTSTEP',
// Full Unicode
'UTF-8',
'UCS-2',
'UCS-2BE',
'UCS-2LE',
'UCS-4',
'UCS-4BE',
'UCS-4LE',
'UTF-16',
'UTF-16BE',
'UTF-16LE',
'UTF-32',
'UTF-32BE',
'UTF-32LE',
'UTF-7',
'C99',
'JAVA',
/* Commented out because that's internal encodings not existing in real world
// Full Unicode, in terms of uint16_t or uint32_t (with machine dependent endianness and alignment)
'UCS-2-INTERNAL',
'UCS-4-INTERNAL',
// Locale dependent, in terms of `char' or `wchar_t' (with machine dependent endianness and alignment,
// and with OS and locale dependent semantics)
'char',
'wchar_t',
'', // The empty encoding name is equivalent to "char": it denotes the locale dependent character encoding.
*/
// When configured with the option --enable-extra-encodings,
// it also provides support for a few extra encodings:
// European languages
'CP437',
'CP737',
'CP775',
'CP852',
'CP853',
'CP855',
'CP857',
'CP858',
'CP860',
'CP861',
'CP863',
'CP865',
'CP869',
'CP1125',
// Semitic languages
'CP864',
// Japanese
'EUC-JISX0213',
'Shift_JISX0213',
'ISO-2022-JP-3',
// Chinese
'BIG5-2003', // (experimental)
// Turkmen
'TDS565',
// Platform specifics
'ATARIST',
'RISCOS-LATIN1',
];
/**
* Get a list of supported character encodings
*
* @return string[]
*/
public static function getSupportedEncodings()
{
return static::$encodings;
}
/**
* Constructor
*
* @throws Exception\ExtensionNotLoadedException
*/
public function __construct()
{
if (! extension_loaded('iconv')) {
throw new Exception\ExtensionNotLoadedException(
'PHP extension "iconv" is required for this wrapper'
);
}
}
/**
* Returns the length of the given string
*
* @param string $str
* @return int|false
*/
public function strlen($str)
{
return iconv_strlen($str, $this->getEncoding());
}
/**
* Returns the portion of string specified by the start and length parameters
*
* @param string $str
* @param int $offset
* @param int|null $length
* @return string|false
*/
public function substr($str, $offset = 0, $length = null)
{
$length ??= $this->strlen($str);
assert($length !== false);
return iconv_substr($str, $offset, $length, $this->getEncoding());
}
/**
* Find the position of the first occurrence of a substring in a string
*
* @param string $haystack
* @param string $needle
* @param int $offset
* @return int|false
*/
public function strpos($haystack, $needle, $offset = 0)
{
$encoding = $this->getEncoding();
assert($encoding !== null);
return iconv_strpos($haystack, $needle, $offset, $encoding);
}
/**
* Convert a string from defined encoding to the defined convert encoding
*
* @param string $str
* @param bool $reverse
* @return string|false
*/
public function convert($str, $reverse = false)
{
$encoding = $this->getEncoding();
$convertEncoding = $this->getConvertEncoding();
if ($convertEncoding === null) {
throw new Exception\LogicException(
'No convert encoding defined'
);
}
if ($encoding === $convertEncoding) {
return $str;
}
$fromEncoding = $reverse ? $convertEncoding : $encoding;
$toEncoding = $reverse ? $encoding : $convertEncoding;
if (null === $toEncoding || null === $fromEncoding) {
return $str;
}
// automatically add "//IGNORE" to not stop converting on invalid characters
// invalid characters triggers a notice anyway
return iconv($fromEncoding, $toEncoding . '//IGNORE', $str);
}
}
laminas-stdlib/src/StringWrapper/Intl.php 0000644 00000004027 15240152645 0014473 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\StringWrapper;
use Laminas\Stdlib\Exception;
use function extension_loaded;
use function grapheme_strlen;
use function grapheme_strpos;
use function grapheme_substr;
class Intl extends AbstractStringWrapper
{
/**
* List of supported character sets (upper case)
*
* @var string[]
*/
protected static $encodings = ['UTF-8'];
/**
* Get a list of supported character encodings
*
* @return string[]
*/
public static function getSupportedEncodings()
{
return static::$encodings;
}
/**
* Constructor
*
* @throws Exception\ExtensionNotLoadedException
*/
public function __construct()
{
if (! extension_loaded('intl')) {
throw new Exception\ExtensionNotLoadedException(
'PHP extension "intl" is required for this wrapper'
);
}
}
/**
* Returns the length of the given string
*
* @param string $str
* @return false|int
*/
public function strlen($str)
{
$len = grapheme_strlen($str);
return $len ?? false;
}
/**
* Returns the portion of string specified by the start and length parameters
*
* @param string $str
* @param int $offset
* @param int|null $length
* @return string|false
*/
public function substr($str, $offset = 0, $length = null)
{
// Due fix of PHP #62759 The third argument returns an empty string if is 0 or null.
if ($length !== null) {
return grapheme_substr($str, $offset, $length);
}
return grapheme_substr($str, $offset);
}
/**
* Find the position of the first occurrence of a substring in a string
*
* @param string $haystack
* @param string $needle
* @param int $offset
* @return int|false
*/
public function strpos($haystack, $needle, $offset = 0)
{
return grapheme_strpos($haystack, $needle, $offset);
}
}
laminas-stdlib/src/StringWrapper/Native.php 0000644 00000007141 15240152645 0015013 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\StringWrapper;
use Laminas\Stdlib\Exception;
use Laminas\Stdlib\StringUtils;
use function in_array;
use function strlen;
use function strpos;
use function strtoupper;
use function substr;
class Native extends AbstractStringWrapper
{
/**
* The character encoding working on
* (overwritten to change default encoding)
*
* @var string
*/
protected $encoding = 'ASCII';
/**
* Check if the given character encoding is supported by this wrapper
* and the character encoding to convert to is also supported.
*
* @param string $encoding
* @param string|null $convertEncoding
* @return bool
*/
public static function isSupported($encoding, $convertEncoding = null)
{
$encodingUpper = strtoupper($encoding);
$supportedEncodings = static::getSupportedEncodings();
if (! in_array($encodingUpper, $supportedEncodings)) {
return false;
}
// This adapter doesn't support to convert between encodings
if ($convertEncoding !== null && $encodingUpper !== strtoupper($convertEncoding)) {
return false;
}
return true;
}
/**
* Get a list of supported character encodings
*
* @return string[]
*/
public static function getSupportedEncodings()
{
return StringUtils::getSingleByteEncodings();
}
/**
* Set character encoding working with and convert to
*
* @param string $encoding The character encoding to work with
* @param string|null $convertEncoding The character encoding to convert to
* @return StringWrapperInterface
*/
public function setEncoding($encoding, $convertEncoding = null)
{
$supportedEncodings = static::getSupportedEncodings();
$encodingUpper = strtoupper($encoding);
if (! in_array($encodingUpper, $supportedEncodings)) {
throw new Exception\InvalidArgumentException(
'Wrapper doesn\'t support character encoding "' . $encoding . '"'
);
}
if (null !== $convertEncoding && $encodingUpper !== strtoupper($convertEncoding)) {
$this->convertEncoding = $encodingUpper;
}
if ($convertEncoding !== null) {
if ($encodingUpper !== strtoupper($convertEncoding)) {
throw new Exception\InvalidArgumentException(
'Wrapper doesn\'t support to convert between character encodings'
);
}
$this->convertEncoding = $encodingUpper;
} else {
$this->convertEncoding = null;
}
$this->encoding = $encodingUpper;
return $this;
}
/**
* Returns the length of the given string
*
* @param string $str
* @return int|false
*/
public function strlen($str)
{
return strlen($str);
}
/**
* Returns the portion of string specified by the start and length parameters
*
* @param string $str
* @param int $offset
* @param int|null $length
* @return string|false
*/
public function substr($str, $offset = 0, $length = null)
{
return substr($str, $offset, $length);
}
/**
* Find the position of the first occurrence of a substring in a string
*
* @param string $haystack
* @param string $needle
* @param int $offset
* @return int|false
*/
public function strpos($haystack, $needle, $offset = 0)
{
return strpos($haystack, $needle, $offset);
}
}
laminas-stdlib/src/StringWrapper/AbstractStringWrapper.php 0000644 00000020704 15240152645 0020060 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\StringWrapper;
use Laminas\Stdlib\Exception;
use Laminas\Stdlib\StringUtils;
use function floor;
use function in_array;
use function sprintf;
use function str_pad;
use function str_repeat;
use function strtoupper;
use function wordwrap;
use const STR_PAD_BOTH;
use const STR_PAD_LEFT;
use const STR_PAD_RIGHT;
abstract class AbstractStringWrapper implements StringWrapperInterface
{
/**
* The character encoding working on
*
* @var string|null
*/
protected $encoding = 'UTF-8';
/**
* An optionally character encoding to convert to
*
* @var string|null
*/
protected $convertEncoding;
/**
* Check if the given character encoding is supported by this wrapper
* and the character encoding to convert to is also supported.
*
* @param string $encoding
* @param string|null $convertEncoding
* @return bool
*/
public static function isSupported($encoding, $convertEncoding = null)
{
$supportedEncodings = static::getSupportedEncodings();
if (! in_array(strtoupper($encoding), $supportedEncodings)) {
return false;
}
if ($convertEncoding !== null && ! in_array(strtoupper($convertEncoding), $supportedEncodings)) {
return false;
}
return true;
}
/**
* Set character encoding working with and convert to
*
* @param string $encoding The character encoding to work with
* @param string|null $convertEncoding The character encoding to convert to
* @return StringWrapperInterface
*/
public function setEncoding($encoding, $convertEncoding = null)
{
$supportedEncodings = static::getSupportedEncodings();
$encodingUpper = strtoupper($encoding);
if (! in_array($encodingUpper, $supportedEncodings)) {
throw new Exception\InvalidArgumentException(
'Wrapper doesn\'t support character encoding "' . $encoding . '"'
);
}
if ($convertEncoding !== null) {
$convertEncodingUpper = strtoupper($convertEncoding);
if (! in_array($convertEncodingUpper, $supportedEncodings)) {
throw new Exception\InvalidArgumentException(
'Wrapper doesn\'t support character encoding "' . $convertEncoding . '"'
);
}
$this->convertEncoding = $convertEncodingUpper;
} else {
$this->convertEncoding = null;
}
$this->encoding = $encodingUpper;
return $this;
}
/**
* Get the defined character encoding to work with
*
* @return null|string
* @throws Exception\LogicException If no encoding was defined.
*/
public function getEncoding()
{
return $this->encoding;
}
/**
* Get the defined character encoding to convert to
*
* @return string|null
*/
public function getConvertEncoding()
{
return $this->convertEncoding;
}
/**
* Convert a string from defined character encoding to the defined convert encoding
*
* @param string $str
* @param bool $reverse
* @return string|false
*/
public function convert($str, $reverse = false)
{
$encoding = $this->getEncoding();
$convertEncoding = $this->getConvertEncoding();
if ($convertEncoding === null) {
throw new Exception\LogicException(
'No convert encoding defined'
);
}
if ($encoding === $convertEncoding) {
return $str;
}
$from = $reverse ? $convertEncoding : $encoding;
$to = $reverse ? $encoding : $convertEncoding;
throw new Exception\RuntimeException(sprintf(
'Converting from "%s" to "%s" isn\'t supported by this string wrapper',
$from ?? '',
$to ?? ''
));
}
/**
* Wraps a string to a given number of characters
*
* @param string $string
* @param int $width
* @param string $break
* @param bool $cut
* @return string|false
*/
public function wordWrap($string, $width = 75, $break = "\n", $cut = false)
{
$string = (string) $string;
if ($string === '') {
return '';
}
$break = (string) $break;
if ($break === '') {
throw new Exception\InvalidArgumentException('Break string cannot be empty');
}
$width = (int) $width;
if ($width === 0 && $cut) {
throw new Exception\InvalidArgumentException('Cannot force cut when width is zero');
}
if (null === $this->getEncoding() || StringUtils::isSingleByteEncoding($this->getEncoding())) {
return wordwrap($string, $width, $break, $cut);
}
$stringWidth = $this->strlen($string);
$breakWidth = $this->strlen($break);
$result = '';
$lastStart = $lastSpace = 0;
for ($current = 0; $current < $stringWidth; $current++) {
$char = $this->substr($string, $current, 1);
$possibleBreak = $char;
if ($breakWidth !== 1) {
$possibleBreak = $this->substr($string, $current, $breakWidth);
}
if ($possibleBreak === $break) {
$result .= $this->substr($string, $lastStart, $current - $lastStart + $breakWidth);
$current += $breakWidth - 1;
$lastStart = $lastSpace = $current + 1;
continue;
}
if ($char === ' ') {
if ($current - $lastStart >= $width) {
$result .= $this->substr($string, $lastStart, $current - $lastStart) . $break;
$lastStart = $current + 1;
}
$lastSpace = $current;
continue;
}
if ($current - $lastStart >= $width && $cut && $lastStart >= $lastSpace) {
$result .= $this->substr($string, $lastStart, $current - $lastStart) . $break;
$lastStart = $lastSpace = $current;
continue;
}
if ($current - $lastStart >= $width && $lastStart < $lastSpace) {
$result .= $this->substr($string, $lastStart, $lastSpace - $lastStart) . $break;
$lastStart = $lastSpace += 1;
continue;
}
}
if ($lastStart !== $current) {
$result .= $this->substr($string, $lastStart, $current - $lastStart);
}
return $result;
}
/**
* Pad a string to a certain length with another string
*
* @param string $input
* @param int $padLength
* @param string $padString
* @param int $padType
* @return string
*/
public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT)
{
if (null === $this->getEncoding() || StringUtils::isSingleByteEncoding($this->getEncoding())) {
return str_pad($input, $padLength, $padString, $padType);
}
$lengthOfPadding = $padLength - $this->strlen($input);
if ($lengthOfPadding <= 0) {
return $input;
}
$padStringLength = $this->strlen($padString);
if ($padStringLength === 0) {
return $input;
}
$repeatCount = (int) floor($lengthOfPadding / $padStringLength);
if ($padType === STR_PAD_BOTH) {
$repeatCountLeft = $repeatCountRight = ($repeatCount - $repeatCount % 2) / 2;
$lastStringLength = $lengthOfPadding - 2 * $repeatCountLeft * $padStringLength;
$lastStringLeftLength = $lastStringRightLength = (int) floor($lastStringLength / 2);
$lastStringRightLength += $lastStringLength % 2;
$lastStringLeft = $this->substr($padString, 0, $lastStringLeftLength);
$lastStringRight = $this->substr($padString, 0, $lastStringRightLength);
return str_repeat($padString, $repeatCountLeft) . $lastStringLeft
. $input
. str_repeat($padString, $repeatCountRight) . $lastStringRight;
}
$lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength);
if ($padType === STR_PAD_LEFT) {
return str_repeat($padString, $repeatCount) . $lastString . $input;
}
return $input . str_repeat($padString, $repeatCount) . $lastString;
}
}
laminas-stdlib/src/StringWrapper/MbString.php 0000644 00000006357 15240152645 0015322 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\StringWrapper;
use Laminas\Stdlib\Exception;
use function array_map;
use function array_search;
use function extension_loaded;
use function mb_convert_encoding;
use function mb_list_encodings;
use function mb_strlen;
use function mb_strpos;
use function mb_substr;
class MbString extends AbstractStringWrapper
{
/**
* List of supported character sets (upper case)
*
* @link http://php.net/manual/mbstring.supported-encodings.php
*
* @var null|string[]
*/
protected static $encodings;
/**
* Get a list of supported character encodings
*
* @return string[]
*/
public static function getSupportedEncodings()
{
if (static::$encodings === null) {
static::$encodings = array_map('strtoupper', mb_list_encodings());
// FIXME: Converting € (UTF-8) to ISO-8859-16 gives a wrong result
$indexIso885916 = array_search('ISO-8859-16', static::$encodings, true);
if ($indexIso885916 !== false) {
unset(static::$encodings[$indexIso885916]);
}
}
return static::$encodings;
}
/**
* Constructor
*
* @throws Exception\ExtensionNotLoadedException
*/
public function __construct()
{
if (! extension_loaded('mbstring')) {
throw new Exception\ExtensionNotLoadedException(
'PHP extension "mbstring" is required for this wrapper'
);
}
}
/**
* Returns the length of the given string
*
* @param string $str
* @return int|false
*/
public function strlen($str)
{
return mb_strlen($str, $this->getEncoding());
}
/**
* Returns the portion of string specified by the start and length parameters
*
* @param string $str
* @param int $offset
* @param int|null $length
* @return string|false
*/
public function substr($str, $offset = 0, $length = null)
{
return mb_substr($str, $offset, $length, $this->getEncoding());
}
/**
* Find the position of the first occurrence of a substring in a string
*
* @param string $haystack
* @param string $needle
* @param int $offset
* @return int|false
*/
public function strpos($haystack, $needle, $offset = 0)
{
return mb_strpos($haystack, $needle, $offset, $this->getEncoding());
}
/**
* Convert a string from defined encoding to the defined convert encoding
*
* @param string $str
* @param bool $reverse
* @return string|false
*/
public function convert($str, $reverse = false)
{
$encoding = $this->getEncoding();
$convertEncoding = $this->getConvertEncoding();
if ($convertEncoding === null) {
throw new Exception\LogicException(
'No convert encoding defined'
);
}
if ($encoding === $convertEncoding) {
return $str;
}
$fromEncoding = $reverse ? $convertEncoding : $encoding;
$toEncoding = $reverse ? $encoding : $convertEncoding;
return mb_convert_encoding($str, $toEncoding ?? '', $fromEncoding ?? '');
}
}
laminas-stdlib/src/StringWrapper/StringWrapperInterface.php 0000644 00000005423 15240152645 0020216 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib\StringWrapper;
use const STR_PAD_RIGHT;
interface StringWrapperInterface
{
/**
* Check if the given character encoding is supported by this wrapper
* and the character encoding to convert to is also supported.
*
* @param string $encoding
* @param string|null $convertEncoding
*/
public static function isSupported($encoding, $convertEncoding = null);
/**
* Get a list of supported character encodings
*
* @return string[]
*/
public static function getSupportedEncodings();
/**
* Set character encoding working with and convert to
*
* @param string $encoding The character encoding to work with
* @param string|null $convertEncoding The character encoding to convert to
* @return StringWrapperInterface
*/
public function setEncoding($encoding, $convertEncoding = null);
/**
* Get the defined character encoding to work with (upper case)
*
* @return string|null
*/
public function getEncoding();
/**
* Get the defined character encoding to convert to (upper case)
*
* @return string|null
*/
public function getConvertEncoding();
/**
* Returns the length of the given string
*
* @param string $str
* @return int|false
*/
public function strlen($str);
/**
* Returns the portion of string specified by the start and length parameters
*
* @param string $str
* @param int $offset
* @param int|null $length
* @return string|false
*/
public function substr($str, $offset = 0, $length = null);
/**
* Find the position of the first occurrence of a substring in a string
*
* @param string $haystack
* @param string $needle
* @param int $offset
* @return int|false
*/
public function strpos($haystack, $needle, $offset = 0);
/**
* Convert a string from defined encoding to the defined convert encoding
*
* @param string $str
* @param bool $reverse
* @return string|false
*/
public function convert($str, $reverse = false);
/**
* Wraps a string to a given number of characters
*
* @param string $str
* @param int $width
* @param string $break
* @param bool $cut
* @return string
*/
public function wordWrap($str, $width = 75, $break = "\n", $cut = false);
/**
* Pad a string to a certain length with another string
*
* @param string $input
* @param int $padLength
* @param string $padString
* @param int $padType
* @return string
*/
public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT);
}
laminas-stdlib/src/PriorityQueue.php 0000644 00000024014 15240152645 0013602 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
use Countable;
use IteratorAggregate;
use ReturnTypeWillChange;
use Serializable;
use UnexpectedValueException;
use function array_map;
use function count;
use function is_array;
use function serialize;
use function sprintf;
use function unserialize;
/**
* Re-usable, serializable priority queue implementation
*
* SplPriorityQueue acts as a heap; on iteration, each item is removed from the
* queue. If you wish to re-use such a queue, you need to clone it first. This
* makes for some interesting issues if you wish to delete items from the queue,
* or, as already stated, iterate over it multiple times.
*
* This class aggregates items for the queue itself, but also composes an
* "inner" iterator in the form of an SplPriorityQueue object for performing
* the actual iteration.
*
* @template TValue
* @template TPriority of int
* @implements IteratorAggregate<array-key, TValue>
*/
class PriorityQueue implements Countable, IteratorAggregate, Serializable
{
public const EXTR_DATA = 0x00000001;
public const EXTR_PRIORITY = 0x00000002;
public const EXTR_BOTH = 0x00000003;
/**
* Inner queue class to use for iteration
*
* @var class-string<\SplPriorityQueue>
*/
protected $queueClass = SplPriorityQueue::class;
/**
* Actual items aggregated in the priority queue. Each item is an array
* with keys "data" and "priority".
*
* @var list<array{data: TValue, priority: TPriority}>
*/
protected $items = [];
/**
* Inner queue object
*
* @var \SplPriorityQueue<TPriority, TValue>|null
*/
protected $queue;
/**
* Insert an item into the queue
*
* Priority defaults to 1 (low priority) if none provided.
*
* @param TValue $data
* @param TPriority $priority
* @return $this
*/
public function insert($data, $priority = 1)
{
/** @psalm-var TPriority $priority */
$priority = (int) $priority;
$this->items[] = [
'data' => $data,
'priority' => $priority,
];
$this->getQueue()->insert($data, $priority);
return $this;
}
/**
* Remove an item from the queue
*
* This is different than {@link extract()}; its purpose is to dequeue an
* item.
*
* This operation is potentially expensive, as it requires
* re-initialization and re-population of the inner queue.
*
* Note: this removes the first item matching the provided item found. If
* the same item has been added multiple times, it will not remove other
* instances.
*
* @return bool False if the item was not found, true otherwise.
*/
public function remove(mixed $datum)
{
$found = false;
$key = null;
foreach ($this->items as $key => $item) {
if ($item['data'] === $datum) {
$found = true;
break;
}
}
if ($found && $key !== null) {
unset($this->items[$key]);
$this->queue = null;
if (! $this->isEmpty()) {
$queue = $this->getQueue();
foreach ($this->items as $item) {
$queue->insert($item['data'], $item['priority']);
}
}
return true;
}
return false;
}
/**
* Is the queue empty?
*
* @return bool
*/
public function isEmpty()
{
return 0 === $this->count();
}
/**
* How many items are in the queue?
*
* @return int
*/
#[ReturnTypeWillChange]
public function count()
{
return count($this->items);
}
/**
* Peek at the top node in the queue, based on priority.
*
* @return TValue
*/
public function top()
{
$queue = clone $this->getQueue();
return $queue->top();
}
/**
* Extract a node from the inner queue and sift up
*
* @return TValue
*/
public function extract()
{
$value = $this->getQueue()->extract();
$keyToRemove = null;
$highestPriority = null;
foreach ($this->items as $key => $item) {
if ($item['data'] !== $value) {
continue;
}
if (null === $highestPriority) {
$highestPriority = $item['priority'];
$keyToRemove = $key;
continue;
}
if ($highestPriority >= $item['priority']) {
continue;
}
$highestPriority = $item['priority'];
$keyToRemove = $key;
}
if ($keyToRemove !== null) {
unset($this->items[$keyToRemove]);
}
return $value;
}
/**
* Retrieve the inner iterator
*
* SplPriorityQueue acts as a heap, which typically implies that as items
* are iterated, they are also removed. This does not work for situations
* where the queue may be iterated multiple times. As such, this class
* aggregates the values, and also injects an SplPriorityQueue. This method
* retrieves the inner queue object, and clones it for purposes of
* iteration.
*
* @return \SplPriorityQueue<TPriority, TValue>
*/
#[ReturnTypeWillChange]
public function getIterator()
{
$queue = $this->getQueue();
return clone $queue;
}
/**
* Serialize the data structure
*
* @return string
*/
public function serialize()
{
return serialize($this->__serialize());
}
/**
* Magic method used for serializing of an instance.
*
* @return list<array{data: TValue, priority: TPriority}>
*/
public function __serialize()
{
return $this->items;
}
/**
* Unserialize a string into a PriorityQueue object
*
* Serialization format is compatible with {@link SplPriorityQueue}
*
* @param string $data
* @return void
*/
public function unserialize($data)
{
$toUnserialize = unserialize($data);
if (! is_array($toUnserialize)) {
throw new UnexpectedValueException(sprintf(
'Cannot deserialize %s instance; corrupt serialization data',
self::class
));
}
/** @psalm-var list<array{data: TValue, priority: TPriority}> $toUnserialize */
$this->__unserialize($toUnserialize);
}
/**
* Magic method used to rebuild an instance.
*
* @param list<array{data: TValue, priority: TPriority}> $data Data array.
* @return void
*/
public function __unserialize($data)
{
foreach ($data as $item) {
$this->insert($item['data'], $item['priority']);
}
}
/**
* Serialize to an array
* By default, returns only the item data, and in the order registered (not
* sorted). You may provide one of the EXTR_* flags as an argument, allowing
* the ability to return priorities or both data and priority.
*
* @param int $flag
* @return array<array-key, mixed>
* @psalm-return ($flag is self::EXTR_BOTH
* ? list<array{data: TValue, priority: TPriority}>
* : $flag is self::EXTR_PRIORITY
* ? list<TPriority>
* : list<TValue>
* )
*/
public function toArray($flag = self::EXTR_DATA)
{
return match ($flag) {
self::EXTR_BOTH => $this->items,
self::EXTR_PRIORITY => array_map(static fn($item): int => $item['priority'], $this->items),
default => array_map(static fn($item): mixed => $item['data'], $this->items),
};
}
/**
* Specify the internal queue class
*
* Please see {@link getIterator()} for details on the necessity of an
* internal queue class. The class provided should extend SplPriorityQueue.
*
* @param class-string<\SplPriorityQueue> $class
* @return $this
*/
public function setInternalQueueClass($class)
{
/** @psalm-suppress RedundantCastGivenDocblockType */
$this->queueClass = (string) $class;
return $this;
}
/**
* Does the queue contain the given datum?
*
* @param TValue $datum
* @return bool
*/
public function contains($datum)
{
foreach ($this->items as $item) {
if ($item['data'] === $datum) {
return true;
}
}
return false;
}
/**
* Does the queue have an item with the given priority?
*
* @param TPriority $priority
* @return bool
*/
public function hasPriority($priority)
{
foreach ($this->items as $item) {
if ($item['priority'] === $priority) {
return true;
}
}
return false;
}
/**
* Get the inner priority queue instance
*
* @throws Exception\DomainException
* @return \SplPriorityQueue<TPriority, TValue>
* @psalm-assert !null $this->queue
*/
protected function getQueue()
{
if (null === $this->queue) {
/** @psalm-suppress UnsafeInstantiation */
$queue = new $this->queueClass();
/** @psalm-var \SplPriorityQueue<TPriority, TValue> $queue */
$this->queue = $queue;
/** @psalm-suppress DocblockTypeContradiction, MixedArgument */
if (! $this->queue instanceof \SplPriorityQueue) {
throw new Exception\DomainException(sprintf(
'PriorityQueue expects an internal queue of type SplPriorityQueue; received "%s"',
$this->queue::class
));
}
}
return $this->queue;
}
/**
* Add support for deep cloning
*
* @return void
*/
public function __clone()
{
if (null !== $this->queue) {
$this->queue = clone $this->queue;
}
}
}
laminas-stdlib/src/ConsoleHelper.php 0000644 00000011106 15240152645 0013514 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
use function function_exists;
use function fwrite;
use function getenv;
use function posix_isatty;
use function preg_replace;
use function sprintf;
use function str_replace;
use const DIRECTORY_SEPARATOR;
use const PHP_EOL;
use const STDERR;
use const STDOUT;
/**
* Utilities for console tooling.
*
* Provides the following facilities:
*
* - Colorize strings using markup (e.g., `<info>message</info>`,
* `<error>message</error>`)
* - Write output to a specified stream, optionally with colorization.
* - Write a line of output to a specified stream, optionally with
* colorization, using the system EOL sequence..
* - Write an error message to STDERR.
*
* Colorization will only occur when expected sequences are discovered, and
* then, only if the console terminal allows it.
*
* Essentially, provides the bare minimum to allow you to provide messages to
* the current console.
*/
class ConsoleHelper
{
public const COLOR_GREEN = "\033[32m";
public const COLOR_RED = "\033[31m";
public const COLOR_RESET = "\033[0m";
public const HIGHLIGHT_INFO = 'info';
public const HIGHLIGHT_ERROR = 'error';
/** @psalm-var array<ConsoleHelper::HIGHLIGHT_*, ConsoleHelper::COLOR_GREEN|ConsoleHelper::COLOR_RED> */
private array $highlightMap = [
self::HIGHLIGHT_INFO => self::COLOR_GREEN,
self::HIGHLIGHT_ERROR => self::COLOR_RED,
];
/** @var string Exists only for testing. */
private string $eol = PHP_EOL;
/** @var resource Exists only for testing. */
private $stderr = STDERR;
private bool $supportsColor;
/**
* @param resource $resource
*/
public function __construct($resource = STDOUT)
{
$this->supportsColor = $this->detectColorCapabilities($resource);
}
/**
* Colorize a string for use with the terminal.
*
* Takes strings formatted as `<key>string</key>` and formats them per the
* $highlightMap; if color support is disabled, simply removes the formatting
* tags.
*
* @param string $string
* @return string
*/
public function colorize($string)
{
$reset = $this->supportsColor ? self::COLOR_RESET : '';
foreach ($this->highlightMap as $key => $color) {
$pattern = sprintf('#<%s>(.*?)</%s>#s', $key, $key);
$color = $this->supportsColor ? $color : '';
$string = preg_replace($pattern, $color . '$1' . $reset, $string);
}
return $string;
}
/**
* @param string $string
* @param bool $colorize Whether or not to colorize the string
* @param resource $resource Defaults to STDOUT
* @return void
*/
public function write($string, $colorize = true, $resource = STDOUT)
{
if ($colorize) {
$string = $this->colorize($string);
}
$string = $this->formatNewlines($string);
fwrite($resource, $string);
}
/**
* @param string $string
* @param bool $colorize Whether or not to colorize the line
* @param resource $resource Defaults to STDOUT
* @return void
*/
public function writeLine($string, $colorize = true, $resource = STDOUT)
{
$this->write($string . $this->eol, $colorize, $resource);
}
/**
* Emit an error message.
*
* Wraps the message in `<error></error>`, and passes it to `writeLine()`,
* using STDERR as the resource; emits an additional empty line when done,
* also to STDERR.
*
* @param string $message
* @return void
*/
public function writeErrorMessage($message)
{
$this->writeLine(sprintf('<error>%s</error>', $message), true, $this->stderr);
$this->writeLine('', false, $this->stderr);
}
/**
* @param resource $resource
* @return bool
*/
private function detectColorCapabilities($resource = STDOUT)
{
if ('\\' === DIRECTORY_SEPARATOR) {
// Windows
return false !== getenv('ANSICON')
|| 'ON' === getenv('ConEmuANSI')
|| 'xterm' === getenv('TERM');
}
return function_exists('posix_isatty') && posix_isatty($resource);
}
/**
* Ensure newlines are appropriate for the current terminal.
*
* @param string $string
* @return string
*/
private function formatNewlines($string)
{
$string = str_replace($this->eol, "\0PHP_EOL\0", $string);
$string = preg_replace("/(\r\n|\n|\r)/", $this->eol, $string);
return str_replace("\0PHP_EOL\0", $this->eol, $string);
}
}
laminas-stdlib/src/ParametersInterface.php 0000644 00000003062 15240152646 0014701 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
use ArrayAccess;
use Countable;
use Serializable;
use Traversable;
/*
* Basically, an ArrayObject. You could simply define something like:
* class QueryParams extends ArrayObject implements Parameters {}
* and have 90% of the functionality
*/
interface ParametersInterface extends ArrayAccess, Countable, Serializable, Traversable
{
/**
* Constructor
*
* @param array $values
*/
public function __construct(?array $values = null);
/**
* From array
*
* Allow deserialization from standard array
*
* @param array $values
* @return mixed
*/
public function fromArray(array $values);
/**
* From string
*
* Allow deserialization from raw body; e.g., for PUT requests
*
* @param string $string
* @return mixed
*/
public function fromString($string);
/**
* To array
*
* Allow serialization back to standard array
*
* @return mixed
*/
public function toArray();
/**
* To string
*
* Allow serialization to query format; e.g., for PUT or POST requests
*
* @return mixed
*/
public function toString();
/**
* Get
*
* @param string $name
* @param mixed|null $default
* @return mixed
*/
public function get($name, $default = null);
/**
* Set
*
* @param string $name
* @param mixed $value
* @return ParametersInterface
*/
public function set($name, $value);
}
laminas-stdlib/src/ArrayUtils.php 0000644 00000022262 15240152646 0013057 0 ustar 00 <?php // phpcs:disable WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix
declare(strict_types=1);
namespace Laminas\Stdlib;
use Iterator;
use Laminas\Stdlib\ArrayUtils\MergeRemoveKey;
use Laminas\Stdlib\ArrayUtils\MergeReplaceKeyInterface;
use Traversable;
use function array_filter;
use function array_key_exists;
use function array_keys;
use function array_values;
use function in_array;
use function is_array;
use function is_callable;
use function is_float;
use function is_int;
use function is_object;
use function is_scalar;
use function is_string;
use function iterator_to_array;
use function method_exists;
use function sprintf;
/**
* Utility class for testing and manipulation of PHP arrays.
*
* Declared abstract, as we have no need for instantiation.
*/
abstract class ArrayUtils
{
/**
* Compatibility Flag for ArrayUtils::filter
*/
public const ARRAY_FILTER_USE_BOTH = 1;
/**
* Compatibility Flag for ArrayUtils::filter
*/
public const ARRAY_FILTER_USE_KEY = 2;
/**
* Test whether an array contains one or more string keys
*
* @param bool $allowEmpty Should an empty array() return true
* @return bool
*/
public static function hasStringKeys(mixed $value, $allowEmpty = false)
{
if (! is_array($value)) {
return false;
}
if (! $value) {
return $allowEmpty;
}
return [] !== array_filter(array_keys($value), 'is_string');
}
/**
* Test whether an array contains one or more integer keys
*
* @param bool $allowEmpty Should an empty array() return true
* @return bool
*/
public static function hasIntegerKeys(mixed $value, $allowEmpty = false)
{
if (! is_array($value)) {
return false;
}
if (! $value) {
return $allowEmpty;
}
return [] !== array_filter(array_keys($value), 'is_int');
}
/**
* Test whether an array contains one or more numeric keys.
*
* A numeric key can be one of the following:
* - an integer 1,
* - a string with a number '20'
* - a string with negative number: '-1000'
* - a float: 2.2120, -78.150999
* - a string with float: '4000.99999', '-10.10'
*
* @param bool $allowEmpty Should an empty array() return true
* @return bool
*/
public static function hasNumericKeys(mixed $value, $allowEmpty = false)
{
if (! is_array($value)) {
return false;
}
if (! $value) {
return $allowEmpty;
}
return [] !== array_filter(array_keys($value), 'is_numeric');
}
/**
* Test whether an array is a list
*
* A list is a collection of values assigned to continuous integer keys
* starting at 0 and ending at count() - 1.
*
* For example:
* <code>
* $list = array('a', 'b', 'c', 'd');
* $list = array(
* 0 => 'foo',
* 1 => 'bar',
* 2 => array('foo' => 'baz'),
* );
* </code>
*
* @param bool $allowEmpty Is an empty list a valid list?
* @return bool
*/
public static function isList(mixed $value, $allowEmpty = false)
{
if (! is_array($value)) {
return false;
}
if (! $value) {
return $allowEmpty;
}
return array_values($value) === $value;
}
/**
* Test whether an array is a hash table.
*
* An array is a hash table if:
*
* 1. Contains one or more non-integer keys, or
* 2. Integer keys are non-continuous or misaligned (not starting with 0)
*
* For example:
* <code>
* $hash = array(
* 'foo' => 15,
* 'bar' => false,
* );
* $hash = array(
* 1995 => 'Birth of PHP',
* 2009 => 'PHP 5.3.0',
* 2012 => 'PHP 5.4.0',
* );
* $hash = array(
* 'formElement,
* 'options' => array( 'debug' => true ),
* );
* </code>
*
* @param bool $allowEmpty Is an empty array() a valid hash table?
* @return bool
*/
public static function isHashTable(mixed $value, $allowEmpty = false)
{
if (! is_array($value)) {
return false;
}
if (! $value) {
return $allowEmpty;
}
return array_values($value) !== $value;
}
/**
* Checks if a value exists in an array.
*
* Due to "foo" == 0 === TRUE with in_array when strict = false, an option
* has been added to prevent this. When $strict = 0/false, the most secure
* non-strict check is implemented. if $strict = -1, the default in_array
* non-strict behaviour is used.
*
* @param array $haystack
* @param int|bool $strict
* @return bool
*/
public static function inArray(mixed $needle, array $haystack, $strict = false)
{
if (! $strict) {
if (is_int($needle) || is_float($needle)) {
$needle = (string) $needle;
}
if (is_string($needle)) {
foreach ($haystack as &$h) {
if (is_int($h) || is_float($h)) {
$h = (string) $h;
}
}
}
}
return in_array($needle, $haystack, (bool) $strict);
}
/**
* Converts an iterator to an array. The $recursive flag, on by default,
* hints whether or not you want to do so recursively.
*
* @template TKey
* @template TValue
* @param iterable<TKey, TValue> $iterator The array or Traversable object to convert
* @param bool $recursive Recursively check all nested structures
* @throws Exception\InvalidArgumentException If $iterator is not an array or a Traversable object.
* @return array<TKey, TValue>
*/
public static function iteratorToArray($iterator, $recursive = true)
{
/** @psalm-suppress DocblockTypeContradiction */
if (! is_array($iterator) && ! $iterator instanceof Traversable) {
throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable object');
}
if (! $recursive) {
if (is_array($iterator)) {
return $iterator;
}
return iterator_to_array($iterator);
}
if (
is_object($iterator)
&& ! $iterator instanceof Iterator
&& method_exists($iterator, 'toArray')
) {
/** @psalm-var array<TKey, TValue> $array */
$array = $iterator->toArray();
return $array;
}
$array = [];
foreach ($iterator as $key => $value) {
if (is_scalar($value)) {
$array[$key] = $value;
continue;
}
if ($value instanceof Traversable) {
$array[$key] = static::iteratorToArray($value, $recursive);
continue;
}
if (is_array($value)) {
$array[$key] = static::iteratorToArray($value, $recursive);
continue;
}
$array[$key] = $value;
}
/** @psalm-var array<TKey, TValue> $array */
return $array;
}
/**
* Merge two arrays together.
*
* If an integer key exists in both arrays and preserveNumericKeys is false, the value
* from the second array will be appended to the first array. If both values are arrays, they
* are merged together, else the value of the second array overwrites the one of the first array.
*
* @param array $a
* @param array $b
* @param bool $preserveNumericKeys
* @return array
*/
public static function merge(array $a, array $b, $preserveNumericKeys = false)
{
foreach ($b as $key => $value) {
if ($value instanceof MergeReplaceKeyInterface) {
$a[$key] = $value->getData();
} elseif (isset($a[$key]) || array_key_exists($key, $a)) {
if ($value instanceof MergeRemoveKey) {
unset($a[$key]);
} elseif (! $preserveNumericKeys && is_int($key)) {
$a[] = $value;
} elseif (is_array($value) && is_array($a[$key])) {
$a[$key] = static::merge($a[$key], $value, $preserveNumericKeys);
} else {
$a[$key] = $value;
}
} else {
if (! $value instanceof MergeRemoveKey) {
$a[$key] = $value;
}
}
}
return $a;
}
/**
* @deprecated Since 3.2.0; use the native array_filter methods
*
* @param callable $callback
* @param null|int $flag
* @return array
* @throws Exception\InvalidArgumentException
*/
public static function filter(array $data, $callback, $flag = null)
{
if (! is_callable($callback)) {
throw new Exception\InvalidArgumentException(sprintf(
'Second parameter of %s must be callable',
__METHOD__
));
}
return array_filter($data, $callback, $flag ?? 0);
}
}
laminas-stdlib/src/StringUtils.php 0000644 00000013474 15240152646 0013254 0 ustar 00 <?php // phpcs:disable WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix
declare(strict_types=1);
namespace Laminas\Stdlib;
use Laminas\Stdlib\StringWrapper\Iconv;
use Laminas\Stdlib\StringWrapper\Intl;
use Laminas\Stdlib\StringWrapper\MbString;
use Laminas\Stdlib\StringWrapper\Native;
use Laminas\Stdlib\StringWrapper\StringWrapperInterface;
use function array_search;
use function defined;
use function extension_loaded;
use function in_array;
use function is_string;
use function preg_match;
use function strtoupper;
/**
* Utility class for handling strings of different character encodings
* using available PHP extensions.
*
* Declared abstract, as we have no need for instantiation.
*/
abstract class StringUtils
{
/**
* Ordered list of registered string wrapper instances
*
* @var list<class-string<StringWrapperInterface>>|null
*/
protected static $wrapperRegistry;
/**
* A list of known single-byte character encodings (upper-case)
*
* @var string[]
*/
protected static $singleByteEncodings = [
'ASCII',
'7BIT',
'8BIT',
'ISO-8859-1',
'ISO-8859-2',
'ISO-8859-3',
'ISO-8859-4',
'ISO-8859-5',
'ISO-8859-6',
'ISO-8859-7',
'ISO-8859-8',
'ISO-8859-9',
'ISO-8859-10',
'ISO-8859-11',
'ISO-8859-13',
'ISO-8859-14',
'ISO-8859-15',
'ISO-8859-16',
'CP-1251',
'CP-1252',
// TODO
];
/**
* Is PCRE compiled with Unicode support?
*
* @var bool
**/
protected static $hasPcreUnicodeSupport;
/**
* Get registered wrapper classes
*
* @return string[]
* @psalm-return list<class-string<StringWrapperInterface>>
*/
public static function getRegisteredWrappers()
{
if (static::$wrapperRegistry === null) {
static::$wrapperRegistry = [];
if (extension_loaded('intl')) {
static::$wrapperRegistry[] = Intl::class;
}
if (extension_loaded('mbstring')) {
static::$wrapperRegistry[] = MbString::class;
}
if (extension_loaded('iconv')) {
static::$wrapperRegistry[] = Iconv::class;
}
static::$wrapperRegistry[] = Native::class;
}
return static::$wrapperRegistry;
}
/**
* Register a string wrapper class
*
* @param class-string<StringWrapperInterface> $wrapper
* @return void
*/
public static function registerWrapper($wrapper)
{
$wrapper = (string) $wrapper;
// using getRegisteredWrappers() here to ensure that the list is initialized
if (! in_array($wrapper, static::getRegisteredWrappers(), true)) {
static::$wrapperRegistry[] = $wrapper;
}
}
/**
* Unregister a string wrapper class
*
* @param class-string<StringWrapperInterface> $wrapper
* @return void
*/
public static function unregisterWrapper($wrapper)
{
// using getRegisteredWrappers() here to ensure that the list is initialized
$index = array_search((string) $wrapper, static::getRegisteredWrappers(), true);
if ($index !== false) {
unset(static::$wrapperRegistry[$index]);
}
}
/**
* Reset all registered wrappers so the default wrappers will be used
*
* @return void
*/
public static function resetRegisteredWrappers()
{
static::$wrapperRegistry = null;
}
/**
* Get the first string wrapper supporting the given character encoding
* and supports to convert into the given convert encoding.
*
* @param string $encoding Character encoding to support
* @param string|null $convertEncoding OPTIONAL character encoding to convert in
* @return StringWrapperInterface
* @throws Exception\RuntimeException If no wrapper supports given character encodings.
*/
public static function getWrapper($encoding = 'UTF-8', $convertEncoding = null)
{
foreach (static::getRegisteredWrappers() as $wrapperClass) {
if ($wrapperClass::isSupported($encoding, $convertEncoding)) {
$wrapper = new $wrapperClass($encoding, $convertEncoding);
$wrapper->setEncoding($encoding, $convertEncoding);
return $wrapper;
}
}
throw new Exception\RuntimeException(
'No wrapper found supporting "' . $encoding . '"'
. ($convertEncoding !== null ? ' and "' . $convertEncoding . '"' : '')
);
}
/**
* Get a list of all known single-byte character encodings
*
* @return string[]
*/
public static function getSingleByteEncodings()
{
return static::$singleByteEncodings;
}
/**
* Check if a given encoding is a known single-byte character encoding
*
* @param string $encoding
* @return bool
*/
public static function isSingleByteEncoding($encoding)
{
return in_array(strtoupper($encoding), static::$singleByteEncodings);
}
/**
* Check if a given string is valid UTF-8 encoded
*
* @param string $str
* @return bool
*/
public static function isValidUtf8($str)
{
return is_string($str) && ($str === '' || preg_match('/^./su', $str) === 1);
}
/**
* Is PCRE compiled with Unicode support?
*
* @return bool
*/
public static function hasPcreUnicodeSupport()
{
if (static::$hasPcreUnicodeSupport === null) {
ErrorHandler::start();
static::$hasPcreUnicodeSupport = defined('PREG_BAD_UTF8_OFFSET_ERROR') && preg_match('/\pL/u', 'a') === 1;
ErrorHandler::stop();
}
return static::$hasPcreUnicodeSupport;
}
}
laminas-stdlib/src/Parameters.php 0000644 00000004333 15240152646 0013062 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Stdlib;
use ArrayObject as PhpArrayObject;
use ReturnTypeWillChange;
use function http_build_query;
use function parse_str;
class Parameters extends PhpArrayObject implements ParametersInterface
{
/**
* Constructor
*
* Enforces that we have an array, and enforces parameter access to array
* elements.
*
* @param array $values
*/
public function __construct(?array $values = null)
{
if (null === $values) {
$values = [];
}
parent::__construct($values, ArrayObject::ARRAY_AS_PROPS);
}
/**
* Populate from native PHP array
*
* @param array $values
* @return void
*/
public function fromArray(array $values)
{
$this->exchangeArray($values);
}
/**
* Populate from query string
*
* @param string $string
* @return void
*/
public function fromString($string)
{
$array = [];
parse_str($string, $array);
$this->fromArray($array);
}
/**
* Serialize to native PHP array
*
* @return array
*/
public function toArray()
{
return $this->getArrayCopy();
}
/**
* Serialize to query string
*
* @return string
*/
public function toString()
{
return http_build_query($this->toArray());
}
/**
* Retrieve by key
*
* Returns null if the key does not exist.
*
* @param string $name
* @return mixed
*/
#[ReturnTypeWillChange]
public function offsetGet($name)
{
if ($this->offsetExists($name)) {
return parent::offsetGet($name);
}
return null;
}
/**
* @param string $name
* @param mixed $default optional default value
* @return mixed
*/
public function get($name, $default = null)
{
if ($this->offsetExists($name)) {
return parent::offsetGet($name);
}
return $default;
}
/**
* @param string $name
* @param mixed $value
* @return Parameters
*/
public function set($name, $value)
{
$this[$name] = $value;
return $this;
}
}
laminas-stdlib/README.md 0000644 00000007131 15240152646 0010735 0 ustar 00 # laminas-stdlib
[](https://github.com/laminas/laminas-stdlib/actions/workflows/continuous-integration.yml)
[](https://shepherd.dev/github/laminas/laminas-stdlib)
> ## 🇷🇺 Русским гражданам
>
> Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм.
>
> У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую.
>
> Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!"
>
> ## 🇺🇸 To Citizens of Russia
>
> We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism.
>
> One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences.
>
> You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!"
`Laminas\Stdlib` is a set of components that implements general purpose utility
class for different scopes like:
- array utilities functions;
- general messaging systems;
- string wrappers;
- etc.
---
- File issues at https://github.com/laminas/laminas-stdlib/issues
- Documentation is at https://docs.laminas.dev/laminas-stdlib/
## Benchmarks
We provide scripts for benchmarking laminas-stdlib using the
[PHPBench](https://github.com/phpbench/phpbench) framework; these can be
found in the `benchmark/` directory.
To execute the benchmarks you can run the following command:
```bash
$ vendor/bin/phpbench run --report=aggregate
```
laminas-stdlib/composer.json 0000644 00000003442 15240152646 0012201 0 ustar 00 {
"name": "laminas/laminas-stdlib",
"description": "SPL extensions, array utilities, error handlers, and more",
"license": "BSD-3-Clause",
"keywords": [
"laminas",
"stdlib"
],
"homepage": "https://laminas.dev",
"support": {
"docs": "https://docs.laminas.dev/laminas-stdlib/",
"issues": "https://github.com/laminas/laminas-stdlib/issues",
"source": "https://github.com/laminas/laminas-stdlib",
"rss": "https://github.com/laminas/laminas-stdlib/releases.atom",
"chat": "https://laminas.dev/chat",
"forum": "https://discourse.laminas.dev"
},
"config": {
"sort-packages": true,
"platform": {
"php": "8.0.99"
},
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"extra": {
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"require-dev": {
"laminas/laminas-coding-standard": "^2.4.0",
"phpbench/phpbench": "^1.2.6",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.28"
},
"autoload": {
"psr-4": {
"Laminas\\Stdlib\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"LaminasTest\\Stdlib\\": "test/",
"LaminasBench\\Stdlib\\": "benchmark/"
}
},
"scripts": {
"check": [
"@cs-check",
"@test"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"static-analysis": "psalm --shepherd --stats",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
},
"conflict": {
"zendframework/zend-stdlib": "*"
}
}
laminas-stdlib/COPYRIGHT.md 0000644 00000000133 15240152646 0011343 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/)
laminas-stdlib/LICENSE.md 0000644 00000002732 15240152646 0011064 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of Laminas Foundation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
laminas-crypt/src/Key/Derivation/Scrypt.php 0000644 00000026623 15240152646 0014765 0 ustar 00 <?php
namespace Laminas\Crypt\Key\Derivation;
use function extension_loaded;
use function hex2bin;
use function mb_substr;
use function pack;
use function scrypt;
use function unpack;
use const PHP_INT_MAX;
use const PHP_INT_SIZE;
/**
* Scrypt key derivation function
*
* @see http://www.tarsnap.com/scrypt.html
* @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01
*/
// phpcs:ignore WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix
abstract class Scrypt
{
/**
* Execute the scrypt algorithm
*
* @param string $password
* @param string $salt
* @param int $n CPU cost
* @param int $r Memory cost
* @param int $p parallelization cost
* @param int $length size of the output key
* @return string
*/
public static function calc($password, $salt, $n, $r, $p, $length)
{
if ($n === 0 || ($n & ($n - 1)) !== 0) {
throw new Exception\InvalidArgumentException("N must be > 0 and a power of 2");
}
if ($n > PHP_INT_MAX / 128 / $r) {
throw new Exception\InvalidArgumentException("Parameter n is too large");
}
if ($r > PHP_INT_MAX / 128 / $p) {
throw new Exception\InvalidArgumentException("Parameter r is too large");
}
if (extension_loaded('Scrypt')) {
if ($length < 16) {
throw new Exception\InvalidArgumentException("Key length is too low, must be greater or equal to 16");
}
return hex2bin(scrypt($password, $salt, $n, $r, $p, $length));
}
$b = Pbkdf2::calc('sha256', $password, $salt, 1, $p * 128 * $r);
$s = '';
for ($i = 0; $i < $p; $i++) {
$s .= self::scryptROMix(mb_substr($b, $i * 128 * $r, 128 * $r, '8bit'), $n, $r);
}
return Pbkdf2::calc('sha256', $password, $s, 1, $length);
}
/**
* scryptROMix
*
* @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-4
*
* @param string $b
* @param int $n
* @param int $r
* @return string
*/
protected static function scryptROMix($b, $n, $r)
{
$x = $b;
$v = [];
for ($i = 0; $i < $n; $i++) {
$v[$i] = $x;
$x = self::scryptBlockMix($x, $r);
}
for ($i = 0; $i < $n; $i++) {
$j = self::integerify($x) % $n;
$t = $x ^ $v[$j];
$x = self::scryptBlockMix($t, $r);
}
return $x;
}
/**
* scryptBlockMix
*
* @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-3
*
* @param string $b
* @param int $r
* @return string
*/
protected static function scryptBlockMix($b, $r)
{
$x = mb_substr($b, -64, null, '8bit');
$even = '';
$odd = '';
$len = 2 * $r;
for ($i = 0; $i < $len; $i++) {
if (PHP_INT_SIZE === 4) {
$x = self::salsa208Core32($x ^ mb_substr($b, 64 * $i, 64, '8bit'));
} else {
$x = self::salsa208Core64($x ^ mb_substr($b, 64 * $i, 64, '8bit'));
}
if ($i % 2 === 0) {
$even .= $x;
} else {
$odd .= $x;
}
}
return $even . $odd;
}
/**
* Salsa 20/8 core (32 bit version)
*
* @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-2
* @see http://cr.yp.to/salsa20.html
*
* @param string $b
* @return string
*/
protected static function salsa208Core32($b)
{
$b32 = [];
for ($i = 0; $i < 16; $i++) {
[, $b32[$i]] = unpack("V", mb_substr($b, $i * 4, 4, '8bit'));
}
$x = $b32;
for ($i = 0; $i < 8; $i += 2) {
$a = $x[ 0] + $x[12];
$x[ 4] ^= ($a << 7) | ($a >> 25) & 0x7f;
$a = $x[ 4] + $x[ 0];
$x[ 8] ^= ($a << 9) | ($a >> 23) & 0x1ff;
$a = $x[ 8] + $x[ 4];
$x[12] ^= ($a << 13) | ($a >> 19) & 0x1fff;
$a = $x[12] + $x[ 8];
$x[ 0] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
$a = $x[ 5] + $x[ 1];
$x[ 9] ^= ($a << 7) | ($a >> 25) & 0x7f;
$a = $x[ 9] + $x[ 5];
$x[13] ^= ($a << 9) | ($a >> 23) & 0x1ff;
$a = $x[13] + $x[ 9];
$x[ 1] ^= ($a << 13) | ($a >> 19) & 0x1fff;
$a = $x[ 1] + $x[13];
$x[ 5] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
$a = $x[10] + $x[ 6];
$x[14] ^= ($a << 7) | ($a >> 25) & 0x7f;
$a = $x[14] + $x[10];
$x[ 2] ^= ($a << 9) | ($a >> 23) & 0x1ff;
$a = $x[ 2] + $x[14];
$x[ 6] ^= ($a << 13) | ($a >> 19) & 0x1fff;
$a = $x[ 6] + $x[ 2];
$x[10] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
$a = $x[15] + $x[11];
$x[ 3] ^= ($a << 7) | ($a >> 25) & 0x7f;
$a = $x[ 3] + $x[15];
$x[ 7] ^= ($a << 9) | ($a >> 23) & 0x1ff;
$a = $x[ 7] + $x[ 3];
$x[11] ^= ($a << 13) | ($a >> 19) & 0x1fff;
$a = $x[11] + $x[ 7];
$x[15] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
$a = $x[ 0] + $x[ 3];
$x[ 1] ^= ($a << 7) | ($a >> 25) & 0x7f;
$a = $x[ 1] + $x[ 0];
$x[ 2] ^= ($a << 9) | ($a >> 23) & 0x1ff;
$a = $x[ 2] + $x[ 1];
$x[ 3] ^= ($a << 13) | ($a >> 19) & 0x1fff;
$a = $x[ 3] + $x[ 2];
$x[ 0] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
$a = $x[ 5] + $x[ 4];
$x[ 6] ^= ($a << 7) | ($a >> 25) & 0x7f;
$a = $x[ 6] + $x[ 5];
$x[ 7] ^= ($a << 9) | ($a >> 23) & 0x1ff;
$a = $x[ 7] + $x[ 6];
$x[ 4] ^= ($a << 13) | ($a >> 19) & 0x1fff;
$a = $x[ 4] + $x[ 7];
$x[ 5] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
$a = $x[10] + $x[ 9];
$x[11] ^= ($a << 7) | ($a >> 25) & 0x7f;
$a = $x[11] + $x[10];
$x[ 8] ^= ($a << 9) | ($a >> 23) & 0x1ff;
$a = $x[ 8] + $x[11];
$x[ 9] ^= ($a << 13) | ($a >> 19) & 0x1fff;
$a = $x[ 9] + $x[ 8];
$x[10] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
$a = $x[15] + $x[14];
$x[12] ^= ($a << 7) | ($a >> 25) & 0x7f;
$a = $x[12] + $x[15];
$x[13] ^= ($a << 9) | ($a >> 23) & 0x1ff;
$a = $x[13] + $x[12];
$x[14] ^= ($a << 13) | ($a >> 19) & 0x1fff;
$a = $x[14] + $x[13];
$x[15] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
}
for ($i = 0; $i < 16; $i++) {
$b32[$i] += $x[$i];
}
$result = '';
for ($i = 0; $i < 16; $i++) {
$result .= pack("V", $b32[$i]);
}
return $result;
}
/**
* Salsa 20/8 core (64 bit version)
*
* @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-2
* @see http://cr.yp.to/salsa20.html
*
* @param string $b
* @return string
*/
protected static function salsa208Core64($b)
{
$b32 = [];
for ($i = 0; $i < 16; $i++) {
[, $b32[$i]] = unpack("V", mb_substr($b, $i * 4, 4, '8bit'));
}
$x = $b32;
for ($i = 0; $i < 8; $i += 2) {
$a = ($x[ 0] + $x[12]) & 0xffffffff;
$x[ 4] ^= ($a << 7) | ($a >> 25);
$a = ($x[ 4] + $x[ 0]) & 0xffffffff;
$x[ 8] ^= ($a << 9) | ($a >> 23);
$a = ($x[ 8] + $x[ 4]) & 0xffffffff;
$x[12] ^= ($a << 13) | ($a >> 19);
$a = ($x[12] + $x[ 8]) & 0xffffffff;
$x[ 0] ^= ($a << 18) | ($a >> 14);
$a = ($x[ 5] + $x[ 1]) & 0xffffffff;
$x[ 9] ^= ($a << 7) | ($a >> 25);
$a = ($x[ 9] + $x[ 5]) & 0xffffffff;
$x[13] ^= ($a << 9) | ($a >> 23);
$a = ($x[13] + $x[ 9]) & 0xffffffff;
$x[ 1] ^= ($a << 13) | ($a >> 19);
$a = ($x[ 1] + $x[13]) & 0xffffffff;
$x[ 5] ^= ($a << 18) | ($a >> 14);
$a = ($x[10] + $x[ 6]) & 0xffffffff;
$x[14] ^= ($a << 7) | ($a >> 25);
$a = ($x[14] + $x[10]) & 0xffffffff;
$x[ 2] ^= ($a << 9) | ($a >> 23);
$a = ($x[ 2] + $x[14]) & 0xffffffff;
$x[ 6] ^= ($a << 13) | ($a >> 19);
$a = ($x[ 6] + $x[ 2]) & 0xffffffff;
$x[10] ^= ($a << 18) | ($a >> 14);
$a = ($x[15] + $x[11]) & 0xffffffff;
$x[ 3] ^= ($a << 7) | ($a >> 25);
$a = ($x[ 3] + $x[15]) & 0xffffffff;
$x[ 7] ^= ($a << 9) | ($a >> 23);
$a = ($x[ 7] + $x[ 3]) & 0xffffffff;
$x[11] ^= ($a << 13) | ($a >> 19);
$a = ($x[11] + $x[ 7]) & 0xffffffff;
$x[15] ^= ($a << 18) | ($a >> 14);
$a = ($x[ 0] + $x[ 3]) & 0xffffffff;
$x[ 1] ^= ($a << 7) | ($a >> 25);
$a = ($x[ 1] + $x[ 0]) & 0xffffffff;
$x[ 2] ^= ($a << 9) | ($a >> 23);
$a = ($x[ 2] + $x[ 1]) & 0xffffffff;
$x[ 3] ^= ($a << 13) | ($a >> 19);
$a = ($x[ 3] + $x[ 2]) & 0xffffffff;
$x[ 0] ^= ($a << 18) | ($a >> 14);
$a = ($x[ 5] + $x[ 4]) & 0xffffffff;
$x[ 6] ^= ($a << 7) | ($a >> 25);
$a = ($x[ 6] + $x[ 5]) & 0xffffffff;
$x[ 7] ^= ($a << 9) | ($a >> 23);
$a = ($x[ 7] + $x[ 6]) & 0xffffffff;
$x[ 4] ^= ($a << 13) | ($a >> 19);
$a = ($x[ 4] + $x[ 7]) & 0xffffffff;
$x[ 5] ^= ($a << 18) | ($a >> 14);
$a = ($x[10] + $x[ 9]) & 0xffffffff;
$x[11] ^= ($a << 7) | ($a >> 25);
$a = ($x[11] + $x[10]) & 0xffffffff;
$x[ 8] ^= ($a << 9) | ($a >> 23);
$a = ($x[ 8] + $x[11]) & 0xffffffff;
$x[ 9] ^= ($a << 13) | ($a >> 19);
$a = ($x[ 9] + $x[ 8]) & 0xffffffff;
$x[10] ^= ($a << 18) | ($a >> 14);
$a = ($x[15] + $x[14]) & 0xffffffff;
$x[12] ^= ($a << 7) | ($a >> 25);
$a = ($x[12] + $x[15]) & 0xffffffff;
$x[13] ^= ($a << 9) | ($a >> 23);
$a = ($x[13] + $x[12]) & 0xffffffff;
$x[14] ^= ($a << 13) | ($a >> 19);
$a = ($x[14] + $x[13]) & 0xffffffff;
$x[15] ^= ($a << 18) | ($a >> 14);
}
for ($i = 0; $i < 16; $i++) {
$b32[$i] = ($b32[$i] + $x[$i]) & 0xffffffff;
}
$result = '';
for ($i = 0; $i < 16; $i++) {
$result .= pack("V", $b32[$i]);
}
return $result;
}
/**
* Integerify
*
* Integerify (B[0] ... B[2 * r - 1]) is defined as the result
* of interpreting B[2 * r - 1] as a little-endian integer.
* Each block B is a string of 64 bytes.
*
* @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-4
*
* @param string $b
* @return int
*/
protected static function integerify($b)
{
$v = 'v';
if (PHP_INT_SIZE === 8) {
$v = 'V';
}
[, $n] = unpack($v, mb_substr($b, -64, null, '8bit'));
return $n;
}
}
laminas-crypt/src/Key/Derivation/Exception/InvalidArgumentException.php 0000644 00000000356 15240152646 0022402 0 ustar 00 <?php
namespace Laminas\Crypt\Key\Derivation\Exception;
use Laminas\Crypt\Exception;
/**
* Invalid argument exception
*/
class InvalidArgumentException extends Exception\InvalidArgumentException implements
ExceptionInterface
{
}
laminas-crypt/src/Key/Derivation/Exception/ExceptionInterface.php 0000644 00000000253 15240152646 0021205 0 ustar 00 <?php
namespace Laminas\Crypt\Key\Derivation\Exception;
use Laminas\Crypt\Exception\ExceptionInterface as Exception;
interface ExceptionInterface extends Exception
{
}
laminas-crypt/src/Key/Derivation/Exception/RuntimeException.php 0000644 00000000336 15240152646 0020732 0 ustar 00 <?php
namespace Laminas\Crypt\Key\Derivation\Exception;
use Laminas\Crypt\Exception;
/**
* Runtime argument exception
*/
class RuntimeException extends Exception\RuntimeException implements
ExceptionInterface
{
}
laminas-crypt/src/Key/Derivation/Pbkdf2.php 0000644 00000002620 15240152646 0014600 0 ustar 00 <?php
namespace Laminas\Crypt\Key\Derivation;
use Laminas\Crypt\Hmac;
use function ceil;
use function hash_hmac;
use function mb_substr;
use function pack;
/**
* PKCS #5 v2.0 standard RFC 2898
*/
class Pbkdf2
{
/**
* Generate the new key
*
* @param string $hash The hash algorithm to be used by HMAC
* @param string $password The source password/key
* @param string $salt
* @param int $iterations The number of iterations
* @param int $length The output size
* @throws Exception\InvalidArgumentException
* @return string
*/
public static function calc($hash, $password, $salt, $iterations, $length)
{
if (! Hmac::isSupported($hash)) {
throw new Exception\InvalidArgumentException("The hash algorithm $hash is not supported by " . self::class);
}
$num = ceil($length / Hmac::getOutputSize($hash, Hmac::OUTPUT_BINARY));
$result = '';
for ($block = 1; $block <= $num; $block++) {
$hmac = hash_hmac($hash, $salt . pack('N', $block), $password, Hmac::OUTPUT_BINARY);
$mix = $hmac;
for ($i = 1; $i < $iterations; $i++) {
$hmac = hash_hmac($hash, $hmac, $password, Hmac::OUTPUT_BINARY);
$mix ^= $hmac;
}
$result .= $mix;
}
return mb_substr($result, 0, $length, '8bit');
}
}
laminas-crypt/src/Key/Derivation/SaltedS2k.php 0000644 00000007447 15240152646 0015300 0 ustar 00 <?php
namespace Laminas\Crypt\Key\Derivation;
use function array_keys;
use function ceil;
use function hash;
use function in_array;
use function intval;
use function mb_strlen;
use function range;
use function str_pad;
use function str_repeat;
use function strlen;
use function substr;
use const MHASH_ADLER32;
use const MHASH_CRC32;
use const MHASH_CRC32B;
use const MHASH_GOST;
use const MHASH_HAVAL128;
use const MHASH_HAVAL160;
use const MHASH_HAVAL192;
use const MHASH_HAVAL224;
use const MHASH_HAVAL256;
use const MHASH_MD2;
use const MHASH_MD4;
use const MHASH_MD5;
use const MHASH_RIPEMD128;
use const MHASH_RIPEMD256;
use const MHASH_RIPEMD320;
use const MHASH_SHA1;
use const MHASH_SHA224;
use const MHASH_SHA256;
use const MHASH_SHA384;
use const MHASH_SHA512;
use const MHASH_SNEFRU256;
use const MHASH_TIGER;
use const MHASH_TIGER128;
use const MHASH_TIGER160;
use const MHASH_WHIRLPOOL;
use const STR_PAD_RIGHT;
/**
* Salted S2K key generation (OpenPGP document, RFC 2440)
*/
class SaltedS2k
{
/** @var array<string, string> */
protected static $supportedMhashAlgos = [
'adler32' => MHASH_ADLER32,
'md2' => MHASH_MD2,
'md4' => MHASH_MD4,
'md5' => MHASH_MD5,
'sha1' => MHASH_SHA1,
'sha224' => MHASH_SHA224,
'sha256' => MHASH_SHA256,
'sha384' => MHASH_SHA384,
'sha512' => MHASH_SHA512,
'ripemd128' => MHASH_RIPEMD128,
'ripemd256' => MHASH_RIPEMD256,
'ripemd320' => MHASH_RIPEMD320,
'haval128,3' => MHASH_HAVAL128, // @deprecated use haval128 instead
'haval128' => MHASH_HAVAL128,
'haval160,3' => MHASH_HAVAL160, // @deprecated use haval160 instead
'haval160' => MHASH_HAVAL160,
'haval192,3' => MHASH_HAVAL192, // @deprecated use haval192 instead
'haval192' => MHASH_HAVAL192,
'haval224,3' => MHASH_HAVAL224, // @deprecated use haval224 instead
'haval224' => MHASH_HAVAL224,
'haval256,3' => MHASH_HAVAL256, // @deprecated use haval256 instead
'haval256' => MHASH_HAVAL256,
'tiger' => MHASH_TIGER,
'tiger128,3' => MHASH_TIGER128, // @deprecated use tiger128 instead
'tiger128' => MHASH_TIGER128,
'tiger160,3' => MHASH_TIGER160, // @deprecated use tiger160 instead
'tiger160' => MHASH_TIGER160,
'whirpool' => MHASH_WHIRLPOOL,
'snefru256' => MHASH_SNEFRU256,
'gost' => MHASH_GOST,
'crc32' => MHASH_CRC32,
'crc32b' => MHASH_CRC32B,
];
/**
* Generate the new key
*
* @param string $hash The hash algorithm to be used by HMAC
* @param string $password The source password/key
* @param int $bytes The output size in bytes
* @param string $salt The salt of the algorithm
* @throws Exception\InvalidArgumentException
* @return string
*/
public static function calc($hash, $password, $salt, $bytes)
{
if (! in_array($hash, array_keys(static::$supportedMhashAlgos))) {
throw new Exception\InvalidArgumentException("The hash algorithm $hash is not supported by " . self::class);
}
if (mb_strlen($salt, '8bit') < 8) {
throw new Exception\InvalidArgumentException('The salt size must be at least of 8 bytes');
}
$result = '';
foreach (range(0, ceil($bytes / strlen(hash($hash, '', true))) - 1) as $i) {
$result .= hash(
$hash,
str_repeat("\0", $i) . str_pad(
substr($salt, 0, 8),
8,
"\0",
STR_PAD_RIGHT
) . $password,
true
);
}
return substr($result, 0, intval($bytes));
}
}
laminas-crypt/src/Hash.php 0000644 00000004102 15240152646 0011514 0 ustar 00 <?php
namespace Laminas\Crypt;
use function hash;
use function hash_algos;
use function in_array;
use function mb_strlen;
use function strtolower;
class Hash
{
public const OUTPUT_STRING = false;
public const OUTPUT_BINARY = true;
/**
* Last algorithm supported
*
* @var string|null
*/
protected static $lastAlgorithmSupported;
/**
* @param string $hash
* @param string $data
* @param bool $output
* @throws Exception\InvalidArgumentException
* @return string
*/
public static function compute($hash, $data, $output = self::OUTPUT_STRING)
{
if (! $hash || ($hash !== static::$lastAlgorithmSupported && ! static::isSupported($hash))) {
throw new Exception\InvalidArgumentException(
'Hash algorithm provided is not supported on this PHP installation'
);
}
return hash($hash, $data, $output);
}
/**
* Get the output size according to the hash algorithm and the output format
*
* @param string $hash
* @param bool $output
* @return int
*/
public static function getOutputSize($hash, $output = self::OUTPUT_STRING)
{
return mb_strlen(static::compute($hash, 'data', $output), '8bit');
}
/**
* Get the supported algorithm
*
* @return array
*/
public static function getSupportedAlgorithms()
{
return hash_algos();
}
/**
* Is the hash algorithm supported?
*
* @param string $algorithm
* @return bool
*/
public static function isSupported($algorithm)
{
if ($algorithm === static::$lastAlgorithmSupported) {
return true;
}
if (in_array(strtolower($algorithm), hash_algos(), true)) {
static::$lastAlgorithmSupported = $algorithm;
return true;
}
return false;
}
/**
* Clear the cache of last algorithm supported
*/
public static function clearLastAlgorithmCache()
{
static::$lastAlgorithmSupported = null;
}
}
laminas-crypt/src/Exception/InvalidArgumentException.php 0000644 00000000264 15240152646 0017544 0 ustar 00 <?php
namespace Laminas\Crypt\Exception;
/**
* Invalid argument exception
*/
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
laminas-crypt/src/Exception/ExceptionInterface.php 0000644 00000000114 15240152646 0016345 0 ustar 00 <?php
namespace Laminas\Crypt\Exception;
interface ExceptionInterface
{
}
laminas-crypt/src/Exception/RuntimeException.php 0000644 00000000244 15240152646 0016074 0 ustar 00 <?php
namespace Laminas\Crypt\Exception;
/**
* Runtime argument exception
*/
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
laminas-crypt/src/Exception/NotFoundException.php 0000644 00000000401 15240152646 0016200 0 ustar 00 <?php
namespace Laminas\Crypt\Exception;
use DomainException;
use Psr\Container\NotFoundExceptionInterface as PsrNotFoundException;
/**
* Runtime argument exception
*/
class NotFoundException extends DomainException implements PsrNotFoundException
{
}
laminas-crypt/src/Symmetric/Exception/InvalidArgumentException.php 0000644 00000000351 15240152646 0021515 0 ustar 00 <?php
namespace Laminas\Crypt\Symmetric\Exception;
use Laminas\Crypt\Exception;
/**
* Invalid argument exception
*/
class InvalidArgumentException extends Exception\InvalidArgumentException implements
ExceptionInterface
{
}
laminas-crypt/src/Symmetric/Exception/ExceptionInterface.php 0000644 00000000246 15240152646 0020327 0 ustar 00 <?php
namespace Laminas\Crypt\Symmetric\Exception;
use Laminas\Crypt\Exception\ExceptionInterface as Exception;
interface ExceptionInterface extends Exception
{
}
laminas-crypt/src/Symmetric/Exception/RuntimeException.php 0000644 00000000331 15240152646 0020045 0 ustar 00 <?php
namespace Laminas\Crypt\Symmetric\Exception;
use Laminas\Crypt\Exception;
/**
* Runtime argument exception
*/
class RuntimeException extends Exception\RuntimeException implements
ExceptionInterface
{
}
laminas-crypt/src/Symmetric/Exception/NotFoundException.php 0000644 00000000320 15240152646 0020154 0 ustar 00 <?php
namespace Laminas\Crypt\Symmetric\Exception;
use Laminas\Crypt\Exception;
/**
* Not found exception
*/
class NotFoundException extends Exception\NotFoundException implements ExceptionInterface
{
}
laminas-crypt/src/Symmetric/SymmetricInterface.php 0000644 00000002446 15240152646 0016413 0 ustar 00 <?php
namespace Laminas\Crypt\Symmetric;
interface SymmetricInterface
{
/**
* @param string $data
*/
public function encrypt($data);
/**
* @param string $data
*/
public function decrypt($data);
/**
* @param string $key
*/
public function setKey($key);
/**
* @return string
*/
public function getKey();
/**
* @return integer
*/
public function getKeySize();
/**
* @return string
*/
public function getAlgorithm();
/**
* @param string $algo
*/
public function setAlgorithm($algo);
/**
* @return array
*/
public function getSupportedAlgorithms();
/**
* @param string $salt
*/
public function setSalt($salt);
/**
* @return string
*/
public function getSalt();
/**
* @return integer
*/
public function getSaltSize();
/**
* @return integer
*/
public function getBlockSize();
/**
* @param string $mode
*/
public function setMode($mode);
/**
* @return string
*/
public function getMode();
/**
* @return array
*/
public function getSupportedModes();
/**
* @param array $options
*/
public function setOptions($options);
}
laminas-crypt/src/Symmetric/Openssl.php 0000644 00000052224 15240152646 0014240 0 ustar 00 <?php
namespace Laminas\Crypt\Symmetric;
use Laminas\Stdlib\ArrayUtils;
use Psr\Container\ContainerInterface;
use Traversable;
use function array_push;
use function class_exists;
use function extension_loaded;
use function get_class;
use function gettype;
use function in_array;
use function is_array;
use function is_int;
use function is_object;
use function is_string;
use function is_subclass_of;
use function mb_strlen;
use function mb_substr;
use function openssl_cipher_iv_length;
use function openssl_decrypt;
use function openssl_encrypt;
use function openssl_error_string;
use function openssl_get_cipher_methods;
use function sprintf;
use function strtolower;
use const OPENSSL_RAW_DATA;
use const OPENSSL_ZERO_PADDING;
use const PHP_VERSION_ID;
/**
* Symmetric encryption using the OpenSSL extension
*
* NOTE: DO NOT USE only this class to encrypt data.
* This class doesn't provide authentication and integrity check over the data.
* PLEASE USE Laminas\Crypt\BlockCipher instead!
*/
class Openssl implements SymmetricInterface
{
public const DEFAULT_PADDING = 'pkcs7';
/**
* Key
*
* @var string
*/
protected $key;
/**
* IV
*
* @var string
*/
protected $iv;
/**
* Encryption algorithm
*
* @var string
*/
protected $algo = 'aes';
/**
* Encryption mode
*
* @var string
*/
protected $mode = 'cbc';
/**
* Padding
*
* @var Padding\PaddingInterface
*/
protected $padding;
/**
* Padding plugins
*
* @var ContainerInterface
*/
protected static $paddingPlugins;
/**
* The encryption algorithms to support
*
* @var array
*/
protected $encryptionAlgos = [
'aes' => 'aes-256',
'blowfish' => 'bf',
'des' => 'des',
'camellia' => 'camellia-256',
'cast5' => 'cast5',
'seed' => 'seed',
];
/**
* Encryption modes to support
*
* @var array
*/
protected $encryptionModes = [
'cbc',
'cfb',
'ofb',
'ecb',
'ctr',
];
/**
* Block sizes (in bytes) for each supported algorithm
*
* @var array
*/
protected $blockSizes = [
'aes' => 16,
'blowfish' => 8,
'des' => 8,
'camellia' => 16,
'cast5' => 8,
'seed' => 16,
];
/**
* Key sizes (in bytes) for each supported algorithm
*
* @var array
*/
protected $keySizes = [
'aes' => 32,
'blowfish' => 56,
'des' => 8,
'camellia' => 32,
'cast5' => 16,
'seed' => 16,
];
/**
* The OpenSSL supported encryption algorithms
*
* @var array
*/
protected $opensslAlgos = [];
/**
* Additional authentication data (only for PHP 7.1+)
*
* @var string
*/
protected $aad = '';
/**
* Store the tag for authentication (only for PHP 7.1+)
*
* @var string
*/
protected $tag;
/**
* Tag size for authenticated encryption modes (only for PHP 7.1+)
*
* @var int
*/
protected $tagSize = 16;
/**
* Constructor
*
* @param array|Traversable $options
* @throws Exception\RuntimeException
* @throws Exception\InvalidArgumentException
*/
public function __construct($options = [])
{
if (! extension_loaded('openssl')) {
throw new Exception\RuntimeException(sprintf(
'You cannot use %s without the OpenSSL extension',
self::class
));
}
// Add the GCM and CCM modes for PHP 7.1+
if (PHP_VERSION_ID >= 70100) {
array_push($this->encryptionModes, 'gcm', 'ccm');
}
$this->setOptions($options);
$this->setDefaultOptions($options);
}
/**
* Set default options
*
* @param array $options
* @return void
* @throws Exception\RuntimeException
* @throws Exception\InvalidArgumentException
*/
public function setOptions($options)
{
if (empty($options)) {
return;
}
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (! is_array($options)) {
throw new Exception\InvalidArgumentException(
'The options parameter must be an array or a Traversable'
);
}
// The algorithm case is not included in the switch because must be
// set before the others
if (isset($options['algo'])) {
$this->setAlgorithm($options['algo']);
} elseif (isset($options['algorithm'])) {
$this->setAlgorithm($options['algorithm']);
}
foreach ($options as $key => $value) {
switch (strtolower($key)) {
case 'mode':
$this->setMode($value);
break;
case 'key':
$this->setKey($value);
break;
case 'iv':
case 'salt':
$this->setSalt($value);
break;
case 'padding':
$plugins = static::getPaddingPluginManager();
$padding = $plugins->get($value);
$this->padding = $padding;
break;
case 'aad':
$this->setAad($value);
break;
case 'tag_size':
$this->setTagSize($value);
break;
}
}
}
/**
* Set default options
*
* @param array $options
* @return void
*/
protected function setDefaultOptions($options = [])
{
if (isset($options['padding'])) {
return;
}
$plugins = static::getPaddingPluginManager();
$padding = $plugins->get(self::DEFAULT_PADDING);
$this->padding = $padding;
}
/**
* Returns the padding plugin manager.
*
* Creates one if none is present.
*
* @return ContainerInterface
*/
public static function getPaddingPluginManager()
{
if (static::$paddingPlugins === null) {
self::setPaddingPluginManager(new PaddingPluginManager());
}
return static::$paddingPlugins;
}
/**
* Set the padding plugin manager
*
* @param string|ContainerInterface $plugins
* @throws Exception\InvalidArgumentException
* @return void
*/
public static function setPaddingPluginManager($plugins)
{
if (is_string($plugins)) {
if (! class_exists($plugins) || ! is_subclass_of($plugins, ContainerInterface::class)) {
throw new Exception\InvalidArgumentException(sprintf(
'Unable to locate padding plugin manager via class "%s"; '
. 'class does not exist or does not implement ContainerInterface',
$plugins
));
}
$plugins = new $plugins();
}
if (! $plugins instanceof ContainerInterface) {
throw new Exception\InvalidArgumentException(sprintf(
'Padding plugins must implements %s; received "%s"',
ContainerInterface::class,
is_object($plugins) ? get_class($plugins) : gettype($plugins)
));
}
static::$paddingPlugins = $plugins;
}
/**
* Get the key size for the selected cipher
*
* @return int
*/
public function getKeySize()
{
return $this->keySizes[$this->algo];
}
/**
* Set the encryption key
* If the key is longer than maximum supported, it will be truncated by getKey().
*
* @param string $key
* @return Openssl Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setKey($key)
{
$keyLen = mb_strlen($key, '8bit');
if (! $keyLen) {
throw new Exception\InvalidArgumentException('The key cannot be empty');
}
if ($keyLen < $this->getKeySize()) {
throw new Exception\InvalidArgumentException(sprintf(
'The size of the key must be at least of %d bytes',
$this->getKeySize()
));
}
$this->key = $key;
return $this;
}
/**
* Get the encryption key
*
* @return string
*/
public function getKey()
{
if (empty($this->key)) {
return;
}
return mb_substr($this->key, 0, $this->getKeySize(), '8bit');
}
/**
* Set the encryption algorithm (cipher)
*
* @param string $algo
* @return Openssl Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setAlgorithm($algo)
{
if (! in_array($algo, $this->getSupportedAlgorithms())) {
throw new Exception\InvalidArgumentException(sprintf(
'The algorithm %s is not supported by %s',
$algo,
self::class
));
}
$this->algo = $algo;
return $this;
}
/**
* Get the encryption algorithm
*
* @return string
*/
public function getAlgorithm()
{
return $this->algo;
}
/**
* Set the padding object
*
* @return Openssl Provides a fluent interface
*/
public function setPadding(Padding\PaddingInterface $padding)
{
$this->padding = $padding;
return $this;
}
/**
* Get the padding object
*
* @return Padding\PaddingInterface
*/
public function getPadding()
{
return $this->padding;
}
/**
* Set Additional Authentication Data
*
* @param string $aad
* @return self
* @throws Exception\InvalidArgumentException
* @throws Exception\RuntimeException
*/
public function setAad($aad)
{
if (! $this->isAuthEncAvailable()) {
throw new Exception\RuntimeException(
'You need PHP 7.1+ and OpenSSL with CCM or GCM mode to use AAD'
);
}
if (! $this->isCcmOrGcm()) {
throw new Exception\RuntimeException(
'You can set Additional Authentication Data (AAD) only for CCM or GCM mode'
);
}
if (! is_string($aad)) {
throw new Exception\InvalidArgumentException(sprintf(
'The provided $aad must be a string, %s given',
gettype($aad)
));
}
$this->aad = $aad;
return $this;
}
/**
* Get the Additional Authentication Data
*
* @return string
*/
public function getAad()
{
return $this->aad;
}
/**
* Get the authentication tag
*
* @return string
*/
public function getTag()
{
return $this->tag;
}
/**
* Set the tag size for CCM and GCM mode
*
* @param int $size
* @return self
* @throws Exception\InvalidArgumentException
* @throws Exception\RuntimeException
*/
public function setTagSize($size)
{
if (! is_int($size)) {
throw new Exception\InvalidArgumentException(sprintf(
'The provided $size must be an integer, %s given',
gettype($size)
));
}
if (! $this->isAuthEncAvailable()) {
throw new Exception\RuntimeException(
'You need PHP 7.1+ and OpenSSL with CCM or GCM mode to set the Tag Size'
);
}
if (! $this->isCcmOrGcm()) {
throw new Exception\RuntimeException(
'You can set the Tag Size only for CCM or GCM mode'
);
}
if ($this->getMode() === 'gcm' && ($size < 4 || $size > 16)) {
throw new Exception\InvalidArgumentException(
'The Tag Size must be between 4 to 16 for GCM mode'
);
}
$this->tagSize = $size;
return $this;
}
/**
* Get the tag size for CCM and GCM mode
*
* @return int
*/
public function getTagSize()
{
return $this->tagSize;
}
/**
* Encrypt
*
* @param string $data
* @throws Exception\InvalidArgumentException
* @return string
*/
public function encrypt($data)
{
// Cannot encrypt empty string
if (! is_string($data) || $data === '') {
throw new Exception\InvalidArgumentException('The data to encrypt cannot be empty');
}
if (null === $this->getKey()) {
throw new Exception\InvalidArgumentException('No key specified for the encryption');
}
if (null === $this->getSalt() && $this->getSaltSize() > 0) {
throw new Exception\InvalidArgumentException('The salt (IV) cannot be empty');
}
if (null === $this->getPadding()) {
throw new Exception\InvalidArgumentException('You must specify a padding method');
}
// padding
$data = $this->padding->pad($data, $this->getBlockSize());
$iv = $this->getSalt();
// encryption with GCM or CCM
if ($this->isCcmOrGcm()) {
$result = openssl_encrypt(
$data,
strtolower($this->encryptionAlgos[$this->algo] . '-' . $this->mode),
$this->getKey(),
OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING,
$iv,
$tag,
$this->getAad(),
$this->getTagSize()
);
$this->tag = $tag;
} else {
$result = openssl_encrypt(
$data,
strtolower($this->encryptionAlgos[$this->algo] . '-' . $this->mode),
$this->getKey(),
OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING,
$iv
);
}
if (false === $result) {
$errMsg = '';
while ($msg = openssl_error_string()) {
$errMsg .= $msg;
}
throw new Exception\RuntimeException(sprintf(
'OpenSSL error: %s',
$errMsg
));
}
if ($this->isCcmOrGcm()) {
return $tag . $iv . $result;
}
return $iv . $result;
}
/**
* Decrypt
*
* @param string $data
* @throws Exception\InvalidArgumentException
* @return string
*/
public function decrypt($data)
{
if (empty($data)) {
throw new Exception\InvalidArgumentException('The data to decrypt cannot be empty');
}
if (null === $this->getKey()) {
throw new Exception\InvalidArgumentException('No decryption key specified');
}
if (null === $this->getPadding()) {
throw new Exception\InvalidArgumentException('You must specify a padding method');
}
if ($this->isCcmOrGcm()) {
$tag = mb_substr($data, 0, $this->getTagSize(), '8bit');
$data = mb_substr($data, $this->getTagSize(), null, '8bit');
$this->tag = $tag;
}
$iv = mb_substr($data, 0, $this->getSaltSize(), '8bit');
$ciphertext = mb_substr($data, $this->getSaltSize(), null, '8bit');
$result = $this->attemptOpensslDecrypt($ciphertext, $iv, $this->tag);
if (false === $result) {
$errMsg = '';
while ($msg = openssl_error_string()) {
$errMsg .= $msg;
}
throw new Exception\RuntimeException(sprintf(
'OpenSSL error: %s',
$errMsg
));
}
// unpadding
return $this->padding->strip($result);
}
/**
* Get the salt (IV) size
*
* @return int
*/
public function getSaltSize()
{
return openssl_cipher_iv_length(
$this->encryptionAlgos[$this->algo] . '-' . $this->mode
);
}
/**
* Get the supported algorithms
*
* @return array
*/
public function getSupportedAlgorithms()
{
if (empty($this->supportedAlgos)) {
foreach ($this->encryptionAlgos as $name => $algo) {
// CBC mode is supported by all the algorithms
if (in_array($algo . '-cbc', $this->getOpensslAlgos())) {
$this->supportedAlgos[] = $name;
}
}
}
return $this->supportedAlgos;
}
/**
* Set the salt (IV)
*
* @param string $salt
* @return Openssl Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setSalt($salt)
{
if ($this->getSaltSize() <= 0) {
throw new Exception\InvalidArgumentException(sprintf(
'You cannot use a salt (IV) for %s in %s mode',
$this->algo,
$this->mode
));
}
if (empty($salt)) {
throw new Exception\InvalidArgumentException('The salt (IV) cannot be empty');
}
if (mb_strlen($salt, '8bit') < $this->getSaltSize()) {
throw new Exception\InvalidArgumentException(sprintf(
'The size of the salt (IV) must be at least %d bytes',
$this->getSaltSize()
));
}
$this->iv = $salt;
return $this;
}
/**
* Get the salt (IV) according to the size requested by the algorithm
*
* @return string
*/
public function getSalt()
{
if (empty($this->iv)) {
return;
}
if (mb_strlen($this->iv, '8bit') < $this->getSaltSize()) {
throw new Exception\RuntimeException(sprintf(
'The size of the salt (IV) must be at least %d bytes',
$this->getSaltSize()
));
}
return mb_substr($this->iv, 0, $this->getSaltSize(), '8bit');
}
/**
* Get the original salt value
*
* @return string
*/
public function getOriginalSalt()
{
return $this->iv;
}
/**
* Set the cipher mode
*
* @param string $mode
* @return Openssl Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setMode($mode)
{
if (empty($mode)) {
return $this;
}
if (! in_array($mode, $this->getSupportedModes())) {
throw new Exception\InvalidArgumentException(sprintf(
'The mode %s is not supported by %s',
$mode,
$this->algo
));
}
$this->mode = $mode;
return $this;
}
/**
* Get the cipher mode
*
* @return string
*/
public function getMode()
{
return $this->mode;
}
/**
* Return the OpenSSL supported encryption algorithms
*
* @return array
*/
protected function getOpensslAlgos()
{
if (empty($this->opensslAlgos)) {
$this->opensslAlgos = openssl_get_cipher_methods(true);
}
return $this->opensslAlgos;
}
/**
* Get all supported encryption modes for the selected algorithm
*
* @return array
*/
public function getSupportedModes()
{
$modes = [];
foreach ($this->encryptionModes as $mode) {
$algo = $this->encryptionAlgos[$this->algo] . '-' . $mode;
if (in_array($algo, $this->getOpensslAlgos())) {
$modes[] = $mode;
}
}
return $modes;
}
/**
* Get the block size
*
* @return int
*/
public function getBlockSize()
{
return $this->blockSizes[$this->algo];
}
/**
* Return true if authenticated encryption is available
*
* @return bool
*/
public function isAuthEncAvailable()
{
// Counter with CBC-MAC
$ccm = in_array('aes-256-ccm', $this->getOpensslAlgos());
// Galois/Counter Mode
$gcm = in_array('aes-256-gcm', $this->getOpensslAlgos());
return PHP_VERSION_ID >= 70100 && ($ccm || $gcm);
}
/**
* @return bool
*/
private function isCcmOrGcm()
{
return in_array(strtolower($this->mode), ['gcm', 'ccm'], true);
}
/**
* @param string $cipherText
* @param string $iv
* @param string $tag
* @return string|bool false on failure
*/
private function attemptOpensslDecrypt($cipherText, $iv, $tag)
{
if ($this->isCcmOrGcm()) {
return openssl_decrypt(
$cipherText,
strtolower($this->encryptionAlgos[$this->algo] . '-' . $this->mode),
$this->getKey(),
OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING,
$iv,
$tag,
$this->getAad()
);
}
return openssl_decrypt(
$cipherText,
strtolower($this->encryptionAlgos[$this->algo] . '-' . $this->mode),
$this->getKey(),
OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING,
$iv
);
}
}
laminas-crypt/src/Symmetric/Mcrypt.php 0000644 00000034750 15240152646 0014077 0 ustar 00 <?php
namespace Laminas\Crypt\Symmetric;
use Laminas\Stdlib\ArrayUtils;
use Psr\Container\ContainerInterface;
use Traversable;
use function array_key_exists;
use function array_keys;
use function class_exists;
use function extension_loaded;
use function get_class;
use function gettype;
use function implode;
use function in_array;
use function is_array;
use function is_object;
use function is_string;
use function is_subclass_of;
use function mb_strlen;
use function mb_substr;
use function mcrypt_decrypt;
use function mcrypt_encrypt;
use function mcrypt_get_block_size;
use function mcrypt_get_iv_size;
use function mcrypt_get_key_size;
use function mcrypt_module_get_supported_key_sizes;
use function sprintf;
use function strtolower;
use function trigger_error;
use const E_USER_DEPRECATED;
use const PHP_VERSION_ID;
/**
* Symmetric encryption using the Mcrypt extension
*
* NOTE: DO NOT USE only this class to encrypt data.
* This class doesn't provide authentication and integrity check over the data.
* PLEASE USE Laminas\Crypt\BlockCipher instead!
*/
class Mcrypt implements SymmetricInterface
{
public const DEFAULT_PADDING = 'pkcs7';
/**
* Key
*
* @var string
*/
protected $key;
/**
* IV
*
* @var string
*/
protected $iv;
/**
* Encryption algorithm
*
* @var string
*/
protected $algo = 'aes';
/**
* Encryption mode
*
* @var string
*/
protected $mode = 'cbc';
/**
* Padding
*
* @var Padding\PaddingInterface
*/
protected $padding;
/**
* Padding plugins
*
* @var ContainerInterface
*/
protected static $paddingPlugins;
/**
* Supported cipher algorithms
*
* @var array
*/
protected $supportedAlgos = [
'aes' => 'rijndael-128',
'blowfish' => 'blowfish',
'des' => 'des',
'3des' => 'tripledes',
'tripledes' => 'tripledes',
'cast-128' => 'cast-128',
'cast-256' => 'cast-256',
'rijndael-128' => 'rijndael-128',
'rijndael-192' => 'rijndael-192',
'rijndael-256' => 'rijndael-256',
'saferplus' => 'saferplus',
'serpent' => 'serpent',
'twofish' => 'twofish',
];
/**
* Supported encryption modes
*
* @var array
*/
protected $supportedModes = [
'cbc' => 'cbc',
'cfb' => 'cfb',
'ctr' => 'ctr',
'ofb' => 'ofb',
'nofb' => 'nofb',
'ncfb' => 'ncfb',
];
/**
* Constructor
*
* @param array|Traversable $options
* @throws Exception\RuntimeException
* @throws Exception\InvalidArgumentException
*/
public function __construct($options = [])
{
if (PHP_VERSION_ID >= 70100) {
trigger_error(
'The Mcrypt extension is deprecated from PHP 7.1+. '
. 'We suggest to use Laminas\Crypt\Symmetric\Openssl.',
E_USER_DEPRECATED
);
}
if (! extension_loaded('mcrypt')) {
throw new Exception\RuntimeException(sprintf(
'You cannot use %s without the Mcrypt extension',
self::class
));
}
$this->setOptions($options);
$this->setDefaultOptions($options);
}
/**
* Set default options
*
* @param array $options
* @return void
*/
public function setOptions($options)
{
if (! empty($options)) {
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
} elseif (! is_array($options)) {
throw new Exception\InvalidArgumentException(
'The options parameter must be an array or a Traversable'
);
}
foreach ($options as $key => $value) {
switch (strtolower($key)) {
case 'algo':
case 'algorithm':
$this->setAlgorithm($value);
break;
case 'mode':
$this->setMode($value);
break;
case 'key':
$this->setKey($value);
break;
case 'iv':
case 'salt':
$this->setSalt($value);
break;
case 'padding':
$plugins = static::getPaddingPluginManager();
$padding = $plugins->get($value);
$this->padding = $padding;
break;
}
}
}
}
/**
* Set default options
*
* @param array $options
* @return void
*/
protected function setDefaultOptions($options = [])
{
if (! isset($options['padding'])) {
$plugins = static::getPaddingPluginManager();
$padding = $plugins->get(self::DEFAULT_PADDING);
$this->padding = $padding;
}
}
/**
* Returns the padding plugin manager. If it doesn't exist it's created.
*
* @return ContainerInterface
*/
public static function getPaddingPluginManager()
{
if (static::$paddingPlugins === null) {
self::setPaddingPluginManager(new PaddingPluginManager());
}
return static::$paddingPlugins;
}
/**
* Set the padding plugin manager
*
* @param string|ContainerInterface $plugins
* @throws Exception\InvalidArgumentException
* @return void
*/
public static function setPaddingPluginManager($plugins)
{
if (is_string($plugins)) {
if (! class_exists($plugins) || ! is_subclass_of($plugins, ContainerInterface::class)) {
throw new Exception\InvalidArgumentException(sprintf(
'Unable to locate padding plugin manager via class "%s"; '
. 'class does not exist or does not implement ContainerInterface',
$plugins
));
}
$plugins = new $plugins();
}
if (! $plugins instanceof ContainerInterface) {
throw new Exception\InvalidArgumentException(sprintf(
'Padding plugins must implements Psr\Container\ContainerInterface; received "%s"',
is_object($plugins) ? get_class($plugins) : gettype($plugins)
));
}
static::$paddingPlugins = $plugins;
}
/**
* Get the maximum key size for the selected cipher and mode of operation
*
* @return int
*/
public function getKeySize()
{
return mcrypt_get_key_size($this->supportedAlgos[$this->algo], $this->supportedModes[$this->mode]);
}
/**
* Set the encryption key
* If the key is longer than maximum supported, it will be truncated by getKey().
*
* @param string $key
* @return Mcrypt Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setKey($key)
{
$keyLen = mb_strlen($key, '8bit');
if (! $keyLen) {
throw new Exception\InvalidArgumentException('The key cannot be empty');
}
$keySizes = mcrypt_module_get_supported_key_sizes($this->supportedAlgos[$this->algo]);
$maxKey = $this->getKeySize();
/*
* blowfish has $keySizes empty, meaning it can have arbitrary key length.
* the others are more picky.
*/
if (! empty($keySizes) && $keyLen < $maxKey) {
if (! in_array($keyLen, $keySizes)) {
throw new Exception\InvalidArgumentException(sprintf(
'The size of the key must be %s bytes or longer',
implode(', ', $keySizes)
));
}
}
$this->key = $key;
return $this;
}
/**
* Get the encryption key
*
* @return string
*/
public function getKey()
{
if (empty($this->key)) {
return;
}
return mb_substr($this->key, 0, $this->getKeySize(), '8bit');
}
/**
* Set the encryption algorithm (cipher)
*
* @param string $algo
* @return Mcrypt Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setAlgorithm($algo)
{
if (! array_key_exists($algo, $this->supportedAlgos)) {
throw new Exception\InvalidArgumentException(sprintf(
'The algorithm %s is not supported by %s',
$algo,
self::class
));
}
$this->algo = $algo;
return $this;
}
/**
* Get the encryption algorithm
*
* @return string
*/
public function getAlgorithm()
{
return $this->algo;
}
/**
* Set the padding object
*
* @return Mcrypt Provides a fluent interface
*/
public function setPadding(Padding\PaddingInterface $padding)
{
$this->padding = $padding;
return $this;
}
/**
* Get the padding object
*
* @return Padding\PaddingInterface
*/
public function getPadding()
{
return $this->padding;
}
/**
* Encrypt
*
* @param string $data
* @throws Exception\InvalidArgumentException
* @return string
*/
public function encrypt($data)
{
// Cannot encrypt empty string
if (! is_string($data) || $data === '') {
throw new Exception\InvalidArgumentException('The data to encrypt cannot be empty');
}
if (null === $this->getKey()) {
throw new Exception\InvalidArgumentException('No key specified for the encryption');
}
if (null === $this->getSalt()) {
throw new Exception\InvalidArgumentException('The salt (IV) cannot be empty');
}
if (null === $this->getPadding()) {
throw new Exception\InvalidArgumentException('You have to specify a padding method');
}
// padding
$data = $this->padding->pad($data, $this->getBlockSize());
$iv = $this->getSalt();
// encryption
$result = mcrypt_encrypt(
$this->supportedAlgos[$this->algo],
$this->getKey(),
$data,
$this->supportedModes[$this->mode],
$iv
);
return $iv . $result;
}
/**
* Decrypt
*
* @param string $data
* @throws Exception\InvalidArgumentException
* @return string
*/
public function decrypt($data)
{
if (empty($data)) {
throw new Exception\InvalidArgumentException('The data to decrypt cannot be empty');
}
if (null === $this->getKey()) {
throw new Exception\InvalidArgumentException('No key specified for the decryption');
}
if (null === $this->getPadding()) {
throw new Exception\InvalidArgumentException('You have to specify a padding method');
}
$iv = mb_substr($data, 0, $this->getSaltSize(), '8bit');
$ciphertext = mb_substr($data, $this->getSaltSize(), null, '8bit');
$result = mcrypt_decrypt(
$this->supportedAlgos[$this->algo],
$this->getKey(),
$ciphertext,
$this->supportedModes[$this->mode],
$iv
);
// unpadding
return $this->padding->strip($result);
}
/**
* Get the salt (IV) size
*
* @return int
*/
public function getSaltSize()
{
return mcrypt_get_iv_size($this->supportedAlgos[$this->algo], $this->supportedModes[$this->mode]);
}
/**
* Get the supported algorithms
*
* @return array
*/
public function getSupportedAlgorithms()
{
return array_keys($this->supportedAlgos);
}
/**
* Set the salt (IV)
*
* @param string $salt
* @return Mcrypt Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setSalt($salt)
{
if (empty($salt)) {
throw new Exception\InvalidArgumentException('The salt (IV) cannot be empty');
}
if (mb_strlen($salt, '8bit') < $this->getSaltSize()) {
throw new Exception\InvalidArgumentException(sprintf(
'The size of the salt (IV) must be at least %d bytes',
$this->getSaltSize()
));
}
$this->iv = $salt;
return $this;
}
/**
* Get the salt (IV) according to the size requested by the algorithm
*
* @return string
*/
public function getSalt()
{
if (empty($this->iv)) {
return;
}
if (mb_strlen($this->iv, '8bit') < $this->getSaltSize()) {
throw new Exception\RuntimeException(sprintf(
'The size of the salt (IV) must be at least %d bytes',
$this->getSaltSize()
));
}
return mb_substr($this->iv, 0, $this->getSaltSize(), '8bit');
}
/**
* Get the original salt value
*
* @return string
*/
public function getOriginalSalt()
{
return $this->iv;
}
/**
* Set the cipher mode
*
* @param string $mode
* @return Mcrypt Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setMode($mode)
{
if (! empty($mode)) {
$mode = strtolower($mode);
if (! array_key_exists($mode, $this->supportedModes)) {
throw new Exception\InvalidArgumentException(sprintf(
'The mode %s is not supported by %s',
$mode,
$this->algo
));
}
$this->mode = $mode;
}
return $this;
}
/**
* Get the cipher mode
*
* @return string
*/
public function getMode()
{
return $this->mode;
}
/**
* Get all supported encryption modes
*
* @return array
*/
public function getSupportedModes()
{
return array_keys($this->supportedModes);
}
/**
* Get the block size
*
* @return int
*/
public function getBlockSize()
{
return mcrypt_get_block_size($this->supportedAlgos[$this->algo], $this->supportedModes[$this->mode]);
}
}
laminas-crypt/src/Symmetric/PaddingPluginManager.php 0000644 00000002413 15240152646 0016630 0 ustar 00 <?php
namespace Laminas\Crypt\Symmetric;
use Psr\Container\ContainerInterface;
use function array_key_exists;
use function sprintf;
/**
* Plugin manager implementation for the padding adapter instances.
*
* Enforces that padding adapters retrieved are instances of
* Padding\PaddingInterface. Additionally, it registers a number of default
* padding adapters available.
*/
class PaddingPluginManager implements ContainerInterface
{
/** @var array<string, string> */
private $paddings = [
'pkcs7' => Padding\Pkcs7::class,
'nopadding' => Padding\NoPadding::class,
'null' => Padding\NoPadding::class,
];
/**
* Do we have the padding plugin?
*
* @param string $id
* @return bool
*/
public function has($id)
{
return array_key_exists($id, $this->paddings);
}
/**
* Retrieve the padding plugin
*
* @param string $id
* @return Padding\PaddingInterface
*/
public function get($id)
{
if (! $this->has($id)) {
throw new Exception\NotFoundException(sprintf(
"The padding adapter %s does not exist",
$id
));
}
$class = $this->paddings[$id];
return new $class();
}
}
laminas-crypt/src/Symmetric/Padding/Pkcs7.php 0000644 00000002164 15240152646 0015150 0 ustar 00 <?php
namespace Laminas\Crypt\Symmetric\Padding;
use function chr;
use function mb_strlen;
use function mb_substr;
use function ord;
use function str_repeat;
/**
* PKCS#7 padding
*/
class Pkcs7 implements PaddingInterface
{
/**
* Pad the string to the specified size
*
* @param string $string The string to pad
* @param int $blockSize The size to pad to
* @return string The padded string
*/
public function pad($string, $blockSize = 32)
{
$pad = $blockSize - (mb_strlen($string, '8bit') % $blockSize);
return $string . str_repeat(chr($pad), $pad);
}
/**
* Strip the padding from the supplied string
*
* @param string $string The string to trim
* @return string The unpadded string
*/
public function strip($string)
{
$end = mb_substr($string, -1, null, '8bit');
$last = ord($end);
$len = mb_strlen($string, '8bit') - $last;
if (mb_substr($string, $len, null, '8bit') === str_repeat($end, $last)) {
return mb_substr($string, 0, $len, '8bit');
}
return false;
}
}
laminas-crypt/src/Symmetric/Padding/NoPadding.php 0000644 00000001074 15240152647 0016024 0 ustar 00 <?php
namespace Laminas\Crypt\Symmetric\Padding;
/**
* No Padding
*/
class NoPadding implements PaddingInterface
{
/**
* Pad a string, do nothing and return the string
*
* @param string $string
* @param int $blockSize
* @return string
*/
public function pad($string, $blockSize = 32)
{
return $string;
}
/**
* Unpad a string, do nothing and return the string
*
* @param string $string
* @return string
*/
public function strip($string)
{
return $string;
}
}
laminas-crypt/src/Symmetric/Padding/PaddingInterface.php 0000644 00000001040 15240152647 0017341 0 ustar 00 <?php
namespace Laminas\Crypt\Symmetric\Padding;
interface PaddingInterface
{
/**
* Pad the string to the specified size
*
* @param string $string The string to pad
* @param int $blockSize The size to pad to
* @return string The padded string
*/
public function pad($string, $blockSize = 32);
/**
* Strip the padding from the supplied string
*
* @param string $string The string to trim
* @return string The unpadded string
*/
public function strip($string);
}
laminas-crypt/src/FileCipher.php 0000644 00000024410 15240152647 0012650 0 ustar 00 <?php
namespace Laminas\Crypt;
use Laminas\Crypt\Key\Derivation\Pbkdf2;
use Laminas\Math\Rand;
use function fclose;
use function file_exists;
use function filesize;
use function fopen;
use function fread;
use function fseek;
use function fwrite;
use function mb_strlen;
use function mb_substr;
use function sprintf;
use function str_repeat;
use function unlink;
/**
* Encrypt/decrypt a file using a symmetric cipher in CBC mode
* then authenticate using HMAC
*/
class FileCipher
{
public const BUFFER_SIZE = 1048576; // 16 * 65536 bytes = 1 Mb
/**
* Hash algorithm for Pbkdf2
*
* @var string
*/
protected $pbkdf2Hash = 'sha256';
/**
* Hash algorithm for HMAC
*
* @var string
*/
protected $hash = 'sha256';
/**
* Number of iterations for Pbkdf2
*
* @var int
*/
protected $keyIteration = 10000;
/**
* Key
*
* @var string
*/
protected $key;
/**
* Cipher
*
* @var SymmetricInterface
*/
protected $cipher;
/**
* Constructor
*
* @param SymmetricInterface $cipher
*/
public function __construct(?Symmetric\SymmetricInterface $cipher = null)
{
if (null === $cipher) {
$cipher = new Symmetric\Openssl();
}
$this->cipher = $cipher;
}
/**
* Set the cipher object
*
* @param SymmetricInterface $cipher
*/
public function setCipher(Symmetric\SymmetricInterface $cipher)
{
$this->cipher = $cipher;
}
/**
* Get the cipher object
*
* @return SymmetricInterface
*/
public function getCipher()
{
return $this->cipher;
}
/**
* Set the number of iterations for Pbkdf2
*
* @param int $num
*/
public function setKeyIteration($num)
{
$this->keyIteration = (int) $num;
}
/**
* Get the number of iterations for Pbkdf2
*
* @return int
*/
public function getKeyIteration()
{
return $this->keyIteration;
}
/**
* Set the encryption/decryption key
*
* @param string $key
* @throws Exception\InvalidArgumentException
*/
public function setKey($key)
{
if (empty($key)) {
throw new Exception\InvalidArgumentException('The key cannot be empty');
}
$this->key = (string) $key;
}
/**
* Get the key
*
* @return string|null
*/
public function getKey()
{
return $this->key;
}
/**
* Set algorithm of the symmetric cipher
*
* @param string $algo
*/
public function setCipherAlgorithm($algo)
{
$this->cipher->setAlgorithm($algo);
}
/**
* Get the cipher algorithm
*
* @return string|bool
*/
public function getCipherAlgorithm()
{
return $this->cipher->getAlgorithm();
}
/**
* Get the supported algorithms of the symmetric cipher
*
* @return array
*/
public function getCipherSupportedAlgorithms()
{
return $this->cipher->getSupportedAlgorithms();
}
/**
* Set the hash algorithm for HMAC authentication
*
* @param string $hash
* @throws Exception\InvalidArgumentException
*/
public function setHashAlgorithm($hash)
{
if (! Hash::isSupported($hash)) {
throw new Exception\InvalidArgumentException(
"The specified hash algorithm '{$hash}' is not supported by Laminas\Crypt\Hash"
);
}
$this->hash = (string) $hash;
}
/**
* Get the hash algorithm for HMAC authentication
*
* @return string
*/
public function getHashAlgorithm()
{
return $this->hash;
}
/**
* Set the hash algorithm for the Pbkdf2
*
* @param string $hash
* @throws Exception\InvalidArgumentException
*/
public function setPbkdf2HashAlgorithm($hash)
{
if (! Hash::isSupported($hash)) {
throw new Exception\InvalidArgumentException(
"The specified hash algorithm '{$hash}' is not supported by Laminas\Crypt\Hash"
);
}
$this->pbkdf2Hash = (string) $hash;
}
/**
* Get the Pbkdf2 hash algorithm
*
* @return string
*/
public function getPbkdf2HashAlgorithm()
{
return $this->pbkdf2Hash;
}
/**
* Encrypt then authenticate a file using HMAC
*
* @param string $fileIn
* @param string $fileOut
* @return bool
* @throws Exception\InvalidArgumentException
*/
public function encrypt($fileIn, $fileOut)
{
$this->checkFileInOut($fileIn, $fileOut);
if (empty($this->key)) {
throw new Exception\InvalidArgumentException('No key specified for encryption');
}
$read = fopen($fileIn, "r");
$write = fopen($fileOut, "w");
$iv = Rand::getBytes($this->cipher->getSaltSize());
$keys = Pbkdf2::calc(
$this->getPbkdf2HashAlgorithm(),
$this->getKey(),
$iv,
$this->getKeyIteration(),
$this->cipher->getKeySize() * 2
);
$hmac = '';
$size = 0;
$tot = filesize($fileIn);
$padding = $this->cipher->getPadding();
$this->cipher->setKey(mb_substr($keys, 0, $this->cipher->getKeySize(), '8bit'));
$this->cipher->setPadding(new Symmetric\Padding\NoPadding());
$this->cipher->setSalt($iv);
$this->cipher->setMode('cbc');
$hashAlgo = $this->getHashAlgorithm();
$saltSize = $this->cipher->getSaltSize();
$algorithm = $this->cipher->getAlgorithm();
$keyHmac = mb_substr($keys, $this->cipher->getKeySize(), null, '8bit');
while ($data = fread($read, self::BUFFER_SIZE)) {
$size += mb_strlen($data, '8bit');
// Padding if last block
if ($size === $tot) {
$this->cipher->setPadding($padding);
}
$result = $this->cipher->encrypt($data);
if ($size <= self::BUFFER_SIZE) {
// Write a placeholder for the HMAC and write the IV
fwrite($write, str_repeat(0, Hmac::getOutputSize($hashAlgo)));
} else {
$result = mb_substr($result, $saltSize, null, '8bit');
}
$hmac = Hmac::compute(
$keyHmac,
$hashAlgo,
$algorithm . $hmac . $result
);
$this->cipher->setSalt(mb_substr($result, -1 * $saltSize, null, '8bit'));
if (fwrite($write, $result) !== mb_strlen($result, '8bit')) {
return false;
}
}
$result = true;
// write the HMAC at the beginning of the file
fseek($write, 0);
if (fwrite($write, $hmac) !== mb_strlen($hmac, '8bit')) {
$result = false;
}
fclose($write);
fclose($read);
return $result;
}
/**
* Decrypt a file
*
* @param string $fileIn
* @param string $fileOut
* @return bool
* @throws Exception\InvalidArgumentException
*/
public function decrypt($fileIn, $fileOut)
{
$this->checkFileInOut($fileIn, $fileOut);
if (empty($this->key)) {
throw new Exception\InvalidArgumentException('No key specified for decryption');
}
$read = fopen($fileIn, "r");
$write = fopen($fileOut, "w");
$hmacRead = fread($read, Hmac::getOutputSize($this->getHashAlgorithm()));
$iv = fread($read, $this->cipher->getSaltSize());
$tot = filesize($fileIn);
$hmac = $iv;
$size = mb_strlen($iv, '8bit') + mb_strlen($hmacRead, '8bit');
$keys = Pbkdf2::calc(
$this->getPbkdf2HashAlgorithm(),
$this->getKey(),
$iv,
$this->getKeyIteration(),
$this->cipher->getKeySize() * 2
);
$padding = $this->cipher->getPadding();
$this->cipher->setPadding(new Symmetric\Padding\NoPadding());
$this->cipher->setKey(mb_substr($keys, 0, $this->cipher->getKeySize(), '8bit'));
$this->cipher->setMode('cbc');
$blockSize = $this->cipher->getBlockSize();
$hashAlgo = $this->getHashAlgorithm();
$algorithm = $this->cipher->getAlgorithm();
$saltSize = $this->cipher->getSaltSize();
$keyHmac = mb_substr($keys, $this->cipher->getKeySize(), null, '8bit');
while ($data = fread($read, self::BUFFER_SIZE)) {
$size += mb_strlen($data, '8bit');
// Unpadding if last block
if ($size + $blockSize >= $tot) {
$this->cipher->setPadding($padding);
$data .= fread($read, $blockSize);
}
$result = $this->cipher->decrypt($iv . $data);
$hmac = Hmac::compute(
$keyHmac,
$hashAlgo,
$algorithm . $hmac . $data
);
$iv = mb_substr($data, -1 * $saltSize, null, '8bit');
if (fwrite($write, $result) !== mb_strlen($result, '8bit')) {
return false;
}
}
fclose($write);
fclose($read);
// check for data integrity
if (! Utils::compareStrings($hmac, $hmacRead)) {
unlink($fileOut);
return false;
}
return true;
}
/**
* Check that input file exists and output file don't
*
* @param string $fileIn
* @param string $fileOut
* @throws Exception\InvalidArgumentException
*/
protected function checkFileInOut($fileIn, $fileOut)
{
if (! file_exists($fileIn)) {
throw new Exception\InvalidArgumentException(sprintf(
'I cannot open the %s file',
$fileIn
));
}
if (file_exists($fileOut)) {
throw new Exception\InvalidArgumentException(sprintf(
'The file %s already exists',
$fileOut
));
}
}
}
laminas-crypt/src/Password/Bcrypt.php 0000644 00000011622 15240152647 0013704 0 ustar 00 <?php
namespace Laminas\Crypt\Password;
use Laminas\Math\Rand;
use Laminas\Stdlib\ArrayUtils;
use Traversable;
use function is_array;
use function mb_strlen;
use function microtime;
use function password_hash;
use function password_verify;
use function sprintf;
use function strtolower;
use function trigger_error;
use const E_USER_DEPRECATED;
use const PASSWORD_BCRYPT;
use const PHP_VERSION_ID;
/**
* Bcrypt algorithm using crypt() function of PHP
*/
class Bcrypt implements PasswordInterface
{
public const MIN_SALT_SIZE = 22;
/** @var string */
protected $cost = '10';
/** @var string */
protected $salt;
/**
* Constructor
*
* @param array|Traversable $options
* @throws Exception\InvalidArgumentException
*/
public function __construct($options = [])
{
if (! empty($options)) {
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (! is_array($options)) {
throw new Exception\InvalidArgumentException(
'The options parameter must be an array or a Traversable'
);
}
foreach ($options as $key => $value) {
switch (strtolower($key)) {
case 'salt':
$this->setSalt($value);
break;
case 'cost':
$this->setCost($value);
break;
}
}
}
}
/**
* Bcrypt
*
* @param string $password
* @throws Exception\RuntimeException
* @return string
*/
public function create($password)
{
$options = ['cost' => (int) $this->cost];
if (PHP_VERSION_ID < 70000) { // salt is deprecated from PHP 7.0
$salt = $this->salt ?: Rand::getBytes(self::MIN_SALT_SIZE);
$options['salt'] = $salt;
}
return password_hash($password, PASSWORD_BCRYPT, $options);
}
/**
* Verify if a password is correct against a hash value
*
* @param string $password
* @param string $hash
* @return bool
*/
public function verify($password, $hash)
{
return password_verify($password, $hash);
}
/**
* Set the cost parameter
*
* @param int|string $cost
* @throws Exception\InvalidArgumentException
* @return Bcrypt Provides a fluent interface
*/
public function setCost($cost)
{
if (! empty($cost)) {
$cost = (int) $cost;
if ($cost < 4 || $cost > 31) {
throw new Exception\InvalidArgumentException(
'The cost parameter of bcrypt must be in range 04-31'
);
}
$this->cost = sprintf('%1$02d', $cost);
}
return $this;
}
/**
* Get the cost parameter
*
* @return string
*/
public function getCost()
{
return $this->cost;
}
/**
* Set the salt value
*
* @param string $salt
* @throws Exception\InvalidArgumentException
* @return Bcrypt Provides a fluent interface
*/
public function setSalt($salt)
{
if (PHP_VERSION_ID >= 70000) {
trigger_error('Salt support is deprecated starting with PHP 7.0.0', E_USER_DEPRECATED);
}
if (mb_strlen($salt, '8bit') < self::MIN_SALT_SIZE) {
throw new Exception\InvalidArgumentException(
'The length of the salt must be at least ' . self::MIN_SALT_SIZE . ' bytes'
);
}
$this->salt = $salt;
return $this;
}
/**
* Get the salt value
*
* @return string
*/
public function getSalt()
{
if (PHP_VERSION_ID >= 70000) {
trigger_error('Salt support is deprecated starting with PHP 7.0.0', E_USER_DEPRECATED);
}
return $this->salt;
}
/**
* Benchmark the bcrypt hash generation to determine the cost parameter based on time to target.
*
* The default time to test is 50 milliseconds which is a good baseline for
* systems handling interactive logins. If you increase the time, you will
* get high cost with better security, but potentially expose your system
* to DoS attacks.
*
* @see php.net/manual/en/function.password-hash.php#refsect1-function.password-hash-examples
*
* @param float $timeTarget Defaults to 50ms (0.05)
* @return int Maximum cost value that falls within the time to target.
*/
public function benchmarkCost($timeTarget = 0.05)
{
$cost = 8;
do {
$cost++;
$start = microtime(true);
password_hash('test', PASSWORD_BCRYPT, ['cost' => $cost]);
$end = microtime(true);
} while (($end - $start) < $timeTarget);
return $cost;
}
}
laminas-crypt/src/Password/PasswordInterface.php 0000644 00000001150 15240152647 0016057 0 ustar 00 <?php
namespace Laminas\Crypt\Password;
interface PasswordInterface
{
/**
* Create a password hash for a given plain text password
*
* @param string $password The password to hash
* @return string The formatted password hash
*/
public function create($password);
/**
* Verify a password hash against a given plain text password
*
* @param string $password The password to hash
* @param string $hash The supplied hash to validate
* @return bool Does the password validate against the hash
*/
public function verify($password, $hash);
}
laminas-crypt/src/Password/Apache.php 0000644 00000021051 15240152647 0013617 0 ustar 00 <?php
namespace Laminas\Crypt\Password;
use Laminas\Crypt\Utils;
use Laminas\Math\Rand;
use Traversable;
use function addcslashes;
use function base64_encode;
use function chr;
use function crypt;
use function explode;
use function implode;
use function in_array;
use function is_array;
use function mb_strlen;
use function mb_substr;
use function md5;
use function min;
use function pack;
use function preg_match;
use function sha1;
use function sprintf;
use function strpos;
use function strrev;
use function strtolower;
use function strtr;
/**
* Apache password authentication
*
* @see http://httpd.apache.org/docs/2.2/misc/password_encryptions.html
*/
class Apache implements PasswordInterface
{
public const BASE64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
public const ALPHA64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
/** @var array */
protected $supportedFormat = [
'crypt',
'sha1',
'md5',
'digest',
];
/** @var string */
protected $format;
/** @var string AuthName (realm) for digest authentication */
protected $authName;
/** @var string UserName */
protected $userName;
/**
* Constructor
*
* @param array|Traversable $options
* @throws Exception\InvalidArgumentException
*/
public function __construct($options = [])
{
if (empty($options)) {
return;
}
if (! is_array($options) && ! $options instanceof Traversable) {
throw new Exception\InvalidArgumentException(
'The options parameter must be an array or a Traversable'
);
}
foreach ($options as $key => $value) {
switch (strtolower($key)) {
case 'format':
$this->setFormat($value);
break;
case 'authname':
$this->setAuthName($value);
break;
case 'username':
$this->setUserName($value);
break;
}
}
}
/**
* Generate the hash of a password
*
* @param string $password
* @throws Exception\RuntimeException
* @return string
*/
public function create($password)
{
if (empty($this->format)) {
throw new Exception\RuntimeException(
'You must specify a password format'
);
}
switch ($this->format) {
case 'crypt':
$hash = crypt($password, Rand::getString(2, self::ALPHA64));
break;
case 'sha1':
$hash = '{SHA}' . base64_encode(sha1($password, true));
break;
case 'md5':
$hash = $this->apr1Md5($password);
break;
case 'digest':
if (empty($this->userName) || empty($this->authName)) {
throw new Exception\RuntimeException(
'You must specify UserName and AuthName (realm) to generate the digest'
);
}
$hash = md5($this->userName . ':' . $this->authName . ':' . $password);
break;
}
return $hash;
}
/**
* Verify if a password is correct against a hash value
*
* @param string $password
* @param string $hash
* @return bool
*/
public function verify($password, $hash)
{
if (mb_substr($hash, 0, 5, '8bit') === '{SHA}') {
$hash2 = '{SHA}' . base64_encode(sha1($password, true));
return Utils::compareStrings($hash, $hash2);
}
if (mb_substr($hash, 0, 6, '8bit') === '$apr1$') {
$token = explode('$', $hash);
if (empty($token[2])) {
throw new Exception\InvalidArgumentException(
'The APR1 password format is not valid'
);
}
$hash2 = $this->apr1Md5($password, $token[2]);
return Utils::compareStrings($hash, $hash2);
}
$bcryptPattern = '/\$2[ay]?\$[0-9]{2}\$[' . addcslashes(static::BASE64, '+/') . '\.]{53}/';
if (mb_strlen($hash, '8bit') > 13 && ! preg_match($bcryptPattern, $hash)) { // digest
if (empty($this->userName) || empty($this->authName)) {
throw new Exception\RuntimeException(
'You must specify UserName and AuthName (realm) to verify the digest'
);
}
$hash2 = md5($this->userName . ':' . $this->authName . ':' . $password);
return Utils::compareStrings($hash, $hash2);
}
return Utils::compareStrings($hash, crypt($password, $hash));
}
/**
* Set the format of the password
*
* @param string $format
* @throws Exception\InvalidArgumentException
* @return Apache Provides a fluent interface
*/
public function setFormat($format)
{
$format = strtolower($format);
if (! in_array($format, $this->supportedFormat)) {
throw new Exception\InvalidArgumentException(sprintf(
'The format %s specified is not valid. The supported formats are: %s',
$format,
implode(',', $this->supportedFormat)
));
}
$this->format = $format;
return $this;
}
/**
* Get the format of the password
*
* @return string
*/
public function getFormat()
{
return $this->format;
}
/**
* Set the AuthName (for digest authentication)
*
* @param string $name
* @return Apache Provides a fluent interface
*/
public function setAuthName($name)
{
$this->authName = $name;
return $this;
}
/**
* Get the AuthName (for digest authentication)
*
* @return string
*/
public function getAuthName()
{
return $this->authName;
}
/**
* Set the username
*
* @param string $name
* @return Apache Provides a fluent interface
*/
public function setUserName($name)
{
$this->userName = $name;
return $this;
}
/**
* Get the username
*
* @return string
*/
public function getUserName()
{
return $this->userName;
}
/**
* Convert a binary string using the alphabet "./0-9A-Za-z"
*
* @param string $value
* @return string
*/
protected function toAlphabet64($value)
{
return strtr(strrev(mb_substr(base64_encode($value), 2, null, '8bit')), self::BASE64, self::ALPHA64);
}
/**
* APR1 MD5 algorithm
*
* @param string $password
* @param null|string $salt
* @return string
*/
protected function apr1Md5($password, $salt = null)
{
if (null === $salt) {
$salt = Rand::getString(8, self::ALPHA64);
} else {
if (mb_strlen($salt, '8bit') !== 8) {
throw new Exception\InvalidArgumentException(
'The salt value for APR1 algorithm must be 8 characters long'
);
}
for ($i = 0; $i < 8; $i++) {
if (strpos(self::ALPHA64, $salt[$i]) === false) {
throw new Exception\InvalidArgumentException(
'The salt value must be a string in the alphabet "./0-9A-Za-z"'
);
}
}
}
$len = mb_strlen($password, '8bit');
$text = $password . '$apr1$' . $salt;
$bin = pack("H32", md5($password . $salt . $password));
for ($i = $len; $i > 0; $i -= 16) {
$text .= mb_substr($bin, 0, min(16, $i), '8bit');
}
for ($i = $len; $i > 0; $i >>= 1) {
$text .= $i & 1 ? chr(0) : $password[0];
}
$bin = pack("H32", md5($text));
for ($i = 0; $i < 1000; $i++) {
$new = $i & 1 ? $password : $bin;
if ($i % 3) {
$new .= $salt;
}
if ($i % 7) {
$new .= $password;
}
$new .= $i & 1 ? $bin : $password;
$bin = pack("H32", md5($new));
}
$tmp = '';
for ($i = 0; $i < 5; $i++) {
$k = $i + 6;
$j = $i + 12;
if ($j === 16) {
$j = 5;
}
$tmp = $bin[$i] . $bin[$k] . $bin[$j] . $tmp;
}
$tmp = chr(0) . chr(0) . $bin[11] . $tmp;
return '$apr1$' . $salt . '$' . $this->toAlphabet64($tmp);
}
}
laminas-crypt/src/Password/Exception/InvalidArgumentException.php 0000644 00000000350 15240152647 0021343 0 ustar 00 <?php
namespace Laminas\Crypt\Password\Exception;
use Laminas\Crypt\Exception;
/**
* Invalid argument exception
*/
class InvalidArgumentException extends Exception\InvalidArgumentException implements
ExceptionInterface
{
}
laminas-crypt/src/Password/Exception/ExceptionInterface.php 0000644 00000000245 15240152647 0020155 0 ustar 00 <?php
namespace Laminas\Crypt\Password\Exception;
use Laminas\Crypt\Exception\ExceptionInterface as Exception;
interface ExceptionInterface extends Exception
{
}
laminas-crypt/src/Password/Exception/RuntimeException.php 0000644 00000000330 15240152647 0017673 0 ustar 00 <?php
namespace Laminas\Crypt\Password\Exception;
use Laminas\Crypt\Exception;
/**
* Runtime argument exception
*/
class RuntimeException extends Exception\RuntimeException implements
ExceptionInterface
{
}
laminas-crypt/src/Password/BcryptSha.php 0000644 00000001541 15240152647 0014337 0 ustar 00 <?php
namespace Laminas\Crypt\Password;
use Laminas\Crypt\Hash;
/**
* Bcrypt algorithm using crypt() function of PHP with password
* hashed using SHA2 to allow for passwords >72 characters.
*/
class BcryptSha extends Bcrypt
{
/**
* BcryptSha
*
* @param string $password
* @throws Exception\RuntimeException
* @return string
*/
public function create($password)
{
return parent::create(Hash::compute('sha256', $password));
}
/**
* Verify if a password is correct against a hash value
*
* @param string $password
* @param string $hash
* @throws Exception\RuntimeException When the hash is unable to be processed.
* @return bool
*/
public function verify($password, $hash)
{
return parent::verify(Hash::compute('sha256', $password), $hash);
}
}
laminas-crypt/src/Hmac.php 0000644 00000005264 15240152647 0011514 0 ustar 00 <?php
namespace Laminas\Crypt;
use function function_exists;
use function hash_algos;
use function hash_hmac;
use function hash_hmac_algos;
use function in_array;
use function mb_strlen;
use function strtolower;
/**
* PHP implementation of the RFC 2104 Hash based Message Authentication Code
*/
class Hmac
{
public const OUTPUT_STRING = false;
public const OUTPUT_BINARY = true;
/**
* Last algorithm supported
*
* @var string|null
*/
protected static $lastAlgorithmSupported;
/**
* Performs a HMAC computation given relevant details such as Key, Hashing
* algorithm, the data to compute MAC of, and an output format of String,
* or Binary.
*
* @param string $key
* @param string $hash
* @param string $data
* @param bool $output
* @throws Exception\InvalidArgumentException
* @return string
*/
public static function compute($key, $hash, $data, $output = self::OUTPUT_STRING)
{
if (empty($key)) {
throw new Exception\InvalidArgumentException('Provided key is null or empty');
}
if (! $hash || ($hash !== static::$lastAlgorithmSupported && ! static::isSupported($hash))) {
throw new Exception\InvalidArgumentException(
"Hash algorithm is not supported on this PHP installation; provided '{$hash}'"
);
}
return hash_hmac($hash, $data, $key, $output);
}
/**
* Get the output size according to the hash algorithm and the output format
*
* @param string $hash
* @param bool $output
* @return int
*/
public static function getOutputSize($hash, $output = self::OUTPUT_STRING)
{
return mb_strlen(static::compute('key', $hash, 'data', $output), '8bit');
}
/**
* Get the supported algorithm
*
* @return array
*/
public static function getSupportedAlgorithms()
{
return function_exists('hash_hmac_algos') ? hash_hmac_algos() : hash_algos();
}
/**
* Is the hash algorithm supported?
*
* @param string $algorithm
* @return bool
*/
public static function isSupported($algorithm)
{
if ($algorithm === static::$lastAlgorithmSupported) {
return true;
}
$algos = static::getSupportedAlgorithms();
if (in_array(strtolower($algorithm), $algos, true)) {
static::$lastAlgorithmSupported = $algorithm;
return true;
}
return false;
}
/**
* Clear the cache of last algorithm supported
*/
public static function clearLastAlgorithmCache()
{
static::$lastAlgorithmSupported = null;
}
}
laminas-crypt/src/SymmetricPluginManager.php 0000644 00000002426 15240152647 0015267 0 ustar 00 <?php
namespace Laminas\Crypt;
use Psr\Container\ContainerInterface;
use function array_key_exists;
use function sprintf;
/**
* Plugin manager implementation for the symmetric adapter instances.
*
* Enforces that symmetric adapters retrieved are instances of
* Symmetric\SymmetricInterface. Additionally, it registers a number of default
* symmetric adapters available.
*/
class SymmetricPluginManager implements ContainerInterface
{
/**
* Default set of symmetric adapters
*
* @var array
*/
protected $symmetric = [
'mcrypt' => Symmetric\Mcrypt::class,
'openssl' => Symmetric\Openssl::class,
];
/**
* Do we have the symmetric plugin?
*
* @param string $id
* @return bool
*/
public function has($id)
{
return array_key_exists($id, $this->symmetric);
}
/**
* Retrieve the symmetric plugin
*
* @param string $id
* @return Symmetric\SymmetricInterface
*/
public function get($id)
{
if (! $this->has($id)) {
throw new Exception\NotFoundException(sprintf(
'The symmetric adapter %s does not exist',
$id
));
}
$class = $this->symmetric[$id];
return new $class();
}
}
laminas-crypt/src/Utils.php 0000644 00000002416 15240152647 0011740 0 ustar 00 <?php
namespace Laminas\Crypt;
use function function_exists;
use function hash_equals;
use function mb_strlen;
use function min;
use function ord;
/**
* Tools for cryptography
*/
class Utils
{
/**
* Compare two strings to avoid timing attacks
*
* C function memcmp() internally used by PHP, exits as soon as a difference
* is found in the two buffers. That makes possible of leaking
* timing information useful to an attacker attempting to iteratively guess
* the unknown string (e.g. password).
* The length will leak.
*
* @param string $expected
* @param string $actual
* @return bool
*/
public static function compareStrings($expected, $actual)
{
$expected = (string) $expected;
$actual = (string) $actual;
if (function_exists('hash_equals')) {
return hash_equals($expected, $actual);
}
$lenExpected = mb_strlen($expected, '8bit');
$lenActual = mb_strlen($actual, '8bit');
$len = min($lenExpected, $lenActual);
$result = 0;
for ($i = 0; $i < $len; $i++) {
$result |= ord($expected[$i]) ^ ord($actual[$i]);
}
$result |= $lenExpected ^ $lenActual;
return $result === 0;
}
}
laminas-crypt/src/Hybrid.php 0000644 00000007764 15240152647 0012074 0 ustar 00 <?php
namespace Laminas\Crypt;
use Laminas\Crypt\PublicKey\Rsa\PrivateKey;
use Laminas\Crypt\PublicKey\Rsa\PublicKey as PubKey;
use Laminas\Math\Rand;
use function array_search;
use function base64_decode;
use function base64_encode;
use function explode;
use function is_array;
use function is_string;
use function sprintf;
/**
* Hybrid encryption (OpenPGP like)
*
* The data are encrypted using a BlockCipher with a random session key
* that is encrypted using RSA with the public key of the receiver.
* The decryption process retrieves the session key using RSA with the private
* key of the receiver and decrypts the data using the BlockCipher.
*/
class Hybrid
{
/** @var BlockCipher */
protected $bCipher;
/** @var PublicKey\Rsa */
protected $rsa;
/**
* Constructor
*/
public function __construct(?BlockCipher $bCipher = null, ?PublicKey\Rsa $rsa = null)
{
$this->bCipher = $bCipher ?? BlockCipher::factory('openssl');
$this->rsa = $rsa ?? new PublicKey\Rsa();
}
/**
* Encrypt using a keyrings
*
* @param string $plaintext
* @param array|string $keys
* @return string
* @throws RuntimeException
*/
public function encrypt($plaintext, $keys = null)
{
// generate a random session key
$sessionKey = Rand::getBytes($this->bCipher->getCipher()->getKeySize());
// encrypt the plaintext with blockcipher algorithm
$this->bCipher->setKey($sessionKey);
$ciphertext = $this->bCipher->encrypt($plaintext);
if (! is_array($keys)) {
$keys = ['' => $keys];
}
$encKeys = '';
// encrypt the session key with public keys
foreach ($keys as $id => $pubkey) {
if (! $pubkey instanceof PubKey && ! is_string($pubkey)) {
throw new Exception\RuntimeException(sprintf(
"The public key must be a string in PEM format or an instance of %s",
PubKey::class
));
}
$pubkey = is_string($pubkey) ? new PubKey($pubkey) : $pubkey;
$encKeys .= sprintf(
"%s:%s:",
base64_encode($id),
base64_encode($this->rsa->encrypt($sessionKey, $pubkey))
);
}
return $encKeys . ';' . $ciphertext;
}
/**
* Decrypt using a private key
*
* @param string $msg
* @param string $privateKey
* @param string $passPhrase
* @param string $id
* @return string
* @throws RuntimeException
*/
public function decrypt($msg, $privateKey = null, $passPhrase = null, $id = "")
{
// get the session key
[$encKeys, $ciphertext] = explode(';', $msg, 2);
$keys = explode(':', $encKeys);
$pos = array_search(base64_encode($id), $keys);
if (false === $pos) {
throw new Exception\RuntimeException(
"This private key cannot be used for decryption"
);
}
if (! $privateKey instanceof PrivateKey && ! is_string($privateKey)) {
throw new Exception\RuntimeException(sprintf(
"The private key must be a string in PEM format or an instance of %s",
PrivateKey::class
));
}
$privateKey = is_string($privateKey) ? new PrivateKey($privateKey, $passPhrase) : $privateKey;
// decrypt the session key with privateKey
$sessionKey = $this->rsa->decrypt(base64_decode($keys[$pos + 1]), $privateKey);
// decrypt the plaintext with the blockcipher algorithm
$this->bCipher->setKey($sessionKey);
return $this->bCipher->decrypt($ciphertext, $sessionKey);
}
/**
* Get the BlockCipher adapter
*
* @return BlockCipher
*/
public function getBlockCipherInstance()
{
return $this->bCipher;
}
/**
* Get the Rsa instance
*
* @return Rsa
*/
public function getRsaInstance()
{
return $this->rsa;
}
}
laminas-crypt/src/BlockCipher.php 0000644 00000033473 15240152650 0013026 0 ustar 00 <?php
namespace Laminas\Crypt;
use Laminas\Crypt\Key\Derivation\Pbkdf2;
use Laminas\Crypt\Symmetric\SymmetricInterface;
use Laminas\Math\Rand;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface as NotFoundException;
use function base64_decode;
use function base64_encode;
use function class_exists;
use function get_class;
use function gettype;
use function in_array;
use function is_array;
use function is_object;
use function is_string;
use function is_subclass_of;
use function mb_substr;
use function sprintf;
/**
* Encrypt using a symmetric cipher then authenticate using HMAC (SHA-256)
*/
class BlockCipher
{
/**
* Hash algorithm for Pbkdf2
*
* @var string
*/
protected $pbkdf2Hash = 'sha256';
/**
* Symmetric cipher
*
* @var SymmetricInterface
*/
protected $cipher;
/**
* Symmetric cipher plugin manager
*
* @var SymmetricPluginManager
*/
protected static $symmetricPlugins;
/**
* Hash algorithm for HMAC
*
* @var string
*/
protected $hash = 'sha256';
/**
* Check if the salt has been set
*
* @var bool
*/
protected $saltSetted = false;
/**
* The output is binary?
*
* @var bool
*/
protected $binaryOutput = false;
/**
* Number of iterations for Pbkdf2
*
* @var string
*/
protected $keyIteration = 5000;
/**
* Key
*
* @var string
*/
protected $key;
/**
* Constructor
*/
public function __construct(SymmetricInterface $cipher)
{
$this->cipher = $cipher;
}
/**
* Factory
*
* @param string $adapter
* @param array $options
* @return BlockCipher
*/
public static function factory($adapter, $options = [])
{
$plugins = static::getSymmetricPluginManager();
try {
$cipher = $plugins->get($adapter);
} catch (NotFoundException $e) {
throw new Exception\RuntimeException(sprintf(
'The symmetric adapter %s does not exist',
$adapter
));
}
$cipher->setOptions($options);
return new static($cipher);
}
/**
* Returns the symmetric cipher plugin manager. If it doesn't exist it's created.
*
* @return ContainerInterface
*/
public static function getSymmetricPluginManager()
{
if (static::$symmetricPlugins === null) {
static::setSymmetricPluginManager(new SymmetricPluginManager());
}
return static::$symmetricPlugins;
}
/**
* Set the symmetric cipher plugin manager
*
* @param string|SymmetricPluginManager $plugins
* @throws Exception\InvalidArgumentException
*/
public static function setSymmetricPluginManager($plugins)
{
if (is_string($plugins)) {
if (! class_exists($plugins) || ! is_subclass_of($plugins, ContainerInterface::class)) {
throw new Exception\InvalidArgumentException(sprintf(
'Unable to locate symmetric cipher plugins using class "%s"; '
. 'class does not exist or does not implement ContainerInterface',
$plugins
));
}
$plugins = new $plugins();
}
if (! $plugins instanceof ContainerInterface) {
throw new Exception\InvalidArgumentException(sprintf(
'Symmetric plugin must implements Interop\Container\ContainerInterface;; received "%s"',
is_object($plugins) ? get_class($plugins) : gettype($plugins)
));
}
static::$symmetricPlugins = $plugins;
}
/**
* Set the symmetric cipher
*
* @return BlockCipher Provides a fluent interface
*/
public function setCipher(SymmetricInterface $cipher)
{
$this->cipher = $cipher;
return $this;
}
/**
* Get symmetric cipher
*
* @return SymmetricInterface
*/
public function getCipher()
{
return $this->cipher;
}
/**
* Set the number of iterations for Pbkdf2
*
* @param int $num
* @return BlockCipher Provides a fluent interface
*/
public function setKeyIteration($num)
{
$this->keyIteration = (int) $num;
return $this;
}
/**
* Get the number of iterations for Pbkdf2
*
* @return int
*/
public function getKeyIteration()
{
return $this->keyIteration;
}
/**
* Set the salt (IV)
*
* @param string $salt
* @return BlockCipher Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setSalt($salt)
{
try {
$this->cipher->setSalt($salt);
} catch (Symmetric\Exception\InvalidArgumentException $e) {
throw new Exception\InvalidArgumentException("The salt is not valid: " . $e->getMessage());
}
$this->saltSetted = true;
return $this;
}
/**
* Get the salt (IV) according to the size requested by the algorithm
*
* @return string
*/
public function getSalt()
{
return $this->cipher->getSalt();
}
/**
* Get the original salt value
*
* @return string
*/
public function getOriginalSalt()
{
return $this->cipher->getOriginalSalt();
}
/**
* Enable/disable the binary output
*
* @param bool $value
* @return BlockCipher Provides a fluent interface
*/
public function setBinaryOutput($value)
{
$this->binaryOutput = (bool) $value;
return $this;
}
/**
* Get the value of binary output
*
* @return bool
*/
public function getBinaryOutput()
{
return $this->binaryOutput;
}
/**
* Set the encryption/decryption key
*
* @param string $key
* @return BlockCipher Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setKey($key)
{
if (empty($key)) {
throw new Exception\InvalidArgumentException('The key cannot be empty');
}
$this->key = $key;
return $this;
}
/**
* Get the key
*
* @return string
*/
public function getKey()
{
return $this->key;
}
/**
* Set algorithm of the symmetric cipher
*
* @param string $algo
* @return BlockCipher Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setCipherAlgorithm($algo)
{
try {
$this->cipher->setAlgorithm($algo);
} catch (Symmetric\Exception\InvalidArgumentException $e) {
throw new Exception\InvalidArgumentException($e->getMessage());
}
return $this;
}
/**
* Get the cipher algorithm
*
* @return string|bool
*/
public function getCipherAlgorithm()
{
return $this->cipher->getAlgorithm();
}
/**
* Get the supported algorithms of the symmetric cipher
*
* @return array
*/
public function getCipherSupportedAlgorithms()
{
return $this->cipher->getSupportedAlgorithms();
}
/**
* Set the hash algorithm for HMAC authentication
*
* @param string $hash
* @return BlockCipher Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setHashAlgorithm($hash)
{
if (! Hash::isSupported($hash)) {
throw new Exception\InvalidArgumentException(
"The specified hash algorithm '{$hash}' is not supported by Laminas\Crypt\Hash"
);
}
$this->hash = $hash;
return $this;
}
/**
* Get the hash algorithm for HMAC authentication
*
* @return string
*/
public function getHashAlgorithm()
{
return $this->hash;
}
/**
* Set the hash algorithm for the Pbkdf2
*
* @param string $hash
* @return BlockCipher Provides a fluent interface
* @throws Exception\InvalidArgumentException
*/
public function setPbkdf2HashAlgorithm($hash)
{
if (! Hash::isSupported($hash)) {
throw new Exception\InvalidArgumentException(
"The specified hash algorithm '{$hash}' is not supported by Laminas\Crypt\Hash"
);
}
$this->pbkdf2Hash = $hash;
return $this;
}
/**
* Get the Pbkdf2 hash algorithm
*
* @return string
*/
public function getPbkdf2HashAlgorithm()
{
return $this->pbkdf2Hash;
}
/**
* Encrypt then authenticate using HMAC
*
* @param string $data
* @return string
* @throws Exception\InvalidArgumentException
*/
public function encrypt($data)
{
// 0 (as integer), 0.0 (as float) & '0' (as string) will return false, though these should be allowed
// Must be a string, integer, or float in order to encrypt
if (
(is_string($data) && $data === '')
|| is_array($data)
|| is_object($data)
) {
throw new Exception\InvalidArgumentException('The data to encrypt cannot be empty');
}
// Cast to string prior to encrypting
if (! is_string($data)) {
$data = (string) $data;
}
if (empty($this->key)) {
throw new Exception\InvalidArgumentException('No key specified for the encryption');
}
$keySize = $this->cipher->getKeySize();
// generate a random salt (IV) if the salt has not been set
if (! $this->saltSetted) {
$this->cipher->setSalt(Rand::getBytes($this->cipher->getSaltSize()));
}
if (in_array($this->cipher->getMode(), ['ccm', 'gcm'], true)) {
return $this->encryptViaCcmOrGcm($data, $keySize);
}
// generate the encryption key and the HMAC key for the authentication
$hash = Pbkdf2::calc(
$this->getPbkdf2HashAlgorithm(),
$this->getKey(),
$this->getSalt(),
$this->keyIteration,
$keySize * 2
);
// set the encryption key
$this->cipher->setKey(mb_substr($hash, 0, $keySize, '8bit'));
// set the key for HMAC
$keyHmac = mb_substr($hash, $keySize, null, '8bit');
// encryption
$ciphertext = $this->cipher->encrypt($data);
// HMAC
$hmac = Hmac::compute($keyHmac, $this->hash, $this->cipher->getAlgorithm() . $ciphertext);
return $this->binaryOutput ? $hmac . $ciphertext : $hmac . base64_encode($ciphertext);
}
/**
* Decrypt
*
* @param string $data
* @return string|bool
* @throws Exception\InvalidArgumentException
*/
public function decrypt($data)
{
if (! is_string($data)) {
throw new Exception\InvalidArgumentException('The data to decrypt must be a string');
}
if ('' === $data) {
throw new Exception\InvalidArgumentException('The data to decrypt cannot be empty');
}
if (empty($this->key)) {
throw new Exception\InvalidArgumentException('No key specified for the decryption');
}
$keySize = $this->cipher->getKeySize();
if (in_array($this->cipher->getMode(), ['ccm', 'gcm'], true)) {
return $this->decryptViaCcmOrGcm($data, $keySize);
}
$hmacSize = Hmac::getOutputSize($this->hash);
$hmac = mb_substr($data, 0, $hmacSize, '8bit');
$ciphertext = mb_substr($data, $hmacSize, null, '8bit') ?: '';
if (! $this->binaryOutput) {
$ciphertext = base64_decode($ciphertext);
}
$iv = mb_substr($ciphertext, 0, $this->cipher->getSaltSize(), '8bit');
// generate the encryption key and the HMAC key for the authentication
$hash = Pbkdf2::calc(
$this->getPbkdf2HashAlgorithm(),
$this->getKey(),
$iv,
$this->keyIteration,
$keySize * 2
);
// set the decryption key
$this->cipher->setKey(mb_substr($hash, 0, $keySize, '8bit'));
// set the key for HMAC
$keyHmac = mb_substr($hash, $keySize, null, '8bit');
$hmacNew = Hmac::compute($keyHmac, $this->hash, $this->cipher->getAlgorithm() . $ciphertext);
if (! Utils::compareStrings($hmacNew, $hmac)) {
return false;
}
return $this->cipher->decrypt($ciphertext);
}
/**
* Note: CCM and GCM modes do not need HMAC
*
* @param string $data
* @param int $keySize
* @return string
* @throws Exception\InvalidArgumentException
*/
private function encryptViaCcmOrGcm($data, $keySize)
{
$this->cipher->setKey(Pbkdf2::calc(
$this->getPbkdf2HashAlgorithm(),
$this->getKey(),
$this->getSalt(),
$this->keyIteration,
$keySize
));
$cipherText = $this->cipher->encrypt($data);
return $this->binaryOutput ? $cipherText : base64_encode($cipherText);
}
/**
* Note: CCM and GCM modes do not need HMAC
*
* @param string $data
* @param int $keySize
* @return string
* @throws Exception\InvalidArgumentException
*/
private function decryptViaCcmOrGcm($data, $keySize)
{
$cipherText = $this->binaryOutput ? $data : base64_decode($data);
$iv = mb_substr($cipherText, $this->cipher->getTagSize(), $this->cipher->getSaltSize(), '8bit');
$this->cipher->setKey(Pbkdf2::calc(
$this->getPbkdf2HashAlgorithm(),
$this->getKey(),
$iv,
$this->keyIteration,
$keySize
));
return $this->cipher->decrypt($cipherText);
}
}
laminas-crypt/src/PublicKey/Rsa.php 0000644 00000023226 15240152650 0013250 0 ustar 00 <?php
namespace Laminas\Crypt\PublicKey;
use Laminas\Crypt\PublicKey\Rsa\Exception;
use Laminas\Stdlib\ArrayUtils;
use Traversable;
use function base64_decode;
use function base64_encode;
use function extension_loaded;
use function is_array;
use function is_file;
use function is_string;
use function openssl_error_string;
use function openssl_sign;
use function openssl_verify;
use function trim;
/**
* Implementation of the RSA public key encryption algorithm.
*/
class Rsa
{
public const MODE_AUTO = 1;
public const MODE_BASE64 = 2;
public const MODE_RAW = 3;
/** @var RsaOptions */
protected $options;
/**
* RSA instance factory
*
* @param array|Traversable $options
* @return Rsa
* @throws Rsa\Exception\RuntimeException
* @throws Rsa\Exception\InvalidArgumentException
*/
public static function factory($options)
{
if (! extension_loaded('openssl')) {
throw new Exception\RuntimeException(
'Can not create Laminas\Crypt\PublicKey\Rsa; openssl extension needs to be loaded'
);
}
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
} elseif (! is_array($options)) {
throw new Exception\InvalidArgumentException(
'The options parameter must be an array or a Traversable'
);
}
$privateKey = null;
$passPhrase = $options['pass_phrase'] ?? null;
if (isset($options['private_key'])) {
if (is_file($options['private_key'])) {
$privateKey = Rsa\PrivateKey::fromFile($options['private_key'], $passPhrase);
} elseif (is_string($options['private_key'])) {
$privateKey = new Rsa\PrivateKey($options['private_key'], $passPhrase);
} else {
throw new Exception\InvalidArgumentException(
'Parameter "private_key" must be PEM formatted string or path to key file'
);
}
unset($options['private_key']);
}
$publicKey = null;
if (isset($options['public_key'])) {
if (is_file($options['public_key'])) {
$publicKey = Rsa\PublicKey::fromFile($options['public_key']);
} elseif (is_string($options['public_key'])) {
$publicKey = new Rsa\PublicKey($options['public_key']);
} else {
throw new Exception\InvalidArgumentException(
'Parameter "public_key" must be PEM/certificate string or path to key/certificate file'
);
}
unset($options['public_key']);
}
$options = new RsaOptions($options);
if ($privateKey instanceof Rsa\PrivateKey) {
$options->setPrivateKey($privateKey);
}
if ($publicKey instanceof Rsa\PublicKey) {
$options->setPublicKey($publicKey);
}
return new Rsa($options);
}
/**
* @throws Rsa\Exception\RuntimeException
*/
public function __construct(?RsaOptions $options = null)
{
if (! extension_loaded('openssl')) {
throw new Exception\RuntimeException(
'Laminas\Crypt\PublicKey\Rsa requires openssl extension to be loaded'
);
}
if ($options === null) {
$this->options = new RsaOptions();
} else {
$this->options = $options;
}
}
/**
* Set options
*
* @return Rsa Provides a fluent interface
*/
public function setOptions(RsaOptions $options)
{
$this->options = $options;
return $this;
}
/**
* Get options
*
* @return RsaOptions
*/
public function getOptions()
{
return $this->options;
}
/**
* Return last openssl error(s)
*
* @return string
*/
public function getOpensslErrorString()
{
$message = '';
while (false !== ($error = openssl_error_string())) {
$message .= $error . "\n";
}
return trim($message);
}
/**
* Sign with private key
*
* @param string $data
* @return string
* @throws Rsa\Exception\RuntimeException
*/
public function sign($data, ?Rsa\PrivateKey $privateKey = null)
{
$signature = '';
if (null === $privateKey) {
$privateKey = $this->options->getPrivateKey();
}
$result = openssl_sign(
$data,
$signature,
$privateKey->getOpensslKeyResource(),
$this->options->getOpensslSignatureAlgorithm()
);
if (false === $result) {
throw new Exception\RuntimeException(
'Can not generate signature; openssl ' . $this->getOpensslErrorString()
);
}
if ($this->options->getBinaryOutput()) {
return $signature;
}
return base64_encode($signature);
}
/**
* Verify signature with public key
*
* $signature can be encoded in base64 or not. $mode sets how the input must be processed:
* - MODE_AUTO: Check if the $signature is encoded in base64. Not recommended for performance.
* - MODE_BASE64: Decode $signature using base64 algorithm.
* - MODE_RAW: $signature is not encoded.
*
* @see Rsa::MODE_AUTO
* @see Rsa::MODE_BASE64
* @see Rsa::MODE_RAW
*
* @param string $data
* @param string $signature
* @param int $mode Input encoding
* @return bool
* @throws Rsa\Exception\RuntimeException
*/
public function verify(
$data,
$signature,
?Rsa\PublicKey $publicKey = null,
$mode = self::MODE_AUTO
) {
if (null === $publicKey) {
$publicKey = $this->options->getPublicKey();
}
switch ($mode) {
case self::MODE_AUTO:
// check if data is encoded in Base64
$output = base64_decode($signature, true);
if ((false !== $output) && ($signature === base64_encode($output))) {
$signature = $output;
}
break;
case self::MODE_BASE64:
$signature = base64_decode($signature);
break;
case self::MODE_RAW:
default:
break;
}
$result = openssl_verify(
$data,
$signature,
$publicKey->getOpensslKeyResource(),
$this->options->getOpensslSignatureAlgorithm()
);
if (-1 === $result) {
throw new Exception\RuntimeException(
'Can not verify signature; openssl ' . $this->getOpensslErrorString()
);
}
return $result === 1;
}
/**
* Encrypt with private/public key
*
* @param string $data
* @return string
* @throws Rsa\Exception\InvalidArgumentException
*/
public function encrypt($data, ?Rsa\AbstractKey $key = null)
{
if (null === $key) {
$key = $this->options->getPublicKey();
}
if (null === $key) {
throw new Exception\InvalidArgumentException('No key specified for the decryption');
}
$padding = $this->getOptions()->getOpensslPadding();
if (null === $padding) {
$encrypted = $key->encrypt($data);
} else {
$encrypted = $key->encrypt($data, $padding);
}
if ($this->options->getBinaryOutput()) {
return $encrypted;
}
return base64_encode($encrypted);
}
/**
* Decrypt with private/public key
*
* $data can be encoded in base64 or not. $mode sets how the input must be processed:
* - MODE_AUTO: Check if the $signature is encoded in base64. Not recommended for performance.
* - MODE_BASE64: Decode $data using base64 algorithm.
* - MODE_RAW: $data is not encoded.
*
* @see Rsa::MODE_AUTO
* @see Rsa::MODE_BASE64
* @see Rsa::MODE_RAW
*
* @param string $data
* @param int $mode Input encoding
* @return string
* @throws Rsa\Exception\InvalidArgumentException
*/
public function decrypt(
$data,
?Rsa\AbstractKey $key = null,
$mode = self::MODE_AUTO
) {
if (null === $key) {
$key = $this->options->getPrivateKey();
}
if (null === $key) {
throw new Exception\InvalidArgumentException('No key specified for the decryption');
}
switch ($mode) {
case self::MODE_AUTO:
// check if data is encoded in Base64
$output = base64_decode($data, true);
if ((false !== $output) && ($data === base64_encode($output))) {
$data = $output;
}
break;
case self::MODE_BASE64:
$data = base64_decode($data);
break;
case self::MODE_RAW:
default:
break;
}
$padding = $this->getOptions()->getOpensslPadding();
if (null === $padding) {
return $key->decrypt($data);
} else {
return $key->decrypt($data, $padding);
}
}
/**
* Generate new private/public key pair
*
* @see RsaOptions::generateKeys()
*
* @param array $opensslConfig
* @return Rsa Provides a fluent interface
* @throws Rsa\Exception\RuntimeException
*/
public function generateKeys(array $opensslConfig = [])
{
$this->options->generateKeys($opensslConfig);
return $this;
}
}
laminas-crypt/src/PublicKey/RsaOptions.php 0000644 00000013214 15240152650 0014620 0 ustar 00 <?php
namespace Laminas\Crypt\PublicKey;
use Laminas\Crypt\PublicKey\Rsa\Exception;
use Laminas\Stdlib\AbstractOptions;
use function array_replace;
use function constant;
use function defined;
use function openssl_error_string;
use function openssl_pkey_export;
use function openssl_pkey_get_details;
use function openssl_pkey_new;
use function strtolower;
use function strtoupper;
use const OPENSSL_KEYTYPE_RSA;
/**
* RSA instance options
*/
class RsaOptions extends AbstractOptions
{
/** @var Rsa\PrivateKey */
protected $privateKey;
/** @var Rsa\PublicKey */
protected $publicKey;
/** @var string */
protected $hashAlgorithm = 'sha1';
/**
* Signature hash algorithm defined by openss constants
*
* @var int
*/
protected $opensslSignatureAlgorithm;
/** @var string */
protected $passPhrase;
/**
* Output is binary
*
* @var bool
*/
protected $binaryOutput = true;
/**
* OPENSSL padding
*
* @var int|null
*/
protected $opensslPadding;
/**
* Set private key
*
* @return RsaOptions Provides a fluent interface
*/
public function setPrivateKey(Rsa\PrivateKey $key)
{
$this->privateKey = $key;
$this->publicKey = $this->privateKey->getPublicKey();
return $this;
}
/**
* Get private key
*
* @return null|Rsa\PrivateKey
*/
public function getPrivateKey()
{
return $this->privateKey;
}
/**
* Set public key
*
* @return RsaOptions Provides a fluent interface
*/
public function setPublicKey(Rsa\PublicKey $key)
{
$this->publicKey = $key;
return $this;
}
/**
* Get public key
*
* @return null|Rsa\PublicKey
*/
public function getPublicKey()
{
return $this->publicKey;
}
/**
* Set pass phrase
*
* @param string $phrase
* @return RsaOptions Provides a fluent interface
*/
public function setPassPhrase($phrase)
{
$this->passPhrase = (string) $phrase;
return $this;
}
/**
* Get pass phrase
*
* @return string
*/
public function getPassPhrase()
{
return $this->passPhrase;
}
/**
* Set hash algorithm
*
* @param string $hash
* @return RsaOptions Provides a fluent interface
* @throws Rsa\Exception\RuntimeException
* @throws Rsa\Exception\InvalidArgumentException
*/
public function setHashAlgorithm($hash)
{
$hashUpper = strtoupper($hash);
if (! defined('OPENSSL_ALGO_' . $hashUpper)) {
throw new Exception\InvalidArgumentException(
"Hash algorithm '{$hash}' is not supported"
);
}
$this->hashAlgorithm = strtolower($hash);
$this->opensslSignatureAlgorithm = constant('OPENSSL_ALGO_' . $hashUpper);
return $this;
}
/**
* Get hash algorithm
*
* @return string
*/
public function getHashAlgorithm()
{
return $this->hashAlgorithm;
}
/** @return string */
public function getOpensslSignatureAlgorithm()
{
if (! isset($this->opensslSignatureAlgorithm)) {
$this->opensslSignatureAlgorithm = constant('OPENSSL_ALGO_' . strtoupper($this->hashAlgorithm));
}
return $this->opensslSignatureAlgorithm;
}
/**
* Enable/disable the binary output
*
* @param bool $value
* @return RsaOptions Provides a fluent interface
*/
public function setBinaryOutput($value)
{
$this->binaryOutput = (bool) $value;
return $this;
}
/**
* Get the value of binary output
*
* @return bool
*/
public function getBinaryOutput()
{
return $this->binaryOutput;
}
/**
* Get the OPENSSL padding
*
* @return int|null
*/
public function getOpensslPadding()
{
return $this->opensslPadding;
}
/**
* Set the OPENSSL padding
*
* @param int|null $opensslPadding
* @return RsaOptions Provides a fluent interface
*/
public function setOpensslPadding($opensslPadding)
{
$this->opensslPadding = (int) $opensslPadding;
return $this;
}
/**
* Generate new private/public key pair
*
* @param array $opensslConfig
* @return RsaOptions Provides a fluent interface
* @throws Rsa\Exception\RuntimeException
*/
public function generateKeys(array $opensslConfig = [])
{
$opensslConfig = array_replace(
[
'private_key_type' => OPENSSL_KEYTYPE_RSA,
'private_key_bits' => Rsa\PrivateKey::DEFAULT_KEY_SIZE,
'digest_alg' => $this->getHashAlgorithm(),
],
$opensslConfig
);
// generate
$resource = openssl_pkey_new($opensslConfig);
if (false === $resource) {
throw new Exception\RuntimeException(
'Can not generate keys; openssl ' . openssl_error_string()
);
}
// export key
$passPhrase = $this->getPassPhrase();
$result = openssl_pkey_export($resource, $private, $passPhrase, $opensslConfig);
if (false === $result) {
throw new Exception\RuntimeException(
'Can not export key; openssl ' . openssl_error_string()
);
}
$details = openssl_pkey_get_details($resource);
$this->privateKey = new Rsa\PrivateKey($private, $passPhrase);
$this->publicKey = new Rsa\PublicKey($details['key']);
return $this;
}
}
laminas-crypt/src/PublicKey/DiffieHellman.php 0000644 00000033234 15240152650 0015212 0 ustar 00 <?php
namespace Laminas\Crypt\PublicKey;
use Laminas\Crypt\Exception;
use Laminas\Crypt\Exception\InvalidArgumentException;
use Laminas\Crypt\Exception\RuntimeException;
use Laminas\Math;
use Laminas\Math\BigInteger\Adapter\AdapterInterface;
use function function_exists;
use function mb_strlen;
use function openssl_dh_compute_key;
use function openssl_error_string;
use function openssl_pkey_get_details;
use function openssl_pkey_new;
use function preg_match;
use const OPENSSL_KEYTYPE_DH;
use const PHP_VERSION_ID;
/**
* PHP implementation of the Diffie-Hellman public key encryption algorithm.
* Allows two unassociated parties to establish a joint shared secret key
* to be used in encrypting subsequent communications.
*/
class DiffieHellman
{
public const DEFAULT_KEY_SIZE = 2048;
/**
* Key formats
*/
public const FORMAT_BINARY = 'binary';
public const FORMAT_NUMBER = 'number';
public const FORMAT_BTWOC = 'btwoc';
/**
* Static flag to select whether to use PHP5.3's openssl extension
* if available.
*
* @var bool
*/
public static $useOpenssl = true;
/**
* Default large prime number; required by the algorithm.
*
* @var string
*/
private $prime;
/**
* The default generator number. This number must be greater than 0 but
* less than the prime number set.
*
* @var string
*/
private $generator;
/**
* A private number set by the local user. It's optional and will
* be generated if not set.
*
* @var string
*/
private $privateKey;
/**
* BigInteger support object courtesy of Laminas\Math
*
* @var AdapterInterface
*/
private $math;
/**
* The public key generated by this instance after calling generateKeys().
*
* @var string
*/
private $publicKey;
/**
* The shared secret key resulting from a completed Diffie Hellman
* exchange
*
* @var string
*/
private $secretKey;
/** @var resource */
protected $opensslKeyResource;
/**
* Constructor; if set construct the object using the parameter array to
* set values for Prime, Generator and Private.
* If a Private Key is not set, one will be generated at random.
*
* @param string $prime
* @param string $generator
* @param string $privateKey
* @param string $privateKeyFormat
*/
public function __construct($prime, $generator, $privateKey = null, $privateKeyFormat = self::FORMAT_NUMBER)
{
// set up BigInteger adapter
$this->math = Math\BigInteger\BigInteger::factory();
$this->setPrime($prime);
$this->setGenerator($generator);
if ($privateKey !== null) {
$this->setPrivateKey($privateKey, $privateKeyFormat);
}
}
/**
* Set whether to use openssl extension
*
* @static
* @param bool $flag
*/
public static function useOpensslExtension($flag = true)
{
static::$useOpenssl = (bool) $flag;
}
/**
* Generate own public key. If a private number has not already been set,
* one will be generated at this stage.
*
* @return DiffieHellman Provides a fluent interface
* @throws RuntimeException
*/
public function generateKeys()
{
if (function_exists('openssl_dh_compute_key') && static::$useOpenssl !== false) {
$details = [
'p' => $this->convert($this->getPrime(), self::FORMAT_NUMBER, self::FORMAT_BINARY),
'g' => $this->convert($this->getGenerator(), self::FORMAT_NUMBER, self::FORMAT_BINARY),
];
// the priv_key parameter is allowed only for PHP < 7.1
// @see https://bugs.php.net/bug.php?id=73478
if ($this->hasPrivateKey() && PHP_VERSION_ID < 70100) {
$details['priv_key'] = $this->convert(
$this->privateKey,
self::FORMAT_NUMBER,
self::FORMAT_BINARY
);
$opensslKeyResource = openssl_pkey_new(['dh' => $details]);
} else {
$opensslKeyResource = openssl_pkey_new([
'dh' => $details,
'private_key_bits' => self::DEFAULT_KEY_SIZE,
'private_key_type' => OPENSSL_KEYTYPE_DH,
]);
}
if (false === $opensslKeyResource) {
throw new Exception\RuntimeException(
'Can not generate new key; openssl ' . openssl_error_string()
);
}
$data = openssl_pkey_get_details($opensslKeyResource);
$this->setPrivateKey($data['dh']['priv_key'], self::FORMAT_BINARY);
$this->setPublicKey($data['dh']['pub_key'], self::FORMAT_BINARY);
$this->opensslKeyResource = $opensslKeyResource;
} else {
// Private key is lazy generated in the absence of ext/openssl
$publicKey = $this->math->powmod($this->getGenerator(), $this->getPrivateKey(), $this->getPrime());
$this->setPublicKey($publicKey);
}
return $this;
}
/**
* Setter for the value of the public number
*
* @param string $number
* @param string $format
* @return DiffieHellman Provides a fluent interface
* @throws InvalidArgumentException
*/
public function setPublicKey($number, $format = self::FORMAT_NUMBER)
{
$number = $this->convert($number, $format, self::FORMAT_NUMBER);
if (! preg_match('/^\d+$/', $number)) {
throw new Exception\InvalidArgumentException('Invalid parameter; not a positive natural number');
}
$this->publicKey = (string) $number;
return $this;
}
/**
* Returns own public key for communication to the second party to this transaction
*
* @param string $format
* @return string
* @throws InvalidArgumentException
*/
public function getPublicKey($format = self::FORMAT_NUMBER)
{
if ($this->publicKey === null) {
throw new Exception\InvalidArgumentException(
'A public key has not yet been generated using a prior call to generateKeys()'
);
}
return $this->convert($this->publicKey, self::FORMAT_NUMBER, $format);
}
/**
* Compute the shared secret key based on the public key received from the
* the second party to this transaction. This should agree to the secret
* key the second party computes on our own public key.
* Once in agreement, the key is known to only to both parties.
* By default, the function expects the public key to be in binary form
* which is the typical format when being transmitted.
*
* If you need the binary form of the shared secret key, call
* getSharedSecretKey() with the optional parameter for Binary output.
*
* @param string $publicKey
* @param string $publicKeyFormat
* @param string $secretKeyFormat
* @return string
* @throws InvalidArgumentException
* @throws RuntimeException
*/
public function computeSecretKey(
$publicKey,
$publicKeyFormat = self::FORMAT_NUMBER,
$secretKeyFormat = self::FORMAT_NUMBER
) {
if (function_exists('openssl_dh_compute_key') && static::$useOpenssl !== false) {
$publicKey = $this->convert($publicKey, $publicKeyFormat, self::FORMAT_BINARY);
$secretKey = openssl_dh_compute_key($publicKey, $this->opensslKeyResource);
if (false === $secretKey) {
throw new Exception\RuntimeException(
'Can not compute key; openssl ' . openssl_error_string()
);
}
$this->secretKey = $this->convert($secretKey, self::FORMAT_BINARY, self::FORMAT_NUMBER);
} else {
$publicKey = $this->convert($publicKey, $publicKeyFormat, self::FORMAT_NUMBER);
if (! preg_match('/^\d+$/', $publicKey)) {
throw new Exception\InvalidArgumentException(
'Invalid parameter; not a positive natural number'
);
}
$this->secretKey = $this->math->powmod($publicKey, $this->getPrivateKey(), $this->getPrime());
}
return $this->getSharedSecretKey($secretKeyFormat);
}
/**
* Return the computed shared secret key from the DiffieHellman transaction
*
* @param string $format
* @return string
* @throws InvalidArgumentException
*/
public function getSharedSecretKey($format = self::FORMAT_NUMBER)
{
if (! isset($this->secretKey)) {
throw new Exception\InvalidArgumentException(
'A secret key has not yet been computed; call computeSecretKey() first'
);
}
return $this->convert($this->secretKey, self::FORMAT_NUMBER, $format);
}
/**
* Setter for the value of the prime number
*
* @param string $number
* @return DiffieHellman Provides a fluent interface
* @throws InvalidArgumentException
*/
public function setPrime($number)
{
if (! preg_match('/^\d+$/', $number) || $number < 11) {
throw new Exception\InvalidArgumentException(
'Invalid parameter; not a positive natural number or too small: '
. 'should be a large natural number prime'
);
}
$this->prime = (string) $number;
return $this;
}
/**
* Getter for the value of the prime number
*
* @param string $format
* @return string
* @throws InvalidArgumentException
*/
public function getPrime($format = self::FORMAT_NUMBER)
{
if (! isset($this->prime)) {
throw new Exception\InvalidArgumentException('No prime number has been set');
}
return $this->convert($this->prime, self::FORMAT_NUMBER, $format);
}
/**
* Setter for the value of the generator number
*
* @param string $number
* @return DiffieHellman Provides a fluent interface
* @throws InvalidArgumentException
*/
public function setGenerator($number)
{
if (! preg_match('/^\d+$/', $number) || $number < 2) {
throw new Exception\InvalidArgumentException(
'Invalid parameter; not a positive natural number greater than 1'
);
}
$this->generator = (string) $number;
return $this;
}
/**
* Getter for the value of the generator number
*
* @param string $format
* @return string
* @throws InvalidArgumentException
*/
public function getGenerator($format = self::FORMAT_NUMBER)
{
if (! isset($this->generator)) {
throw new Exception\InvalidArgumentException('No generator number has been set');
}
return $this->convert($this->generator, self::FORMAT_NUMBER, $format);
}
/**
* Setter for the value of the private number
*
* @param string $number
* @param string $format
* @return DiffieHellman Provides a fluent interface
* @throws InvalidArgumentException
*/
public function setPrivateKey($number, $format = self::FORMAT_NUMBER)
{
$number = $this->convert($number, $format, self::FORMAT_NUMBER);
if (! preg_match('/^\d+$/', $number)) {
throw new Exception\InvalidArgumentException('Invalid parameter; not a positive natural number');
}
$this->privateKey = (string) $number;
return $this;
}
/**
* Getter for the value of the private number
*
* @param string $format
* @return string
*/
public function getPrivateKey($format = self::FORMAT_NUMBER)
{
if (! $this->hasPrivateKey()) {
$this->setPrivateKey($this->generatePrivateKey(), self::FORMAT_BINARY);
}
return $this->convert($this->privateKey, self::FORMAT_NUMBER, $format);
}
/**
* Check whether a private key currently exists.
*
* @return bool
*/
public function hasPrivateKey()
{
return isset($this->privateKey);
}
/**
* Convert number between formats
*
* @param string $number
* @param string $inputFormat
* @param string $outputFormat
* @return string
*/
protected function convert($number, $inputFormat = self::FORMAT_NUMBER, $outputFormat = self::FORMAT_BINARY)
{
if ($inputFormat === $outputFormat) {
return $number;
}
// convert to number
switch ($inputFormat) {
case self::FORMAT_BINARY:
case self::FORMAT_BTWOC:
$number = $this->math->binToInt($number);
break;
case self::FORMAT_NUMBER:
default:
// do nothing
break;
}
// convert to output format
switch ($outputFormat) {
case self::FORMAT_BINARY:
return $this->math->intToBin($number);
case self::FORMAT_BTWOC:
return $this->math->intToBin($number, true);
case self::FORMAT_NUMBER:
default:
return $number;
}
}
/**
* In the event a private number/key has not been set by the user,
* or generated by ext/openssl, a best attempt will be made to
* generate a random key. Having a random number generator installed
* on linux/bsd is highly recommended! The alternative is not recommended
* for production unless without any other option.
*
* @return string
*/
protected function generatePrivateKey()
{
return Math\Rand::getBytes(mb_strlen($this->getPrime(), '8bit'));
}
}
laminas-crypt/src/PublicKey/Rsa/Exception/InvalidArgumentException.php 0000644 00000000351 15240152650 0022150 0 ustar 00 <?php
namespace Laminas\Crypt\PublicKey\Rsa\Exception;
use Laminas\Crypt\Exception;
/**
* Invalid argument exception
*/
class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface
{
}
laminas-crypt/src/PublicKey/Rsa/Exception/ExceptionInterface.php 0000644 00000000252 15240152650 0020757 0 ustar 00 <?php
namespace Laminas\Crypt\PublicKey\Rsa\Exception;
use Laminas\Crypt\Exception\ExceptionInterface as Exception;
interface ExceptionInterface extends Exception
{
}
laminas-crypt/src/PublicKey/Rsa/Exception/RuntimeException.php 0000644 00000000331 15240152650 0020500 0 ustar 00 <?php
namespace Laminas\Crypt\PublicKey\Rsa\Exception;
use Laminas\Crypt\Exception;
/**
* Runtime argument exception
*/
class RuntimeException extends Exception\RuntimeException implements ExceptionInterface
{
}
laminas-crypt/src/PublicKey/Rsa/PrivateKey.php 0000644 00000010055 15240152650 0015327 0 ustar 00 <?php
namespace Laminas\Crypt\PublicKey\Rsa;
use function file_get_contents;
use function is_readable;
use function is_string;
use function openssl_error_string;
use function openssl_pkey_get_details;
use function openssl_pkey_get_private;
use function openssl_private_decrypt;
use function openssl_private_encrypt;
use const OPENSSL_PKCS1_OAEP_PADDING;
use const OPENSSL_PKCS1_PADDING;
/**
* RSA private key
*/
class PrivateKey extends AbstractKey
{
/**
* Public key
*
* @var PublicKey
*/
protected $publicKey;
/**
* Create private key instance from PEM formatted key file
*
* @param string $pemFile
* @param string|null $passPhrase
* @return PrivateKey
* @throws Exception\InvalidArgumentException
*/
public static function fromFile($pemFile, $passPhrase = null)
{
if (! is_readable($pemFile)) {
throw new Exception\InvalidArgumentException(
"PEM file '{$pemFile}' is not readable"
);
}
return new static(file_get_contents($pemFile), $passPhrase);
}
/**
* Constructor
*
* @param string $pemString
* @param string $passPhrase
* @throws Exception\RuntimeException
*/
public function __construct($pemString, $passPhrase = null)
{
$result = openssl_pkey_get_private($pemString, $passPhrase);
if (false === $result) {
throw new Exception\RuntimeException(
'Unable to load private key; openssl ' . openssl_error_string()
);
}
$this->pemString = $pemString;
$this->opensslKeyResource = $result;
$this->details = openssl_pkey_get_details($this->opensslKeyResource);
}
/**
* Get the public key
*
* @return PublicKey
*/
public function getPublicKey()
{
if ($this->publicKey === null) {
$this->publicKey = new PublicKey($this->details['key']);
}
return $this->publicKey;
}
/**
* Encrypt using this key
*
* @param string $data
* @param integer $padding
* @return string
* @throws Exception\RuntimeException
* @throws Exception\InvalidArgumentException
*/
public function encrypt($data, $padding = OPENSSL_PKCS1_PADDING)
{
if (empty($data)) {
throw new Exception\InvalidArgumentException('The data to encrypt cannot be empty');
}
$encrypted = '';
$result = openssl_private_encrypt($data, $encrypted, $this->getOpensslKeyResource(), $padding);
if (false === $result) {
throw new Exception\RuntimeException(
'Can not encrypt; openssl ' . openssl_error_string()
);
}
return $encrypted;
}
/**
* Decrypt using this key
*
* Starting in 2.4.9/2.5.2, we changed the default padding to
* OPENSSL_PKCS1_OAEP_PADDING to prevent Bleichenbacher's chosen-ciphertext
* attack.
*
* @see http://archiv.infsec.ethz.ch/education/fs08/secsem/bleichenbacher98.pdf
*
* @param string $data
* @param integer $padding
* @return string
* @throws Exception\RuntimeException
* @throws Exception\InvalidArgumentException
*/
public function decrypt($data, $padding = OPENSSL_PKCS1_OAEP_PADDING)
{
if (! is_string($data)) {
throw new Exception\InvalidArgumentException('The data to decrypt must be a string');
}
if ('' === $data) {
throw new Exception\InvalidArgumentException('The data to decrypt cannot be empty');
}
$decrypted = '';
$result = openssl_private_decrypt($data, $decrypted, $this->getOpensslKeyResource(), $padding);
if (false === $result) {
throw new Exception\RuntimeException(
'Can not decrypt; openssl ' . openssl_error_string()
);
}
return $decrypted;
}
/**
* @return string
*/
public function toString()
{
return $this->pemString;
}
}
laminas-crypt/src/PublicKey/Rsa/PublicKey.php 0000644 00000011020 15240152650 0015124 0 ustar 00 <?php
namespace Laminas\Crypt\PublicKey\Rsa;
use function file_get_contents;
use function is_readable;
use function is_string;
use function openssl_error_string;
use function openssl_pkey_get_details;
use function openssl_pkey_get_public;
use function openssl_public_decrypt;
use function openssl_public_encrypt;
use function strpos;
use const OPENSSL_PKCS1_OAEP_PADDING;
use const OPENSSL_PKCS1_PADDING;
/**
* RSA public key
*/
class PublicKey extends AbstractKey
{
public const CERT_START = '-----BEGIN CERTIFICATE-----';
/** @var string */
protected $certificateString;
/**
* Create public key instance public key from PEM formatted key file
* or X.509 certificate file
*
* @param string $pemOrCertificateFile
* @return PublicKey
* @throws Exception\InvalidArgumentException
*/
public static function fromFile($pemOrCertificateFile)
{
if (! is_readable($pemOrCertificateFile)) {
throw new Exception\InvalidArgumentException(
"File '{$pemOrCertificateFile}' is not readable"
);
}
return new static(file_get_contents($pemOrCertificateFile));
}
/**
* Construct public key with PEM formatted string or X.509 certificate
*
* @param string $pemStringOrCertificate
* @throws Exception\RuntimeException
*/
public function __construct($pemStringOrCertificate)
{
$result = openssl_pkey_get_public($pemStringOrCertificate);
if (false === $result) {
throw new Exception\RuntimeException(
'Unable to load public key; openssl ' . openssl_error_string()
);
}
if (strpos($pemStringOrCertificate, self::CERT_START) !== false) {
$this->certificateString = $pemStringOrCertificate;
} else {
$this->pemString = $pemStringOrCertificate;
}
$this->opensslKeyResource = $result;
$this->details = openssl_pkey_get_details($this->opensslKeyResource);
}
/**
* Encrypt using this key
*
* Starting in 2.4.9/2.5.2, we changed the default padding to
* OPENSSL_PKCS1_OAEP_PADDING to prevent Bleichenbacher's chosen-ciphertext
* attack.
*
* @see http://archiv.infsec.ethz.ch/education/fs08/secsem/bleichenbacher98.pdf
*
* @param string $data
* @param string $padding
* @throws Exception\InvalidArgumentException
* @throws Exception\RuntimeException
* @return string
*/
public function encrypt($data, $padding = OPENSSL_PKCS1_OAEP_PADDING)
{
if (empty($data)) {
throw new Exception\InvalidArgumentException('The data to encrypt cannot be empty');
}
$encrypted = '';
$result = openssl_public_encrypt($data, $encrypted, $this->getOpensslKeyResource(), $padding);
if (false === $result) {
throw new Exception\RuntimeException(
'Can not encrypt; openssl ' . openssl_error_string()
);
}
return $encrypted;
}
/**
* Decrypt using this key
*
* @param string $data
* @param string $padding
* @throws Exception\InvalidArgumentException
* @throws Exception\RuntimeException
* @return string
*/
public function decrypt($data, $padding = OPENSSL_PKCS1_PADDING)
{
if (! is_string($data)) {
throw new Exception\InvalidArgumentException('The data to decrypt must be a string');
}
if ('' === $data) {
throw new Exception\InvalidArgumentException('The data to decrypt cannot be empty');
}
$decrypted = '';
$result = openssl_public_decrypt($data, $decrypted, $this->getOpensslKeyResource(), $padding);
if (false === $result) {
throw new Exception\RuntimeException(
'Can not decrypt; openssl ' . openssl_error_string()
);
}
return $decrypted;
}
/**
* Get certificate string
*
* @return string
*/
public function getCertificate()
{
return $this->certificateString;
}
/**
* To string
*
* @return string
* @throws Exception\RuntimeException
*/
public function toString()
{
if (! empty($this->certificateString)) {
return $this->certificateString;
} elseif (! empty($this->pemString)) {
return $this->pemString;
}
throw new Exception\RuntimeException('No public key string representation is available');
}
}
laminas-crypt/src/PublicKey/Rsa/AbstractKey.php 0000644 00000002502 15240152650 0015456 0 ustar 00 <?php
namespace Laminas\Crypt\PublicKey\Rsa;
abstract class AbstractKey
{
public const DEFAULT_KEY_SIZE = 2048;
/**
* PEM formatted key
*
* @var string
*/
protected $pemString;
/**
* Key Resource
*
* @var resource
*/
protected $opensslKeyResource;
/**
* Openssl details array
*
* @var array
*/
protected $details = [];
/**
* Get key size in bits
*
* @return int
*/
public function getSize()
{
return $this->details['bits'];
}
/**
* Retrieve openssl key resource
*
* @return resource
*/
public function getOpensslKeyResource()
{
return $this->opensslKeyResource;
}
/**
* Encrypt using this key
*
* @abstract
* @param string $data
* @return string
*/
abstract public function encrypt($data);
/**
* Decrypt using this key
*
* @abstract
* @param string $data
* @return string
*/
abstract public function decrypt($data);
/**
* Get string representation of this key
*
* @abstract
* @return string
*/
abstract public function toString();
/**
* @return string
*/
public function __toString()
{
return $this->toString();
}
}
laminas-crypt/README.md 0000644 00000010637 15240152650 0010615 0 ustar 00 # laminas-crypt
> ## 🇷🇺 Русским гражданам
>
> Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм.
>
> У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую.
>
> Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!"
>
> ## 🇺🇸 To Citizens of Russia
>
> We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism.
>
> One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences.
>
> You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!"
> This package is considered feature-complete, and is now in **security-only** maintenance mode, following a [decision by the Technical Steering Committee](https://github.com/laminas/technical-steering-committee/blob/2b55453e172a1b8c9c4c212be7cf7e7a58b9352c/meetings/minutes/2020-08-03-TSC-Minutes.md#vote-on-components-to-mark-as-security-only).
> If you have a security issue, please [follow our security reporting guidelines](https://getlaminas.org/security/).
> If you wish to take on the role of maintainer, please [nominate yourself](https://github.com/laminas/technical-steering-committee/issues/new?assignees=&labels=Nomination&template=Maintainer_Nomination.md&title=%5BNOMINATION%5D%5BMAINTAINER%5D%3A+%7Bname+of+person+being+nominated%7D)
[](https://github.com/laminas/laminas-crypt/actions?query=workflow%3A"Continuous+Integration")
`Laminas\Crypt` provides support of some cryptographic tools.
Some of the available features are:
- encrypt-then-authenticate using symmetric ciphers (the authentication step
is provided using HMAC);
- encrypt/decrypt using symmetric and public key algorithm (e.g. RSA algorithm);
- encrypt/decrypt using hybrid mode (OpenPGP like);
- generate digital sign using public key algorithm (e.g. RSA algorithm);
- key exchange using the Diffie-Hellman method;
- key derivation function (e.g. using PBKDF2 algorithm);
- secure password hash (e.g. using Bcrypt algorithm);
- generate Hash values;
- generate HMAC values;
The main scope of this component is to offer an easy and secure way to protect
and authenticate sensitive data in PHP.
- File issues at https://github.com/laminas/laminas-crypt/issues
- Documentation is at https://docs.laminas.dev/laminas-crypt
laminas-crypt/composer.json 0000644 00000003575 15240152650 0012063 0 ustar 00 {
"name": "laminas/laminas-crypt",
"description": "Strong cryptography tools and password hashing",
"license": "BSD-3-Clause",
"keywords": [
"laminas",
"crypt"
],
"homepage": "https://laminas.dev",
"support": {
"docs": "https://docs.laminas.dev/laminas-crypt/",
"issues": "https://github.com/laminas/laminas-crypt/issues",
"source": "https://github.com/laminas/laminas-crypt",
"rss": "https://github.com/laminas/laminas-crypt/releases.atom",
"chat": "https://laminas.dev/chat",
"forum": "https://discourse.laminas.dev"
},
"config": {
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
},
"platform": {
"php": "8.0.99"
}
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"ext-mbstring": "*",
"laminas/laminas-math": "^3.4",
"laminas/laminas-servicemanager": "^3.11.2",
"laminas/laminas-stdlib": "^3.6",
"psr/container": "^1.1"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"phpunit/phpunit": "^9.5.25"
},
"suggest": {
"ext-openssl": "Required for most features of Laminas\\Crypt"
},
"autoload": {
"psr-4": {
"Laminas\\Crypt\\": "src/"
}
},
"autoload-dev": {
"files": [
"test/_autoload.php"
],
"psr-4": {
"LaminasTest\\Crypt\\": "test/"
}
},
"scripts": {
"check": [
"@cs-check",
"@test"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
},
"conflict": {
"zendframework/zend-crypt": "*"
}
}
laminas-crypt/COPYRIGHT.md 0000644 00000000133 15240152650 0011216 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/)
laminas-crypt/composer.lock 0000644 00000251535 15240152650 0012043 0 ustar 00 {
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "f0226534df10f52ad5be908e00cabdad",
"packages": [
{
"name": "laminas/laminas-math",
"version": "3.6.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-math.git",
"reference": "5770fc632a3614f5526632a8b70f41b65130460e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-math/zipball/5770fc632a3614f5526632a8b70f41b65130460e",
"reference": "5770fc632a3614f5526632a8b70f41b65130460e",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-math": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"phpunit/phpunit": "~9.5.25"
},
"suggest": {
"ext-bcmath": "If using the bcmath functionality",
"ext-gmp": "If using the gmp functionality"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2.x-dev",
"dev-develop": "3.3.x-dev"
}
},
"autoload": {
"psr-4": {
"Laminas\\Math\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Create cryptographically secure pseudo-random numbers, and manage big integers",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"math"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-math/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-math/issues",
"rss": "https://github.com/laminas/laminas-math/releases.atom",
"source": "https://github.com/laminas/laminas-math"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-16T14:22:28+00:00"
},
{
"name": "laminas/laminas-servicemanager",
"version": "3.19.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-servicemanager.git",
"reference": "ed160729bb8721127efdaac799f9a298963345b1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/ed160729bb8721127efdaac799f9a298963345b1",
"reference": "ed160729bb8721127efdaac799f9a298963345b1",
"shasum": ""
},
"require": {
"laminas/laminas-stdlib": "^3.2.1",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"psr/container": "^1.0"
},
"conflict": {
"ext-psr": "*",
"laminas/laminas-code": "<3.3.1",
"zendframework/zend-code": "<3.3.1",
"zendframework/zend-servicemanager": "*"
},
"provide": {
"psr/container-implementation": "^1.0"
},
"replace": {
"container-interop/container-interop": "^1.2.0"
},
"require-dev": {
"composer/package-versions-deprecated": "^1.11.99.5",
"laminas/laminas-coding-standard": "~2.4.0",
"laminas/laminas-container-config-test": "^0.7",
"laminas/laminas-dependency-plugin": "^2.2",
"mikey179/vfsstream": "^1.6.11@alpha",
"ocramius/proxy-manager": "^2.14.1",
"phpbench/phpbench": "^1.2.6",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.28"
},
"suggest": {
"ocramius/proxy-manager": "ProxyManager ^2.1.1 to handle lazy initialization of services"
},
"bin": [
"bin/generate-deps-for-config-factory",
"bin/generate-factory-for-class"
],
"type": "library",
"autoload": {
"files": [
"src/autoload.php"
],
"psr-4": {
"Laminas\\ServiceManager\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Factory-Driven Dependency Injection Container",
"homepage": "https://laminas.dev",
"keywords": [
"PSR-11",
"dependency-injection",
"di",
"dic",
"laminas",
"service-manager",
"servicemanager"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-servicemanager/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-servicemanager/issues",
"rss": "https://github.com/laminas/laminas-servicemanager/releases.atom",
"source": "https://github.com/laminas/laminas-servicemanager"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-10T20:59:22+00:00"
},
{
"name": "laminas/laminas-stdlib",
"version": "3.15.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-stdlib.git",
"reference": "63b66bd4b696f024f42616b9d95cdb10e5109c27"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/63b66bd4b696f024f42616b9d95cdb10e5109c27",
"reference": "63b66bd4b696f024f42616b9d95cdb10e5109c27",
"shasum": ""
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-stdlib": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "^2.4.0",
"phpbench/phpbench": "^1.2.6",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.28"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Stdlib\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "SPL extensions, array utilities, error handlers, and more",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"stdlib"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-stdlib/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-stdlib/issues",
"rss": "https://github.com/laminas/laminas-stdlib/releases.atom",
"source": "https://github.com/laminas/laminas-stdlib"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-10T19:10:24+00:00"
},
{
"name": "psr/container",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
"shasum": ""
},
"require": {
"php": ">=7.4.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
"homepage": "https://github.com/php-fig/container",
"keywords": [
"PSR-11",
"container",
"container-interface",
"container-interop",
"psr"
],
"support": {
"issues": "https://github.com/php-fig/container/issues",
"source": "https://github.com/php-fig/container/tree/1.1.2"
},
"time": "2021-11-05T16:50:12+00:00"
}
],
"packages-dev": [
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
"version": "v0.7.2",
"source": {
"type": "git",
"url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
"phpcompatibility/php-compatibility": "^9.0"
},
"type": "composer-plugin",
"extra": {
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
"Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Franck Nijhof",
"email": "franck.nijhof@dealerdirect.com",
"homepage": "http://www.frenck.nl",
"role": "Developer / IT Manager"
},
{
"name": "Contributors",
"homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
"homepage": "http://www.dealerdirect.com",
"keywords": [
"PHPCodeSniffer",
"PHP_CodeSniffer",
"code quality",
"codesniffer",
"composer",
"installer",
"phpcbf",
"phpcs",
"plugin",
"qa",
"quality",
"standard",
"standards",
"style guide",
"stylecheck",
"tests"
],
"support": {
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
"time": "2022-02-04T12:51:07+00:00"
},
{
"name": "doctrine/instantiator",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9",
"ext-pdo": "*",
"ext-phar": "*",
"phpbench/phpbench": "^0.16 || ^1",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-phpunit": "^1",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"vimeo/psalm": "^4.22"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "https://ocramius.github.io/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://www.doctrine-project.org/projects/instantiator.html",
"keywords": [
"constructor",
"instantiate"
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/1.4.1"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
"type": "tidelift"
}
],
"time": "2022-03-03T08:28:38+00:00"
},
{
"name": "laminas/laminas-coding-standard",
"version": "2.4.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-coding-standard.git",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7",
"php": "^7.4 || ^8.0",
"slevomat/coding-standard": "^7.0",
"squizlabs/php_codesniffer": "^3.6",
"webimpress/coding-standard": "^1.2"
},
"conflict": {
"phpstan/phpdoc-parser": ">=1.6.0"
},
"type": "phpcodesniffer-standard",
"autoload": {
"psr-4": {
"LaminasCodingStandard\\": "src/LaminasCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Laminas Coding Standard",
"homepage": "https://laminas.dev",
"keywords": [
"Coding Standard",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-coding-standard/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-coding-standard/issues",
"rss": "https://github.com/laminas/laminas-coding-standard/releases.atom",
"source": "https://github.com/laminas/laminas-coding-standard"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-08-24T17:45:47+00:00"
},
{
"name": "myclabs/deep-copy",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"conflict": {
"doctrine/collections": "<1.6.8",
"doctrine/common": "<2.13.3 || >=3,<3.2.2"
},
"require-dev": {
"doctrine/collections": "^1.6.8",
"doctrine/common": "^2.13.3 || ^3.2.2",
"phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
},
"type": "library",
"autoload": {
"files": [
"src/DeepCopy/deep_copy.php"
],
"psr-4": {
"DeepCopy\\": "src/DeepCopy/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Create deep copies (clones) of your objects",
"keywords": [
"clone",
"copy",
"duplicate",
"object",
"object graph"
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
},
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
"type": "tidelift"
}
],
"time": "2022-03-03T13:19:32+00:00"
},
{
"name": "nikic/php-parser",
"version": "v4.15.1",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=7.0"
},
"require-dev": {
"ircmaxell/php-yacc": "^0.0.7",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
},
"bin": [
"bin/php-parse"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.9-dev"
}
},
"autoload": {
"psr-4": {
"PhpParser\\": "lib/PhpParser"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov"
}
],
"description": "A PHP parser written in PHP",
"keywords": [
"parser",
"php"
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1"
},
"time": "2022-09-04T07:30:47+00:00"
},
{
"name": "phar-io/manifest",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-phar": "*",
"ext-xmlwriter": "*",
"phar-io/version": "^3.0.1",
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
"support": {
"issues": "https://github.com/phar-io/manifest/issues",
"source": "https://github.com/phar-io/manifest/tree/2.0.3"
},
"time": "2021-07-20T11:28:43+00:00"
},
{
"name": "phar-io/version",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/phar-io/version.git",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Library for handling version information and constraints",
"support": {
"issues": "https://github.com/phar-io/version/issues",
"source": "https://github.com/phar-io/version/tree/3.2.1"
},
"time": "2022-02-21T01:04:05+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "981cc368a216c988e862a75e526b6076987d1b50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/981cc368a216c988e862a75e526b6076987d1b50",
"reference": "981cc368a216c988e862a75e526b6076987d1b50",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.5.1"
},
"time": "2022-05-05T11:32:40+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.17",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
"nikic/php-parser": "^4.14",
"php": ">=7.3",
"phpunit/php-file-iterator": "^3.0.3",
"phpunit/php-text-template": "^2.0.2",
"sebastian/code-unit-reverse-lookup": "^2.0.2",
"sebastian/complexity": "^2.0",
"sebastian/environment": "^5.1.2",
"sebastian/lines-of-code": "^1.0.3",
"sebastian/version": "^3.0.1",
"theseer/tokenizer": "^1.2.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcov": "*",
"ext-xdebug": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-08-30T12:24:04+00:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "3.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2021-12-02T12:48:52+00:00"
},
{
"name": "phpunit/php-invoker",
"version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-invoker.git",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"ext-pcntl": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcntl": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Invoke callables with a timeout",
"homepage": "https://github.com/sebastianbergmann/php-invoker/",
"keywords": [
"process"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-invoker/issues",
"source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:58:55+00:00"
},
{
"name": "phpunit/php-text-template",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
"source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T05:33:50+00:00"
},
{
"name": "phpunit/php-timer",
"version": "5.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-timer/issues",
"source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:16:10+00:00"
},
{
"name": "phpunit/phpunit",
"version": "9.5.25",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
"reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.3.1",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
"myclabs/deep-copy": "^1.10.1",
"phar-io/manifest": "^2.0.3",
"phar-io/version": "^3.0.2",
"php": ">=7.3",
"phpunit/php-code-coverage": "^9.2.13",
"phpunit/php-file-iterator": "^3.0.5",
"phpunit/php-invoker": "^3.1.1",
"phpunit/php-text-template": "^2.0.3",
"phpunit/php-timer": "^5.0.2",
"sebastian/cli-parser": "^1.0.1",
"sebastian/code-unit": "^1.0.6",
"sebastian/comparator": "^4.0.8",
"sebastian/diff": "^4.0.3",
"sebastian/environment": "^5.1.3",
"sebastian/exporter": "^4.0.5",
"sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3",
"sebastian/type": "^3.2",
"sebastian/version": "^3.0.2"
},
"suggest": {
"ext-soap": "*",
"ext-xdebug": "*"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.5-dev"
}
},
"autoload": {
"files": [
"src/Framework/Assert/Functions.php"
],
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.25"
},
"funding": [
{
"url": "https://phpunit.de/sponsors.html",
"type": "custom"
},
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
"type": "tidelift"
}
],
"time": "2022-09-25T03:44:45+00:00"
},
{
"name": "sebastian/cli-parser",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for parsing CLI options",
"homepage": "https://github.com/sebastianbergmann/cli-parser",
"support": {
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
"source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:08:49+00:00"
},
{
"name": "sebastian/code-unit",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit.git",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the PHP code units",
"homepage": "https://github.com/sebastianbergmann/code-unit",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit/issues",
"source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:08:54+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
"source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:30:19+00:00"
},
{
"name": "sebastian/comparator",
"version": "4.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/diff": "^4.0",
"sebastian/exporter": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "https://github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
"source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T12:41:17+00:00"
},
{
"name": "sebastian/complexity",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.7",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for calculating the complexity of PHP code units",
"homepage": "https://github.com/sebastianbergmann/complexity",
"support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues",
"source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T15:52:27+00:00"
},
{
"name": "sebastian/diff",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3",
"symfony/process": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
}
],
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
"diff",
"udiff",
"unidiff",
"unified diff"
],
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:10:38+00:00"
},
{
"name": "sebastian/environment",
"version": "5.1.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-posix": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"support": {
"issues": "https://github.com/sebastianbergmann/environment/issues",
"source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-04-03T09:37:03+00:00"
},
{
"name": "sebastian/exporter",
"version": "4.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-mbstring": "*",
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "https://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T06:03:37+00:00"
},
{
"name": "sebastian/global-state",
"version": "5.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-dom": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-uopz": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-02-14T08:28:10+00:00"
},
{
"name": "sebastian/lines-of-code",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.6",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for counting the lines of code in PHP source code",
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
"support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-11-28T06:42:11+00:00"
},
{
"name": "sebastian/object-enumerator",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
"source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:12:34+00:00"
},
{
"name": "sebastian/object-reflector",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Allows reflection of object attributes, including inherited and non-public ones",
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-reflector/issues",
"source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:14:26+00:00"
},
{
"name": "sebastian/recursion-context",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
"source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:17:30+00:00"
},
{
"name": "sebastian/resource-operations",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"support": {
"issues": "https://github.com/sebastianbergmann/resource-operations/issues",
"source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:45:17+00:00"
},
{
"name": "sebastian/type",
"version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the types of the PHP type system",
"homepage": "https://github.com/sebastianbergmann/type",
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
"source": "https://github.com/sebastianbergmann/type/tree/3.2.0"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-12T14:47:03+00:00"
},
{
"name": "sebastian/version",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "c6c1022351a901512170118436c764e473f6de8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
"reference": "c6c1022351a901512170118436c764e473f6de8c",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"support": {
"issues": "https://github.com/sebastianbergmann/version/issues",
"source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:39:44+00:00"
},
{
"name": "slevomat/coding-standard",
"version": "7.2.1",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
"php": "^7.2 || ^8.0",
"phpstan/phpdoc-parser": "^1.5.1",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phing/phing": "2.17.3",
"php-parallel-lint/php-parallel-lint": "1.3.2",
"phpstan/phpstan": "1.4.10|1.7.1",
"phpstan/phpstan-deprecation-rules": "1.0.0",
"phpstan/phpstan-phpunit": "1.0.0|1.1.1",
"phpstan/phpstan-strict-rules": "1.2.3",
"phpunit/phpunit": "7.5.20|8.5.21|9.5.20"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "7.x-dev"
}
},
"autoload": {
"psr-4": {
"SlevomatCodingStandard\\": "SlevomatCodingStandard"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
"source": "https://github.com/slevomat/coding-standard/tree/7.2.1"
},
"funding": [
{
"url": "https://github.com/kukulich",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
"type": "tidelift"
}
],
"time": "2022-05-25T10:58:12+00:00"
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.7.1",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"bin/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2022-06-18T07:21:10+00:00"
},
{
"name": "theseer/tokenizer",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
}
],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/1.2.1"
},
"funding": [
{
"url": "https://github.com/theseer",
"type": "github"
}
],
"time": "2021-07-28T10:34:58+00:00"
},
{
"name": "webimpress/coding-standard",
"version": "1.2.4",
"source": {
"type": "git",
"url": "https://github.com/webimpress/coding-standard.git",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webimpress/coding-standard/zipball/cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"shasum": ""
},
"require": {
"php": "^7.3 || ^8.0",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phpunit/phpunit": "^9.5.13"
},
"type": "phpcodesniffer-standard",
"extra": {
"dev-master": "1.2.x-dev",
"dev-develop": "1.3.x-dev"
},
"autoload": {
"psr-4": {
"WebimpressCodingStandard\\": "src/WebimpressCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-2-Clause"
],
"description": "Webimpress Coding Standard",
"keywords": [
"Coding Standard",
"PSR-2",
"phpcs",
"psr-12",
"webimpress"
],
"support": {
"issues": "https://github.com/webimpress/coding-standard/issues",
"source": "https://github.com/webimpress/coding-standard/tree/1.2.4"
},
"funding": [
{
"url": "https://github.com/michalbundyra",
"type": "github"
}
],
"time": "2022-02-15T19:52:12+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"ext-mbstring": "*"
},
"platform-dev": [],
"platform-overrides": {
"php": "8.0.99"
},
"plugin-api-version": "2.2.0"
}
laminas-crypt/phpcs.xml.dist 0000644 00000001337 15240152650 0012134 0 ustar 00 <?xml version="1.0"?>
<ruleset
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/squizlabs/php_codesniffer/phpcs.xsd">
<config name="php_version" value="70300"/>
<arg name="basepath" value="."/>
<arg name="cache" value=".phpcs-cache"/>
<arg name="colors"/>
<arg name="extensions" value="php"/>
<arg name="parallel" value="80"/>
<!-- Show progress -->
<arg value="p"/>
<!-- Paths to check -->
<file>src</file>
<file>test</file>
<!-- Include all rules from Laminas Coding Standard -->
<rule ref="LaminasCodingStandard">
<exclude name="SlevomatCodingStandard.TypeHints.DeclareStrictTypes"/>
</rule>
</ruleset>
laminas-crypt/LICENSE.md 0000644 00000002732 15240152650 0010737 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of Laminas Foundation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
laminas-ldap/psalm-baseline.xml 0000644 00000235016 15240152650 0012533 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="4.27.0@faf106e717c37b8c81721845dba9de3d8deed8ff">
<file src="src/Attribute.php">
<DocblockTypeContradiction occurrences="2">
<code>is_int($value)</code>
<code>is_string($value)</code>
</DocblockTypeContradiction>
<InvalidReturnStatement occurrences="2">
<code>$value->format('U')</code>
<code>Converter\Converter::fromLdapDateTime($value, false)->format('U')</code>
</InvalidReturnStatement>
<InvalidReturnType occurrences="1">
<code>int|null</code>
</InvalidReturnType>
<InvalidScalarArgument occurrences="2">
<code>mt_rand()</code>
<code>mt_rand()</code>
</InvalidScalarArgument>
<MissingReturnType occurrences="2">
<code>setDateTimeAttribute</code>
<code>setPassword</code>
</MissingReturnType>
<MixedArgument occurrences="11">
<code>$data[$attribName]</code>
<code>$data[$attribName]</code>
<code>$data[$attribName]</code>
<code>$data[$attribName]</code>
<code>$data[$attribName][$index]</code>
<code>$resultArray</code>
<code>$resultArray</code>
<code>$v</code>
<code>$v</code>
<code>$values</code>
<code>$values[$i]</code>
</MixedArgument>
<MixedArrayAccess occurrences="2">
<code>$data[$attribName][$index]</code>
<code>$resultArray[$k]</code>
</MixedArrayAccess>
<MixedAssignment occurrences="9">
<code>$resultArray</code>
<code>$retArray[]</code>
<code>$return</code>
<code>$v</code>
<code>$v</code>
<code>$v</code>
<code>$v</code>
<code>$v</code>
<code>$values</code>
</MixedAssignment>
<MixedInferredReturnType occurrences="1">
<code>array|int</code>
</MixedInferredReturnType>
<MixedReturnStatement occurrences="1">
<code>$values</code>
</MixedReturnStatement>
<RedundantConditionGivenDocblockType occurrences="3">
<code>$value !== null</code>
<code>$value !== null</code>
<code>is_int($index)</code>
</RedundantConditionGivenDocblockType>
</file>
<file src="src/Collection.php">
<MixedInferredReturnType occurrences="1">
<code>array|null</code>
</MixedInferredReturnType>
<MixedReturnStatement occurrences="1">
<code>$this->cache[$this->current]</code>
</MixedReturnStatement>
</file>
<file src="src/Collection/DefaultIterator.php">
<InvalidArgument occurrences="1">
<code>$this</code>
</InvalidArgument>
<MissingClosureReturnType occurrences="1">
<code>static fn($a, $b) =></code>
</MissingClosureReturnType>
<MixedArgument occurrences="1">
<code>$entry['resource']</code>
</MixedArgument>
<MixedArgumentTypeCoercion occurrences="1"/>
<MixedArrayAccess occurrences="5">
<code>$a['sortValue']</code>
<code>$b['sortValue']</code>
<code>$entry['resource']</code>
<code>$nextEntry['resource']</code>
<code>$nextEntry['resource']</code>
</MixedArrayAccess>
<MixedArrayAssignment occurrences="1">
<code>$this->entries[$key]['sortValue']</code>
</MixedArrayAssignment>
<MixedArrayOffset occurrences="1">
<code>$entry[$attrName]</code>
</MixedArrayOffset>
<MixedAssignment occurrences="6">
<code>$attrName</code>
<code>$entry</code>
<code>$nextEntry</code>
<code>$nextEntry</code>
<code>$this->current</code>
<code>$this->current</code>
</MixedAssignment>
<PossiblyInvalidFunctionCall occurrences="1">
<code>call_user_func($this->attributeNameTreatment, $name)</code>
</PossiblyInvalidFunctionCall>
<RedundantCastGivenDocblockType occurrences="1">
<code>(int) $attributeNameTreatment</code>
</RedundantCastGivenDocblockType>
<TypeDoesNotContainType occurrences="1">
<code>is_string($attributeNameTreatment) && ! function_exists($attributeNameTreatment)</code>
</TypeDoesNotContainType>
</file>
<file src="src/Converter/Converter.php">
<DocblockTypeContradiction occurrences="1">
<code>is_scalar($value)</code>
</DocblockTypeContradiction>
<InvalidScalarArgument occurrences="8">
<code>$e->getCode()</code>
<code>$time['day']</code>
<code>$time['hour']</code>
<code>$time['minute']</code>
<code>$time['month']</code>
<code>$time['offsethours']</code>
<code>$time['offsetminutes']</code>
<code>$time['second']</code>
</InvalidScalarArgument>
<MixedArgument occurrences="2">
<code>$value</code>
<code>$value</code>
</MixedArgument>
<MixedAssignment occurrences="1">
<code>$v</code>
</MixedAssignment>
<RedundantConditionGivenDocblockType occurrences="1">
<code>is_string($date)</code>
</RedundantConditionGivenDocblockType>
</file>
<file src="src/Dn.php">
<DocblockTypeContradiction occurrences="1">
<code>null === $val</code>
</DocblockTypeContradiction>
<InvalidArgument occurrences="1">
<code>[$key, $value]</code>
</InvalidArgument>
<MissingReturnType occurrences="2">
<code>setCaseFold</code>
<code>setDefaultCaseFold</code>
</MissingReturnType>
<MixedArgument occurrences="6">
<code>$p</code>
<code>$part</code>
<code>$this->dn[$index]</code>
<code>$val</code>
<code>$val</code>
<code>$value</code>
</MixedArgument>
<MixedArgumentTypeCoercion occurrences="1">
<code>$key</code>
</MixedArgumentTypeCoercion>
<MixedArrayOffset occurrences="1">
<code>$multi[$key]</code>
</MixedArrayOffset>
<MixedAssignment occurrences="8">
<code>$key</code>
<code>$multi[$key]</code>
<code>$p</code>
<code>$part</code>
<code>$val</code>
<code>$val</code>
<code>$val</code>
<code>$value</code>
</MixedAssignment>
<MixedInferredReturnType occurrences="2">
<code>array</code>
<code>array</code>
</MixedInferredReturnType>
<MixedReturnStatement occurrences="2">
<code>count($values) === 1 ? $values[0] : $values</code>
<code>count($values) === 1 ? $values[0] : $values</code>
</MixedReturnStatement>
<NullArgument occurrences="2">
<code>null</code>
<code>null</code>
</NullArgument>
<PossiblyInvalidArgument occurrences="1">
<code>$lastKey</code>
</PossiblyInvalidArgument>
<PossiblyNullArgument occurrences="8">
<code>$caseFold</code>
<code>$caseFold</code>
<code>$caseFold</code>
<code>$caseFold</code>
<code>$caseFold</code>
<code>$caseFold</code>
<code>$caseFold</code>
<code>$k</code>
</PossiblyNullArgument>
<PossiblyNullArrayAccess occurrences="4">
<code>$k[$i]</code>
<code>$k[$i]</code>
<code>$v[$i]</code>
<code>$v[$i]</code>
</PossiblyNullArrayAccess>
<RedundantCastGivenDocblockType occurrences="5">
<code>(int) $length</code>
<code>(int) $length</code>
<code>(int) $levelUp</code>
<code>(int) $offset</code>
<code>(string) $dn</code>
</RedundantCastGivenDocblockType>
<RedundantConditionGivenDocblockType occurrences="1">
<code>is_string($dn)</code>
</RedundantConditionGivenDocblockType>
<UnsafeInstantiation occurrences="3">
<code>new static($dn, $caseFold)</code>
<code>new static($dnArray, $caseFold)</code>
<code>new static($newDn, $this->caseFold)</code>
</UnsafeInstantiation>
</file>
<file src="src/ErrorHandler.php">
<DocblockTypeContradiction occurrences="2">
<code>! self::$errorHandler</code>
<code>! self::$errorHandler</code>
</DocblockTypeContradiction>
<InvalidArgument occurrences="1"/>
<UnusedClosureParam occurrences="2">
<code>$errNo</code>
<code>$errString</code>
</UnusedClosureParam>
</file>
<file src="src/Exception/LdapException.php">
<PossiblyNullArgument occurrences="1">
<code>$code</code>
</PossiblyNullArgument>
</file>
<file src="src/Filter.php">
<MissingParamType occurrences="2">
<code>$filter</code>
<code>$filter</code>
</MissingParamType>
<UnsafeInstantiation occurrences="10">
<code>new static($attr, $value, self::TYPE_APPROX, null, null)</code>
<code>new static($attr, $value, self::TYPE_EQUALS, '*', '*')</code>
<code>new static($attr, $value, self::TYPE_EQUALS, '*', null)</code>
<code>new static($attr, $value, self::TYPE_EQUALS, null, '*')</code>
<code>new static($attr, $value, self::TYPE_EQUALS, null, null)</code>
<code>new static($attr, $value, self::TYPE_GREATER, null, null)</code>
<code>new static($attr, $value, self::TYPE_GREATEROREQUAL, null, null)</code>
<code>new static($attr, $value, self::TYPE_LESS, null, null)</code>
<code>new static($attr, $value, self::TYPE_LESSOREQUAL, null, null)</code>
<code>new static($attr, '', self::TYPE_EQUALS, '*', null)</code>
</UnsafeInstantiation>
</file>
<file src="src/Filter/AbstractFilter.php">
<DocblockTypeContradiction occurrences="1">
<code>null === $val</code>
</DocblockTypeContradiction>
<MissingParamType occurrences="2">
<code>$filter</code>
<code>$filter</code>
</MissingParamType>
<MixedArgument occurrences="2">
<code>$val</code>
<code>$value</code>
</MixedArgument>
<MixedAssignment occurrences="2">
<code>$val</code>
<code>$value</code>
</MixedAssignment>
<MixedInferredReturnType occurrences="2">
<code>array</code>
<code>array</code>
</MixedInferredReturnType>
<MixedReturnStatement occurrences="2">
<code>count($values) === 1 ? $values[0] : $values</code>
<code>count($values) === 1 ? $values[0] : $values</code>
</MixedReturnStatement>
</file>
<file src="src/Filter/AbstractLogicalFilter.php">
<MixedAssignment occurrences="2">
<code>$s</code>
<code>$sub</code>
</MixedAssignment>
<MixedMethodCall occurrences="1">
<code>toString</code>
</MixedMethodCall>
<MixedOperand occurrences="1">
<code>$sub->toString()</code>
</MixedOperand>
</file>
<file src="src/Filter/MaskFilter.php">
<MissingParamType occurrences="1">
<code>$value</code>
</MissingParamType>
<MixedArgument occurrences="1">
<code>$args[$i]</code>
</MixedArgument>
</file>
<file src="src/Handler.php">
<MixedArgument occurrences="3">
<code>Connection::class</code>
<code>Result::class</code>
<code>ResultEntry::class</code>
</MixedArgument>
<MixedInferredReturnType occurrences="1">
<code>bool</code>
</MixedInferredReturnType>
<UndefinedClass occurrences="3">
<code>Connection</code>
<code>Result</code>
<code>ResultEntry</code>
</UndefinedClass>
<UndefinedDocblockClass occurrences="1">
<code>class-string<Connection>|class-string<ResultEntry>|class-string<Result></code>
</UndefinedDocblockClass>
</file>
<file src="src/Ldap.php">
<ArgumentTypeCoercion occurrences="1">
<code>$duration * 1000000</code>
</ArgumentTypeCoercion>
<DocblockTypeContradiction occurrences="5">
<code>$accountDomainName === null</code>
<code>$accountDomainNameShort === null</code>
<code>$dname === null</code>
<code>$this->rootDse === null</code>
<code>$this->schema === null</code>
</DocblockTypeContradiction>
<InvalidArgument occurrences="3">
<code>$aname</code>
<code>$aname</code>
<code>$aname</code>
</InvalidArgument>
<InvalidNullableReturnType occurrences="3">
<code>array</code>
<code>array</code>
<code>resource</code>
</InvalidNullableReturnType>
<MissingReturnType occurrences="1">
<code>reconnectSleep</code>
</MissingReturnType>
<MixedArgument occurrences="22">
<code>$c</code>
<code>$c</code>
<code>$c</code>
<code>$collectionClass</code>
<code>$entry[$key]</code>
<code>$entry[$key]</code>
<code>$entry[$key]</code>
<code>$entry[$key]</code>
<code>$host</code>
<code>$message</code>
<code>$password</code>
<code>$password</code>
<code>$this->connectString</code>
<code>$username</code>
<code>$username</code>
<code>$username</code>
<code>$username</code>
<code>$username</code>
<code>$val</code>
<code>$value</code>
<code>$value</code>
<code>array_shift($newDnParts)</code>
</MixedArgument>
<MixedArgumentTypeCoercion occurrences="1">
<code>$errorMessages</code>
</MixedArgumentTypeCoercion>
<MixedArrayAccess occurrences="1">
<code>$this->lastConnectBindParams[$method][$parameter]</code>
</MixedArrayAccess>
<MixedAssignment occurrences="29">
<code>$$key</code>
<code>$accountCanonicalForm</code>
<code>$c</code>
<code>$c</code>
<code>$collectionClass</code>
<code>$err</code>
<code>$errorMessages[]</code>
<code>$host</code>
<code>$message</code>
<code>$networkTimeout</code>
<code>$password</code>
<code>$permittedOptions[$key]</code>
<code>$port</code>
<code>$reverseSort</code>
<code>$this->boundUser</code>
<code>$this->connectString</code>
<code>$useSsl</code>
<code>$useStartTls</code>
<code>$username</code>
<code>$v</code>
<code>$val</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
</MixedAssignment>
<MixedInferredReturnType occurrences="20">
<code>bool</code>
<code>bool</code>
<code>bool</code>
<code>bool</code>
<code>bool</code>
<code>bool</code>
<code>int</code>
<code>int</code>
<code>int</code>
<code>int</code>
<code>int</code>
<code>string</code>
<code>string</code>
<code>string</code>
<code>string</code>
<code>string</code>
<code>string</code>
<code>string</code>
<code>string</code>
<code>string[]|null</code>
</MixedInferredReturnType>
<MixedOperand occurrences="5">
<code>$host</code>
<code>$host</code>
<code>$port</code>
<code>$username</code>
<code>-$err</code>
</MixedOperand>
<MixedReturnStatement occurrences="20">
<code>$accountCanonicalForm</code>
<code>$acct['dn']</code>
<code>$err</code>
<code>$this->options['accountDomainName']</code>
<code>$this->options['accountDomainNameShort']</code>
<code>$this->options['accountFilterFormat']</code>
<code>$this->options['allowEmptyPassword']</code>
<code>$this->options['baseDn']</code>
<code>$this->options['bindRequiresDn']</code>
<code>$this->options['host']</code>
<code>$this->options['networkTimeout']</code>
<code>$this->options['optReferrals']</code>
<code>$this->options['password']</code>
<code>$this->options['port']</code>
<code>$this->options['reconnectAttempts']</code>
<code>$this->options['saslOpts']</code>
<code>$this->options['tryUsernameSplit']</code>
<code>$this->options['useSsl']</code>
<code>$this->options['useStartTls']</code>
<code>$this->options['username']</code>
</MixedReturnStatement>
<NullableReturnStatement occurrences="4">
<code>$acct</code>
<code>$result->getFirst()</code>
<code>$this->resource</code>
<code>null</code>
</NullableReturnStatement>
<PossiblyInvalidArgument occurrences="3">
<code>$filter</code>
<code>$filter</code>
<code>$filter</code>
</PossiblyInvalidArgument>
<PossiblyInvalidCast occurrences="3">
<code>$filter</code>
<code>$filter</code>
<code>$filter</code>
</PossiblyInvalidCast>
<PossiblyInvalidOperand occurrences="1">
<code>$filter</code>
</PossiblyInvalidOperand>
<PossiblyNullArgument occurrences="17">
<code>$attrs</code>
<code>$password</code>
<code>$sasl_authc_id</code>
<code>$sasl_authz_id</code>
<code>$sasl_mech</code>
<code>$sasl_props</code>
<code>$sasl_realm</code>
<code>$this->resource</code>
<code>$this->resource</code>
<code>$this->resource</code>
<code>$this->resource</code>
<code>$this->resource</code>
<code>$this->resource</code>
<code>$this->resource</code>
<code>$this->resource</code>
<code>$this->resource</code>
<code>$username</code>
</PossiblyNullArgument>
<PossiblyUndefinedVariable occurrences="2">
<code>$err</code>
<code>$err</code>
</PossiblyUndefinedVariable>
<PropertyNotSetInConstructor occurrences="2">
<code>$rootDse</code>
<code>$schema</code>
</PropertyNotSetInConstructor>
<RedundantCastGivenDocblockType occurrences="6">
<code>(bool) $alwaysEmulate</code>
<code>(bool) $useSsl</code>
<code>(bool) $useStartTls</code>
<code>(int) $networkTimeout</code>
<code>(int) $port</code>
<code>(string) $collectionClass</code>
</RedundantCastGivenDocblockType>
<RedundantConditionGivenDocblockType occurrences="2">
<code>$sort !== null && is_string($sort)</code>
<code>is_string($sort)</code>
</RedundantConditionGivenDocblockType>
<ReferenceConstraintViolation occurrences="3">
<code>$aname</code>
<code>$dname</code>
<code>return;</code>
</ReferenceConstraintViolation>
<ReservedWord occurrences="1">
<code>null|Exception\LdapException</code>
</ReservedWord>
<UnsafeInstantiation occurrences="1">
<code>new $collectionClass($iterator)</code>
</UnsafeInstantiation>
<UnusedForeachValue occurrences="1">
<code>$val</code>
</UnusedForeachValue>
<UnusedFunctionCall occurrences="2">
<code>ldap_free_result</code>
<code>ldap_unbind</code>
</UnusedFunctionCall>
</file>
<file src="src/Ldif/Encoder.php">
<InvalidNullableReturnType occurrences="1">
<code>string</code>
</InvalidNullableReturnType>
<InvalidScalarArgument occurrences="1">
<code>$value</code>
</InvalidScalarArgument>
<MissingReturnType occurrences="1">
<code>pushAttribute</code>
</MissingReturnType>
<MixedArgument occurrences="5">
<code>$this->options['version']</code>
<code>$this->options['wrap']</code>
<code>$v</code>
<code>$value</code>
<code>$value</code>
</MixedArgument>
<MixedArgumentTypeCoercion occurrences="1">
<code>$key</code>
</MixedArgumentTypeCoercion>
<MixedArrayAssignment occurrences="1">
<code>$entry[$name][]</code>
</MixedArrayAssignment>
<MixedArrayOffset occurrences="3">
<code>$entry[$name]</code>
<code>$entry[$name]</code>
<code>$entry[$name]</code>
</MixedArrayOffset>
<MixedAssignment occurrences="9">
<code>$dn</code>
<code>$entry[$name]</code>
<code>$entry[$name][]</code>
<code>$name</code>
<code>$oc</code>
<code>$type</code>
<code>$v</code>
<code>$value</code>
<code>$value</code>
</MixedAssignment>
<NullableReturnStatement occurrences="1">
<code>null</code>
</NullableReturnStatement>
<RedundantCastGivenDocblockType occurrences="1">
<code>(string) $string</code>
</RedundantCastGivenDocblockType>
<UnsafeInstantiation occurrences="2">
<code>new static($options)</code>
<code>new static([])</code>
</UnsafeInstantiation>
</file>
<file src="src/Node.php">
<DocblockTypeContradiction occurrences="4">
<code>$data === null</code>
<code>$this->ldap === null</code>
<code>is_array($this->children)</code>
<code>is_array($this->children)</code>
</DocblockTypeContradiction>
<InvalidMethodCall occurrences="1">
<code>getRdnString</code>
</InvalidMethodCall>
<InvalidNullableReturnType occurrences="1">
<code>Node</code>
</InvalidNullableReturnType>
<InvalidPropertyAssignmentValue occurrences="1">
<code>$this->children</code>
</InvalidPropertyAssignmentValue>
<InvalidReturnStatement occurrences="1">
<code>$this</code>
</InvalidReturnStatement>
<InvalidReturnType occurrences="1">
<code>array</code>
</InvalidReturnType>
<LessSpecificReturnStatement occurrences="1"/>
<MissingReturnType occurrences="6">
<code>_setAttribute</code>
<code>_setDateTimeAttribute</code>
<code>loadData</code>
<code>markAsNew</code>
<code>markAsToBeDeleted</code>
<code>triggerEvent</code>
</MissingReturnType>
<MixedArgument occurrences="5">
<code>$this->currentData[$key]</code>
<code>$this->originalData[$key]</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
</MixedArgument>
<MixedArgumentTypeCoercion occurrences="2">
<code>$key</code>
<code>$key</code>
</MixedArgumentTypeCoercion>
<MixedAssignment occurrences="10">
<code>$changed[$key]</code>
<code>$changed[$key]</code>
<code>$changes['add'][$key]</code>
<code>$changes['add'][$key]</code>
<code>$changes['delete'][$key]</code>
<code>$changes['replace'][$key]</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
</MixedAssignment>
<MoreSpecificReturnType occurrences="1">
<code>Collection</code>
</MoreSpecificReturnType>
<NullableReturnStatement occurrences="1">
<code>static::fromLdap($parentDn, $ldap)</code>
</NullableReturnStatement>
<PossiblyNullPropertyAssignmentValue occurrences="3">
<code>null</code>
<code>null</code>
<code>null</code>
</PossiblyNullPropertyAssignmentValue>
<PossiblyNullReference occurrences="1">
<code>getRdnString</code>
</PossiblyNullReference>
<PropertyNotSetInConstructor occurrences="3">
<code>$events</code>
<code>$ldap</code>
<code>$newDn</code>
</PropertyNotSetInConstructor>
<RedundantCastGivenDocblockType occurrences="2">
<code>(bool) $delete</code>
<code>(bool) $new</code>
</RedundantCastGivenDocblockType>
<RedundantConditionGivenDocblockType occurrences="8">
<code>$dn instanceof Dn</code>
<code>$dn instanceof Dn</code>
<code>$this->events</code>
<code>$this->events</code>
<code>$this->ldap !== null</code>
<code>$this->newDn !== null</code>
<code>is_array($this->children)</code>
<code>is_array($this->children)</code>
</RedundantConditionGivenDocblockType>
<RedundantPropertyInitializationCheck occurrences="2">
<code>$this->newDn</code>
<code>parent::_getDn()</code>
</RedundantPropertyInitializationCheck>
<UnsafeInstantiation occurrences="3">
<code>new static($dn, $data, $fromDataSource, null)</code>
<code>new static($dn, $data, true, $ldap)</code>
<code>new static($dn, [], false, null)</code>
</UnsafeInstantiation>
<UnusedForeachValue occurrences="1">
<code>$value</code>
</UnusedForeachValue>
</file>
<file src="src/Node/AbstractNode.php">
<MissingReturnType occurrences="1">
<code>loadData</code>
</MissingReturnType>
<MixedArgument occurrences="1">
<code>$this->currentData[$name]</code>
</MixedArgument>
<MixedArgumentTypeCoercion occurrences="1">
<code>$name</code>
</MixedArgumentTypeCoercion>
<MixedAssignment occurrences="4">
<code>$data[$key]</code>
<code>$data[$name]</code>
<code>$value</code>
<code>$value</code>
</MixedAssignment>
<MixedInferredReturnType occurrences="1">
<code>array</code>
</MixedInferredReturnType>
<MixedReturnStatement occurrences="1">
<code>$this->getAttribute('objectClass', null)</code>
</MixedReturnStatement>
<UnusedForeachValue occurrences="1">
<code>$value</code>
</UnusedForeachValue>
</file>
<file src="src/Node/ChildrenIterator.php">
<InvalidNullableReturnType occurrences="1">
<code>ChildrenIterator</code>
</InvalidNullableReturnType>
<MixedInferredReturnType occurrences="2">
<code>Node</code>
<code>array|null</code>
</MixedInferredReturnType>
<MixedReturnStatement occurrences="2">
<code>$this->data[$rdn]</code>
<code>current($this->data)</code>
</MixedReturnStatement>
<MixedReturnTypeCoercion occurrences="2">
<code>key($this->data)</code>
<code>string</code>
</MixedReturnTypeCoercion>
<NullableReturnStatement occurrences="1">
<code>null</code>
</NullableReturnStatement>
</file>
<file src="src/Node/Collection.php">
<ImplementedReturnTypeMismatch occurrences="2">
<code>Node</code>
<code>string</code>
</ImplementedReturnTypeMismatch>
<InvalidNullableReturnType occurrences="1">
<code>string</code>
</InvalidNullableReturnType>
<NullableReturnStatement occurrences="1">
<code>$this->iterator->key()</code>
</NullableReturnStatement>
</file>
<file src="src/Node/RootDse.php">
<MixedArrayAccess occurrences="1">
<code>$data['structuralobjectclass'][0]</code>
</MixedArrayAccess>
<MixedInferredReturnType occurrences="2">
<code>array</code>
<code>string|null</code>
</MixedInferredReturnType>
<MixedReturnStatement occurrences="2">
<code>$this->getAttribute('namingContexts', null)</code>
<code>$this->getAttribute('subschemaSubentry', 0)</code>
</MixedReturnStatement>
<PossiblyNullArgument occurrences="1">
<code>$schemaDn</code>
</PossiblyNullArgument>
<UnsafeInstantiation occurrences="1">
<code>new static($dn, $data)</code>
</UnsafeInstantiation>
</file>
<file src="src/Node/RootDse/ActiveDirectory.php">
<MixedInferredReturnType occurrences="15">
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
</MixedInferredReturnType>
<MixedReturnStatement occurrences="15">
<code>$this->getAttribute('configurationNamingContext', 0)</code>
<code>$this->getAttribute('currentTime', 0)</code>
<code>$this->getAttribute('defaultNamingContext', 0)</code>
<code>$this->getAttribute('dnsHostName', 0)</code>
<code>$this->getAttribute('domainControllerFunctionality', 0)</code>
<code>$this->getAttribute('domainFunctionality', 0)</code>
<code>$this->getAttribute('dsServiceName', 0)</code>
<code>$this->getAttribute('forestFunctionality', 0)</code>
<code>$this->getAttribute('highestCommittedUSN', 0)</code>
<code>$this->getAttribute('isGlobalCatalogReady', 0)</code>
<code>$this->getAttribute('isSynchronized', 0)</code>
<code>$this->getAttribute('ldapServiceName', 0)</code>
<code>$this->getAttribute('rootDomainNamingContext', 0)</code>
<code>$this->getAttribute('schemaNamingContext', 0)</code>
<code>$this->getAttribute('serverName', 0)</code>
</MixedReturnStatement>
<PossiblyNullArgument occurrences="1">
<code>$schemaDn</code>
</PossiblyNullArgument>
</file>
<file src="src/Node/RootDse/OpenLdap.php">
<MixedInferredReturnType occurrences="2">
<code>string|null</code>
<code>string|null</code>
</MixedInferredReturnType>
<MixedReturnStatement occurrences="2">
<code>$this->getAttribute('configContext', 0)</code>
<code>$this->getAttribute('monitorContext', 0)</code>
</MixedReturnStatement>
</file>
<file src="src/Node/RootDse/eDirectory.php">
<MixedInferredReturnType occurrences="10">
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
<code>string|null</code>
</MixedInferredReturnType>
<MixedReturnStatement occurrences="10">
<code>$this->getAttribute('abandonOps', 0)</code>
<code>$this->getAttribute('chainings', 0)</code>
<code>$this->getAttribute('dsaName', 0)</code>
<code>$this->getAttribute('errors', 0)</code>
<code>$this->getAttribute('extendedOps', 0)</code>
<code>$this->getAttribute('referralsReturned', 0)</code>
<code>$this->getAttribute('securityErrors', 0)</code>
<code>$this->getAttribute('vendorName', 0)</code>
<code>$this->getAttribute('vendorVersion', 0)</code>
<code>$this->getAttribute('wholeSubtreeSearchOps', 0)</code>
</MixedReturnStatement>
</file>
<file src="src/Node/Schema.php">
<UnsafeInstantiation occurrences="1">
<code>new static($dn, $data, $ldap)</code>
</UnsafeInstantiation>
</file>
<file src="src/Node/Schema/ActiveDirectory.php">
<PossiblyNullArgument occurrences="2">
<code>$node</code>
<code>$node</code>
</PossiblyNullArgument>
</file>
<file src="src/Node/Schema/AttributeType/ActiveDirectory.php">
<ImplementedReturnTypeMismatch occurrences="4">
<code>null</code>
<code>null</code>
<code>null</code>
<code>null</code>
</ImplementedReturnTypeMismatch>
<MixedArrayAccess occurrences="1">
<code>$this->ldapdisplayname[0]</code>
</MixedArrayAccess>
<MixedInferredReturnType occurrences="1">
<code>string</code>
</MixedInferredReturnType>
<MixedReturnStatement occurrences="1">
<code>$this->ldapdisplayname[0]</code>
</MixedReturnStatement>
</file>
<file src="src/Node/Schema/AttributeType/OpenLdap.php">
<MixedArgument occurrences="1">
<code>$this->_parents</code>
</MixedArgument>
<MixedArrayAccess occurrences="1">
<code>$this->_parents[0]</code>
</MixedArrayAccess>
<MixedAssignment occurrences="1">
<code>$maxLength</code>
</MixedAssignment>
<MixedInferredReturnType occurrences="6">
<code>OpenLdap|null</code>
<code>bool</code>
<code>string</code>
<code>string</code>
<code>string</code>
<code>string</code>
</MixedInferredReturnType>
<MixedReturnStatement occurrences="6">
<code>$this->_parents[0]</code>
<code>$this->desc</code>
<code>$this->name</code>
<code>$this->oid</code>
<code>$this->syntax</code>
<code>$this->{'single-value'}</code>
</MixedReturnStatement>
</file>
<file src="src/Node/Schema/ObjectClass/ActiveDirectory.php">
<ImplementedReturnTypeMismatch occurrences="6">
<code>null</code>
<code>null</code>
<code>null</code>
<code>null</code>
<code>null</code>
<code>null</code>
</ImplementedReturnTypeMismatch>
<MixedArrayAccess occurrences="1">
<code>$this->ldapdisplayname[0]</code>
</MixedArrayAccess>
<MixedInferredReturnType occurrences="1">
<code>string</code>
</MixedInferredReturnType>
<MixedReturnStatement occurrences="1">
<code>$this->ldapdisplayname[0]</code>
</MixedReturnStatement>
</file>
<file src="src/Node/Schema/ObjectClass/OpenLdap.php">
<DocblockTypeContradiction occurrences="2">
<code>$this->inheritedMay === null</code>
<code>$this->inheritedMust === null</code>
</DocblockTypeContradiction>
<MixedArgument occurrences="6">
<code>$may</code>
<code>$may</code>
<code>$must</code>
<code>$must</code>
<code>$p->getMayContain()</code>
<code>$p->getMustContain()</code>
</MixedArgument>
<MixedAssignment occurrences="3">
<code>$may</code>
<code>$must</code>
<code>$p</code>
</MixedAssignment>
<MixedInferredReturnType occurrences="5">
<code>array</code>
<code>array</code>
<code>string</code>
<code>string</code>
<code>string</code>
</MixedInferredReturnType>
<MixedMethodCall occurrences="2">
<code>getMayContain</code>
<code>getMustContain</code>
</MixedMethodCall>
<MixedReturnStatement occurrences="5">
<code>$this->_parents</code>
<code>$this->desc</code>
<code>$this->name</code>
<code>$this->oid</code>
<code>$this->sup</code>
</MixedReturnStatement>
<PropertyNotSetInConstructor occurrences="2">
<code>$inheritedMay</code>
<code>$inheritedMust</code>
</PropertyNotSetInConstructor>
</file>
<file src="src/Node/Schema/OpenLdap.php">
<MissingReturnType occurrences="2">
<code>ensureNameAttribute</code>
<code>resolveInheritance</code>
</MissingReturnType>
<MixedArgument occurrences="12">
<code>$attributeType['syntax']</code>
<code>$data[$token]</code>
<code>$parent</code>
<code>$tmp</code>
<code>$val->sup</code>
<code>$val->sup</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
<code>array_shift($tokens)</code>
</MixedArgument>
<MixedArrayAssignment occurrences="1">
<code>$data[$token][]</code>
</MixedArrayAssignment>
<MixedArrayOffset occurrences="5">
<code>$this->attributeTypes[$alias]</code>
<code>$this->ldapSyntaxes[$val['oid']]</code>
<code>$this->matchingRuleUse[$val['name']]</code>
<code>$this->matchingRules[$val['name']]</code>
<code>$this->objectClasses[$alias]</code>
</MixedArrayOffset>
<MixedAssignment occurrences="21">
<code>$alias</code>
<code>$alias</code>
<code>$attributeType['oid']</code>
<code>$data[$token]</code>
<code>$data[$token]</code>
<code>$data[$token][]</code>
<code>$data['_parents'][]</code>
<code>$data['name']</code>
<code>$data['name']</code>
<code>$ldapSyntax['oid']</code>
<code>$matchingRuleUse['oid']</code>
<code>$matchingRule['oid']</code>
<code>$objectClass['oid']</code>
<code>$parent</code>
<code>$tmp</code>
<code>$tmp</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
</MixedAssignment>
</file>
<file src="test/AbstractOnlineTestCase.php">
<MissingReturnType occurrences="1">
<code>cleanupLDAPServer</code>
</MissingReturnType>
<PossiblyFalseOperand occurrences="1">
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
</PossiblyFalseOperand>
<UnusedForeachValue occurrences="1">
<code>$entry</code>
</UnusedForeachValue>
<UnusedFunctionCall occurrences="2">
<code>ldap_add</code>
<code>ldap_delete</code>
</UnusedFunctionCall>
</file>
<file src="test/AttributeTest.php">
<InvalidArgument occurrences="3">
<code>$object</code>
<code>$stream</code>
<code>false</code>
</InvalidArgument>
<InvalidScalarArgument occurrences="4">
<code>$ts</code>
<code>'index'</code>
<code>3.1415</code>
<code>true</code>
</InvalidScalarArgument>
<MixedArgument occurrences="9">
<code>$data['ts']</code>
<code>$data['ts'][0]</code>
<code>$data['ts'][0]</code>
<code>$data['ts'][0]</code>
<code>$data['ts'][0]</code>
<code>$data['ts'][0]</code>
<code>$data['ts'][0]</code>
<code>$data['ts'][1]</code>
<code>$data['ts'][1]</code>
</MixedArgument>
<MixedArrayAccess occurrences="12">
<code>$data['file'][0]</code>
<code>$data['object'][0]</code>
<code>$data['p2_false'][0]</code>
<code>$data['p2_true'][0]</code>
<code>$data['ts'][0]</code>
<code>$data['ts'][0]</code>
<code>$data['ts'][0]</code>
<code>$data['ts'][0]</code>
<code>$data['ts'][0]</code>
<code>$data['ts'][0]</code>
<code>$data['ts'][1]</code>
<code>$data['ts'][1]</code>
</MixedArrayAccess>
<MixedAssignment occurrences="7">
<code>$password</code>
<code>$password</code>
<code>$password</code>
<code>$password</code>
<code>$value</code>
<code>$value</code>
<code>$value</code>
</MixedAssignment>
<PossiblyFalseArgument occurrences="4">
<code>strpos($md5, '}')</code>
<code>strpos($sha, '}')</code>
<code>strpos($smd5, '}')</code>
<code>strpos($ssha, '}')</code>
</PossiblyFalseArgument>
<PossiblyInvalidArgument occurrences="1">
<code>$utcTimestamp</code>
</PossiblyInvalidArgument>
<PossiblyInvalidArrayAccess occurrences="2">
<code>$retTs[0]</code>
<code>$retTs[1]</code>
</PossiblyInvalidArrayAccess>
</file>
<file src="test/BindTest.php">
<InvalidArrayOffset occurrences="1">
<code>$options['accountDomainName']</code>
</InvalidArrayOffset>
<MissingReturnType occurrences="17">
<code>testAnonymousBind</code>
<code>testBindWithEmptyPassword</code>
<code>testBindWithNullPassword</code>
<code>testBindWithoutDnUsernameAndDnRequired</code>
<code>testBoundUserIsFalseIfNotBoundToLDAP</code>
<code>testBoundUserIsReturnedAfterBinding</code>
<code>testConnectBind</code>
<code>testEmptyOptionsBind</code>
<code>testExplicitParamsBind</code>
<code>testNoBaseDnBind</code>
<code>testNoDomainNameBind</code>
<code>testPlainBind</code>
<code>testRequiresDnBind</code>
<code>testRequiresDnWithoutDnBind</code>
<code>testResourceIsAlwaysReturned</code>
<code>testSaslBind</code>
<code>testSaslBindNoExplicitUsername</code>
</MissingReturnType>
<PossiblyFalsePropertyAssignmentValue occurrences="2">
<code>getenv('TESTS_LAMINAS_LDAP_ALT_PRINCIPAL_NAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
</PossiblyFalsePropertyAssignmentValue>
<PropertyTypeCoercion occurrences="8">
<code>$this->options</code>
<code>$this->options</code>
<code>$this->options</code>
<code>$this->options</code>
<code>$this->options</code>
<code>$this->options</code>
<code>$this->options</code>
</PropertyTypeCoercion>
</file>
<file src="test/CanonTest.php">
<MissingReturnType occurrences="12">
<code>testAccountCanonization</code>
<code>testDefaultAccountFilterFormat</code>
<code>testDnCanon</code>
<code>testGetUnavailableCanoncialForm</code>
<code>testGetUnknownCanonicalForm</code>
<code>testInvalidAccountCanon</code>
<code>testInvalidAccountName</code>
<code>testMismatchDomainBind</code>
<code>testPlainCanon</code>
<code>testPossibleAuthority</code>
<code>testSpecialCharacterInUsername</code>
<code>testSplittingOption</code>
</MissingReturnType>
<MixedArgument occurrences="2">
<code>$form</code>
<code>$name</code>
</MixedArgument>
<MixedArrayAccess occurrences="1">
<code>$names[$form]</code>
</MixedArrayAccess>
<MixedArrayOffset occurrences="1">
<code>$names[$form]</code>
</MixedArrayOffset>
<MixedAssignment occurrences="2">
<code>$form</code>
<code>$name</code>
</MixedAssignment>
<PossiblyFalseArgument occurrences="14">
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
</PossiblyFalseArgument>
<PossiblyFalseOperand occurrences="28">
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME_SHORT')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME_SHORT')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME_SHORT')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME_SHORT')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME_SHORT')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME_SHORT')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME_SHORT')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME_SHORT')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME_SHORT')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ACCOUNT_DOMAIN_NAME_SHORT')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
</PossiblyFalseOperand>
<PossiblyUndefinedVariable occurrences="3">
<code>$names</code>
<code>$names</code>
<code>$names</code>
</PossiblyUndefinedVariable>
<UnusedVariable occurrences="11">
<code>$canon</code>
<code>$canon</code>
<code>$canon</code>
<code>$canon</code>
<code>$canon</code>
<code>$canon</code>
<code>$canon</code>
<code>$canon</code>
<code>$canon</code>
<code>$canon</code>
<code>$canon</code>
</UnusedVariable>
</file>
<file src="test/ChangePasswordTest.php">
<ArgumentTypeCoercion occurrences="1">
<code>'Laminas\Ldap'</code>
</ArgumentTypeCoercion>
<InvalidScalarArgument occurrences="2">
<code>512</code>
<code>512</code>
</InvalidScalarArgument>
<MissingReturnType occurrences="4">
<code>testAddNewUserWithPasswordActiveDirectory</code>
<code>testAddNewUserWithPasswordOpenLDAP</code>
<code>testChangePasswordWithUserAccountActiveDirectory</code>
<code>testChangePasswordWithUserAccountOpenLDAP</code>
</MissingReturnType>
<UndefinedClass occurrences="1">
<code>'Laminas\Ldap'</code>
</UndefinedClass>
</file>
<file src="test/ConnectTest.php">
<InvalidScalarArgument occurrences="3">
<code>$port</code>
<code>$port</code>
<code>$useSsl</code>
</InvalidScalarArgument>
<PossiblyFalseArgument occurrences="1">
<code>$host</code>
</PossiblyFalseArgument>
<PossiblyFalseOperand occurrences="2">
<code>$host</code>
<code>$host</code>
</PossiblyFalseOperand>
<PropertyTypeCoercion occurrences="3">
<code>$this->options</code>
<code>$this->options</code>
</PropertyTypeCoercion>
</file>
<file src="test/Converter/ConverterTest.php">
<InvalidScalarArgument occurrences="1">
<code>$convert['date']</code>
</InvalidScalarArgument>
<MissingReturnType occurrences="1">
<code>testFromLdapDateTimeThrowsException</code>
</MissingReturnType>
<MixedArgument occurrences="4">
<code>$convert</code>
<code>$convert['type']</code>
<code>$value</code>
<code>$value</code>
</MixedArgument>
<PossiblyInvalidArgument occurrences="1">
<code>testToLdap</code>
</PossiblyInvalidArgument>
</file>
<file src="test/CopyRenameTest.php">
<MissingReturnType occurrences="25">
<code>testRecursiveCopy</code>
<code>testRecursiveCopyToSubtree</code>
<code>testRecursiveCopyToSubtreeWithDnObjects</code>
<code>testRecursiveCopyWithDnObjects</code>
<code>testRecursiveMoveToSubtree</code>
<code>testRecursiveMoveToSubtreeWithDnObjects</code>
<code>testRecursiveRename</code>
<code>testRecursiveRenameWithDnObjects</code>
<code>testRenameEmulationSourceNotExists</code>
<code>testRenameEmulationTargetExists</code>
<code>testRenameEmulationTargetParentNotExists</code>
<code>testRenameSourceNotExists</code>
<code>testRenameTargetExists</code>
<code>testRenameTargetParentNotExists</code>
<code>testSimpleLeafCopy</code>
<code>testSimpleLeafCopyToSubtree</code>
<code>testSimpleLeafCopyToSubtreeWithDnObjects</code>
<code>testSimpleLeafCopyWithDnObjects</code>
<code>testSimpleLeafMoveAlias</code>
<code>testSimpleLeafMoveToSubtree</code>
<code>testSimpleLeafMoveToSubtreeWithDnObjects</code>
<code>testSimpleLeafRename</code>
<code>testSimpleLeafRenameEmulation</code>
<code>testSimpleLeafRenameEmulationWithDnObjects</code>
<code>testSimpleLeafRenameWithDnObjects</code>
</MissingReturnType>
<UnusedFunctionCall occurrences="1">
<code>ldap_add</code>
</UnusedFunctionCall>
</file>
<file src="test/CrudTest.php">
<MissingReturnType occurrences="21">
<code>testAddAndDelete</code>
<code>testAddObjectClass</code>
<code>testAddWithDnObject</code>
<code>testAddingEntryThatHasMultipleValuesOnRdnAttribute</code>
<code>testAddingEntryWithMissingRdnAttribute</code>
<code>testAddingEntryWithMissingRdnAttributeValue</code>
<code>testDeleteRecursively</code>
<code>testIllegalAdd</code>
<code>testIllegalDelete</code>
<code>testIllegalUpdate</code>
<code>testPrepareLDAPEntryArray</code>
<code>testPrepareLDAPEntryArrayArrayData</code>
<code>testPrepareLDAPEntryArrayObjectData</code>
<code>testRemoveObjectClass</code>
<code>testSave</code>
<code>testSaveWithDnObject</code>
<code>testUpdate</code>
<code>testUpdateWithDnObject</code>
<code>testUpdatingEntryWithAttributeThatIsAnRdnAttribute</code>
<code>testUpdatingEntryWithRdnAttributeValueMissingInData</code>
<code>testZeroValueMakesItThroughSanitationProcess</code>
</MissingReturnType>
<MixedArgument occurrences="5">
<code>$entry['objectclass']</code>
<code>$entry['objectclass']</code>
<code>$entry['objectclass']</code>
<code>$entry['objectclass']</code>
<code>$entry['ou']</code>
</MixedArgument>
<MixedArrayAccess occurrences="7">
<code>$entry['associateddomain'][0]</code>
<code>$entry['l'][0]</code>
<code>$entry['l'][0]</code>
<code>$entry['l'][0]</code>
<code>$entry['l'][0]</code>
<code>$entry['l'][0]</code>
<code>$entry['l'][0]</code>
</MixedArrayAccess>
<MixedArrayAssignment occurrences="3">
<code>$entry['associatedDomain'][]</code>
<code>$entry['objectclass'][]</code>
<code>$entry['objectclass'][]</code>
</MixedArrayAssignment>
<UnusedVariable occurrences="1">
<code>$entry</code>
</UnusedVariable>
</file>
<file src="test/Dn/CreationTest.php">
<InvalidScalarArgument occurrences="1">
<code>1</code>
</InvalidScalarArgument>
<MissingReturnType occurrences="5">
<code>testDnCreation</code>
<code>testDnCreationWithDifferentCaseFoldings</code>
<code>testEmptyStringDn</code>
<code>testGetParentDn</code>
<code>testGetRdn</code>
</MissingReturnType>
<NullArgument occurrences="1">
<code>null</code>
</NullArgument>
</file>
<file src="test/Dn/EscapingTest.php">
<MissingReturnType occurrences="2">
<code>testEscapeValues</code>
<code>testUnescapeValues</code>
</MissingReturnType>
</file>
<file src="test/Dn/ExplodingTest.php">
<UnusedVariable occurrences="1">
<code>$dnArray</code>
</UnusedVariable>
</file>
<file src="test/Dn/ImplodingTest.php">
<MissingReturnType occurrences="10">
<code>testDnWithMultiValuedRdnRoundTrip</code>
<code>testImplodeDn</code>
<code>testImplodeDnWithUtf8Characters</code>
<code>testImplodeRdn</code>
<code>testImplodeRdnCaseFold</code>
<code>testImplodeRdnInvalidOne</code>
<code>testImplodeRdnInvalidThree</code>
<code>testImplodeRdnMultiValuedRdn</code>
<code>testImplodeRdnMultiValuedRdn2</code>
<code>testImplodeRdnMultiValuedRdnCaseFold</code>
</MissingReturnType>
</file>
<file src="test/Dn/MiscTest.php">
<MissingReturnType occurrences="7">
<code>testIsChildOf</code>
<code>testIsChildOfIllegalBothDn</code>
<code>testIsChildOfIllegalDn1</code>
<code>testIsChildOfIllegalDn2</code>
<code>testIsChildOfOtherSubtree</code>
<code>testIsChildOfParentDnLonger</code>
<code>testIsChildOfWithDnObjects</code>
</MissingReturnType>
</file>
<file src="test/Dn/ModificationTest.php">
<InvalidScalarArgument occurrences="1">
<code>'string'</code>
</InvalidScalarArgument>
<MissingReturnType occurrences="6">
<code>testArrayAccessImplementation</code>
<code>testDnManipulationAppendAndPrepend</code>
<code>testDnManipulationGet</code>
<code>testDnManipulationInsert</code>
<code>testDnManipulationRemove</code>
<code>testDnManipulationSet</code>
</MissingReturnType>
</file>
<file src="test/ErrorHandlerTest.php">
<MissingClosureParamType occurrences="2">
<code>$errno</code>
<code>$error</code>
</MissingClosureParamType>
<MixedArgumentTypeCoercion occurrences="4">
<code>$this->dummyErrorHandler</code>
<code>$this->dummyErrorHandler</code>
<code>$this->dummyErrorHandler</code>
<code>$this->dummyErrorHandler</code>
</MixedArgumentTypeCoercion>
<UnusedClosureParam occurrences="2">
<code>$errno</code>
<code>$error</code>
</UnusedClosureParam>
</file>
<file src="test/Exception/LdapExceptionTest.php">
<MissingReturnType occurrences="1">
<code>testException</code>
</MissingReturnType>
</file>
<file src="test/FilterTest.php">
<MissingReturnType occurrences="12">
<code>testChaining</code>
<code>testComplexFilter</code>
<code>testEscapeValues</code>
<code>testFilterCreation</code>
<code>testFilterEscapeBasicOperation</code>
<code>testFilterValueUtf8</code>
<code>testGroupingFilter</code>
<code>testIllegalGroupingFilter</code>
<code>testNegate</code>
<code>testRealFilterString</code>
<code>testToStringImplementation</code>
<code>testUnescapeValues</code>
</MissingReturnType>
<UnusedVariable occurrences="1">
<code>$f</code>
</UnusedVariable>
</file>
<file src="test/Ldif/SimpleDecoderTest.php">
<MissingReturnType occurrences="12">
<code>testDecodeSimpleSingleItem</code>
<code>testDecodeSimpleSingleItemWithMultilineComment</code>
<code>testDecodeSimpleSingleItemWithUri</code>
<code>testDecodeSingleItemWithBase64Attributes</code>
<code>testDecodeSingleItemWithFoldedAttribute</code>
<code>testDecodeSingleItemWithFoldedAttributesAndEmptyLinesBetween</code>
<code>testDecodeSingleItemWithFoldedBase64Attribute</code>
<code>testDecodeStringContainingBase64EncodedValue</code>
<code>testDecodeStringContainingEntriesWithUtf8EncodedAttributeValues</code>
<code>testDecodeStringContainingEntryWithFoldedAttributeValue</code>
<code>testDecodeTwoItems</code>
<code>testRoundtripEncoding</code>
</MissingReturnType>
<MixedArrayAccess occurrences="29">
<code>$actual[0]['description']</code>
<code>$actual[0]['dn']</code>
<code>$actual[0]['objectclass']</code>
<code>$actual[0]['ou']</code>
<code>$actual[0]['ou;lang-en']</code>
<code>$actual[0]['ou;lang-ja']</code>
<code>$actual[0]['ou;lang-ja;phonetic']</code>
<code>$actual[1]['cn']</code>
<code>$actual[1]['cn;lang-en']</code>
<code>$actual[1]['cn;lang-ja']</code>
<code>$actual[1]['cn;lang-ja;phonetic']</code>
<code>$actual[1]['dn']</code>
<code>$actual[1]['givenname']</code>
<code>$actual[1]['givenname;lang-en']</code>
<code>$actual[1]['givenname;lang-ja']</code>
<code>$actual[1]['givenname;lang-ja;phonetic']</code>
<code>$actual[1]['mail']</code>
<code>$actual[1]['objectclass']</code>
<code>$actual[1]['preferredlanguage']</code>
<code>$actual[1]['sn']</code>
<code>$actual[1]['sn;lang-en']</code>
<code>$actual[1]['sn;lang-ja']</code>
<code>$actual[1]['sn;lang-ja;phonetic']</code>
<code>$actual[1]['title']</code>
<code>$actual[1]['title;lang-en']</code>
<code>$actual[1]['title;lang-ja']</code>
<code>$actual[1]['title;lang-ja;phonetic']</code>
<code>$actual[1]['uid']</code>
<code>$actual[1]['userpassword']</code>
</MixedArrayAccess>
</file>
<file src="test/Node/AttributeIterationTest.php">
<MissingReturnType occurrences="1">
<code>testSimpleIteration</code>
</MissingReturnType>
<MixedAssignment occurrences="2">
<code>$data[$k]</code>
<code>$v</code>
</MixedAssignment>
<RedundantConditionGivenDocblockType occurrences="1">
<code>assertNotNull</code>
</RedundantConditionGivenDocblockType>
</file>
<file src="test/Node/ChildrenIterationTest.php">
<MissingReturnType occurrences="3">
<code>testCallingNextAfterIterationShouldNotThrowException</code>
<code>testSimpleIteration</code>
<code>testSimpleRecursiveIteration</code>
</MissingReturnType>
<MixedArgument occurrences="1">
<code>$n->getRdnArray()</code>
</MixedArgument>
<MixedAssignment occurrences="3">
<code>$dn</code>
<code>$n</code>
<code>$rdn</code>
</MixedAssignment>
<MixedMethodCall occurrences="3">
<code>getDn</code>
<code>getRdnArray</code>
<code>toString</code>
</MixedMethodCall>
<PossiblyFalseArgument occurrences="2">
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
</PossiblyFalseArgument>
<UnusedForeachValue occurrences="1">
<code>$n</code>
</UnusedForeachValue>
<UnusedVariable occurrences="3">
<code>$rdn</code>
<code>$rdn</code>
<code>$rdn</code>
</UnusedVariable>
</file>
<file src="test/Node/ChildrenTest.php">
<InvalidMethodCall occurrences="1">
<code>getChildren</code>
</InvalidMethodCall>
<MissingReturnType occurrences="7">
<code>testCascadingAttachAndDetach</code>
<code>testChildrenCollectionSerialization</code>
<code>testGetChildrenOnAttachedNode</code>
<code>testGetChildrenOnDetachedNode</code>
<code>testHasChildrenOnAttachedNode</code>
<code>testHasChildrenOnDetachedNodeWithPriorGetChildren</code>
<code>testHasChildrenOnDetachedNodeWithoutPriorGetChildren</code>
</MissingReturnType>
<MixedArgument occurrences="2">
<code>$children2</code>
<code>$children2</code>
</MixedArgument>
<MixedAssignment occurrences="8">
<code>$children2</code>
<code>$children2</code>
<code>$nc</code>
<code>$nc</code>
<code>$nc</code>
<code>$node2</code>
<code>$node2</code>
<code>$nodeChildren</code>
</MixedAssignment>
<MixedMethodCall occurrences="12">
<code>attachLDAP</code>
<code>attachLDAP</code>
<code>getChildren</code>
<code>getChildren</code>
<code>getLDAP</code>
<code>hasChildren</code>
<code>hasChildren</code>
<code>hasChildren</code>
<code>hasChildren</code>
<code>isAttached</code>
<code>isAttached</code>
<code>isAttached</code>
</MixedMethodCall>
<PossiblyFalseArgument occurrences="3">
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
</PossiblyFalseArgument>
<PossiblyNullReference occurrences="15">
<code>detachLDAP</code>
<code>detachLDAP</code>
<code>detachLDAP</code>
<code>detachLDAP</code>
<code>getChildren</code>
<code>getChildren</code>
<code>getChildren</code>
<code>getChildren</code>
<code>getChildren</code>
<code>getChildren</code>
<code>hasChildren</code>
<code>hasChildren</code>
<code>hasChildren</code>
<code>hasChildren</code>
<code>hasChildren</code>
</PossiblyNullReference>
</file>
<file src="test/Node/OfflineTest.php">
<MissingReturnType occurrences="45">
<code>testAppendToAttributeFirstTime</code>
<code>testArrayAccess</code>
<code>testAttributeAccessDnGet</code>
<code>testCreateEmptyNode</code>
<code>testCreateFromArrayAndEnsureRdnValues</code>
<code>testCreateFromArrayIllegalDn</code>
<code>testCreateFromArrayMalformedDn</code>
<code>testCreateFromArrayMissingDn</code>
<code>testCreateFromArrayObjectDn</code>
<code>testCreateFromArrayStringDn</code>
<code>testDeleteUnusedAttribute</code>
<code>testDnObjectCloning</code>
<code>testExistsAttribute</code>
<code>testGetAttributes</code>
<code>testGetChangedData</code>
<code>testGetChanges</code>
<code>testGetData</code>
<code>testGetDnArray</code>
<code>testGetDnObject</code>
<code>testGetDnString</code>
<code>testGetObjectClass</code>
<code>testGetRdnArray</code>
<code>testGetRdnString</code>
<code>testGetSetAndDeleteMethods</code>
<code>testHasValue</code>
<code>testIllegalAttributeAccessDnSet</code>
<code>testIllegalAttributeAccessRdnAttributeSet</code>
<code>testModifyObjectClass</code>
<code>testOverloading</code>
<code>testRdnAttributesHandleMultiValuedAttribute</code>
<code>testRdnAttributesHandleMultiValuedAttribute2</code>
<code>testRdnAttributesHandleMultiValuedAttribute3</code>
<code>testRemoveDuplicates</code>
<code>testRemoveFromAttributeArray</code>
<code>testRemoveFromAttributeMultipleArray</code>
<code>testRemoveFromAttributeMultipleSimple</code>
<code>testRemoveFromAttributeSimple</code>
<code>testRenameNodeArray</code>
<code>testRenameNodeDnObject</code>
<code>testRenameNodeFromDataSource</code>
<code>testRenameNodeString</code>
<code>testSerialize</code>
<code>testToArray</code>
<code>testToJson</code>
<code>testToString</code>
</MissingReturnType>
<MixedArgument occurrences="8">
<code>$data['dn']</code>
<code>$data['dn']</code>
<code>$data['dn']</code>
<code>$node->getAttribute('key')</code>
<code>$node->getAttribute('key')</code>
<code>$node->getAttribute('userPassword')</code>
<code>$node->key</code>
<code>$node['key']</code>
</MixedArgument>
<MixedArrayAccess occurrences="4">
<code>$node->cn[0]</code>
<code>$node->host[3]</code>
<code>$node->key[0]</code>
<code>$node['key'][0]</code>
</MixedArrayAccess>
<MixedAssignment occurrences="3">
<code>$cn</code>
<code>$cn</code>
<code>$newObject</code>
</MixedAssignment>
<PossiblyInvalidArgument occurrences="1">
<code>$utcTimestamp</code>
</PossiblyInvalidArgument>
<UnusedVariable occurrences="3">
<code>$node</code>
<code>$node</code>
<code>$node</code>
</UnusedVariable>
</file>
<file src="test/Node/OnlineTest.php">
<InvalidArgument occurrences="7">
<code>ExceptionInterface::class</code>
<code>ExceptionInterface::class</code>
<code>ExceptionInterface::class</code>
<code>ExceptionInterface::class</code>
<code>[]</code>
<code>[]</code>
<code>[]</code>
</InvalidArgument>
<InvalidCatch occurrences="5"/>
<InvalidMethodCall occurrences="1">
<code>getDnString</code>
</InvalidMethodCall>
<InvalidPropertyFetch occurrences="2">
<code>$node->ou</code>
<code>$node->ou</code>
</InvalidPropertyFetch>
<MissingReturnType occurrences="19">
<code>testAttachToInvalidLDAP</code>
<code>testAttachToValidLDAP</code>
<code>testChangeReadOnlySystemAttributes</code>
<code>testCountChildren</code>
<code>testCountSubtree</code>
<code>testDetachAndReattach</code>
<code>testExistsDn</code>
<code>testGetBaseNode</code>
<code>testGetIllegalNode</code>
<code>testGetNode</code>
<code>testGetNonexistentParent</code>
<code>testGetParent</code>
<code>testLoadFromLDAP</code>
<code>testLoadFromLDAPIllegalEntry</code>
<code>testLoadFromLDAPWithDnObject</code>
<code>testReload</code>
<code>testSearchChildren</code>
<code>testSearchSubtree</code>
<code>testSerialize</code>
</MissingReturnType>
<MixedArgumentTypeCoercion occurrences="1">
<code>$attr</code>
</MixedArgumentTypeCoercion>
<MixedAssignment occurrences="1">
<code>$newObject</code>
</MixedAssignment>
<MixedMethodCall occurrences="1">
<code>isAttached</code>
</MixedMethodCall>
<PossiblyFalseArgument occurrences="6">
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
</PossiblyFalseArgument>
<PossiblyNullPropertyFetch occurrences="2">
<code>$node->ou</code>
<code>$node->ou</code>
</PossiblyNullPropertyFetch>
<PossiblyNullReference occurrences="13">
<code>countChildren</code>
<code>countChildren</code>
<code>countSubtree</code>
<code>exists</code>
<code>getDn</code>
<code>getDnString</code>
<code>getParent</code>
<code>getParent</code>
<code>isAttached</code>
<code>reload</code>
<code>searchChildren</code>
<code>searchChildren</code>
<code>searchSubtree</code>
</PossiblyNullReference>
<TooManyArguments occurrences="3">
<code>searchChildren</code>
<code>searchChildren</code>
<code>searchSubtree</code>
</TooManyArguments>
<UnusedVariable occurrences="3">
<code>$node</code>
<code>$node</code>
<code>$pnode</code>
</UnusedVariable>
</file>
<file src="test/Node/RootDseTest.php">
<MissingReturnType occurrences="7">
<code>testGetters</code>
<code>testLoadRootDseNode</code>
<code>testOffsetSetWillThrowException</code>
<code>testOffsetUnsetWillThrowException</code>
<code>testSetterWillThrowException</code>
<code>testSupportCheckMethods</code>
<code>testUnsetterWillThrowException</code>
</MissingReturnType>
<RedundantCondition occurrences="1">
<code>assertNull</code>
</RedundantCondition>
<UndefinedMethod occurrences="41">
<code>getConfigContext</code>
<code>getConfigurationNamingContext</code>
<code>getCurrentTime</code>
<code>getDefaultNamingContext</code>
<code>getDnsHostName</code>
<code>getDomainControllerFunctionality</code>
<code>getDomainFunctionality</code>
<code>getDsServiceName</code>
<code>getDsaName</code>
<code>getForestFunctionality</code>
<code>getHighestCommittedUSN</code>
<code>getIsGlobalCatalogReady</code>
<code>getIsSynchronized</code>
<code>getLDAPServiceName</code>
<code>getMonitorContext</code>
<code>getRootDomainNamingContext</code>
<code>getSchemaNamingContext</code>
<code>getServerName</code>
<code>getStatisticsAbandonOps</code>
<code>getStatisticsChainings</code>
<code>getStatisticsErrors</code>
<code>getStatisticsExtendedOps</code>
<code>getStatisticsReferralsReturned</code>
<code>getStatisticsSecurityErrors</code>
<code>getStatisticsWholeSubtreeSearchOps</code>
<code>getVendorName</code>
<code>getVendorVersion</code>
<code>supportsCapability</code>
<code>supportsCapability</code>
<code>supportsControl</code>
<code>supportsControl</code>
<code>supportsControl</code>
<code>supportsControl</code>
<code>supportsExtension</code>
<code>supportsExtension</code>
<code>supportsExtension</code>
<code>supportsExtension</code>
<code>supportsFeature</code>
<code>supportsFeature</code>
<code>supportsPolicy</code>
<code>supportsPolicy</code>
</UndefinedMethod>
</file>
<file src="test/Node/SchemaTest.php">
<MissingReturnType occurrences="13">
<code>testActiveDirectorySchema</code>
<code>testGetters</code>
<code>testOffsetSetWillThrowException</code>
<code>testOffsetUnsetWillThrowException</code>
<code>testOpenLDAPSchema</code>
<code>testOpenLDAPSchemaAttributeTypeAliases</code>
<code>testOpenLDAPSchemaAttributeTypeInheritance</code>
<code>testOpenLDAPSchemaObjectClassAliases</code>
<code>testOpenLDAPSchemaObjectClassInheritance</code>
<code>testSchemaNode</code>
<code>testSetterWillThrowException</code>
<code>testUnsetterWillThrowException</code>
<code>testeDirectorySchema</code>
</MissingReturnType>
<MixedArrayAccess occurrences="2">
<code>$ou->_parents[0]</code>
<code>$ou->_parents[0]</code>
</MixedArrayAccess>
<MixedAssignment occurrences="10">
<code>$ca</code>
<code>$ca2</code>
<code>$cn</code>
<code>$name</code>
<code>$ob1</code>
<code>$ob1</code>
<code>$ob2</code>
<code>$ob2</code>
<code>$ou</code>
<code>$schemaUn</code>
</MixedAssignment>
<MixedMethodCall occurrences="12">
<code>getMaxLength</code>
<code>getMaxLength</code>
<code>getMayContain</code>
<code>getMayContain</code>
<code>getMustContain</code>
<code>getMustContain</code>
<code>getOid</code>
<code>getOid</code>
<code>getOid</code>
<code>getOid</code>
<code>getSyntax</code>
<code>getSyntax</code>
</MixedMethodCall>
<MixedPropertyFetch occurrences="18">
<code>$ca->may</code>
<code>$ca->must</code>
<code>$ca->sup</code>
<code>$ca2->may</code>
<code>$ca2->must</code>
<code>$ca2->sup</code>
<code>$cn->equality</code>
<code>$cn->ordering</code>
<code>$cn->substr</code>
<code>$cn->sup</code>
<code>$cn->syntax</code>
<code>$cn->{'max-length'}</code>
<code>$name->equality</code>
<code>$name->ordering</code>
<code>$name->substr</code>
<code>$name->sup</code>
<code>$name->syntax</code>
<code>$name->{'max-length'}</code>
</MixedPropertyFetch>
<UndefinedMethod occurrences="3">
<code>getLDAPSyntaxes</code>
<code>getMatchingRuleUse</code>
<code>getMatchingRules</code>
</UndefinedMethod>
<UnusedVariable occurrences="2">
<code>$attributeTypes</code>
<code>$objectClasses</code>
</UnusedVariable>
</file>
<file src="test/Node/UpdateTest.php">
<InvalidMethodCall occurrences="1">
<code>getDn</code>
</InvalidMethodCall>
<MissingReturnType occurrences="9">
<code>testAddDeletedNode</code>
<code>testAddNewNode</code>
<code>testModifyDeletedNode</code>
<code>testMoveDeletedExistingNode</code>
<code>testMoveDeletedNewNode</code>
<code>testMoveExistingNode</code>
<code>testMoveNewNode</code>
<code>testMoveNode</code>
<code>testSimpleUpdateOneValue</code>
</MissingReturnType>
<MixedArgument occurrences="3">
<code>$child->getDn()</code>
<code>$entry['objectclass']</code>
<code>$entry['objectclass']</code>
</MixedArgument>
<MixedArrayAccess occurrences="1">
<code>$entry['objectclass'][0]</code>
</MixedArrayAccess>
<PossiblyNullPropertyAssignment occurrences="2">
<code>$node1</code>
<code>$node1</code>
</PossiblyNullPropertyAssignment>
<PossiblyNullReference occurrences="7">
<code>getDn</code>
<code>move</code>
<code>rename</code>
<code>setDn</code>
<code>setDn</code>
<code>setDn</code>
<code>update</code>
</PossiblyNullReference>
</file>
<file src="test/OfflineReconnectTest.php">
<PossiblyNullReference occurrences="3">
<code>enable</code>
<code>enable</code>
<code>enable</code>
</PossiblyNullReference>
</file>
<file src="test/OfflineTest.php">
<MissingReturnType occurrences="5">
<code>testAddingAttributes</code>
<code>testAddingAttributesFails</code>
<code>testRemovingAttributesFails</code>
<code>testUpdatingAttributes</code>
<code>testUpdatingAttributesFails</code>
</MissingReturnType>
</file>
<file src="test/ReconnectTest.php">
<InvalidReturnStatement occurrences="1">
<code>$options</code>
</InvalidReturnStatement>
<InvalidReturnType occurrences="1">
<code>non-empty-array<string, string></code>
</InvalidReturnType>
<InvalidScalarArgument occurrences="2">
<code>getenv('TESTS_LAMINAS_LDAP_PORT')</code>
<code>getenv('TESTS_LAMINAS_LDAP_PORT')</code>
</InvalidScalarArgument>
<MixedArrayAccess occurrences="4">
<code>$entry['l'][0]</code>
<code>$entry['uid'][0]</code>
<code>$entry['uid'][0]</code>
<code>$entry['uid'][0]</code>
</MixedArrayAccess>
<MixedAssignment occurrences="1">
<code>$options['port']</code>
</MixedAssignment>
<MixedOperand occurrences="1">
<code>$options['port']</code>
</MixedOperand>
<PossiblyFalseArgument occurrences="3">
<code>getenv('TESTS_LAMINAS_LDAP_HOST')</code>
<code>getenv('TESTS_LAMINAS_LDAP_HOST')</code>
<code>getenv('TESTS_LAMINAS_LDAP_SCRIPTS_PORT')</code>
</PossiblyFalseArgument>
<PossiblyFalseOperand occurrences="8">
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_ALT_USERNAME')</code>
<code>getenv('TESTS_LAMINAS_LDAP_BASE_DN')</code>
<code>getenv('TESTS_LAMINAS_LDAP_BASE_DN')</code>
<code>getenv('TESTS_LAMINAS_LDAP_BASE_DN')</code>
<code>getenv('TESTS_LAMINAS_LDAP_BASE_DN')</code>
</PossiblyFalseOperand>
</file>
<file src="test/SearchTest.php">
<DocblockTypeContradiction occurrences="1">
<code>assertNull</code>
</DocblockTypeContradiction>
<MissingReturnType occurrences="44">
<code>testAttributeNameTreatmentCustomFunction</code>
<code>testAttributeNameTreatmentCustomInstanceMethod</code>
<code>testAttributeNameTreatmentCustomStaticMethod</code>
<code>testAttributeNameTreatmentNative</code>
<code>testAttributeNameTreatmentToLower</code>
<code>testAttributeNameTreatmentToUpper</code>
<code>testCallingCurrentOnCollectionReturnsFirstElement</code>
<code>testCallingCurrentOnEmptyCollectionReturnsNull</code>
<code>testCallingCurrentOnEmptyIteratorReturnsNull</code>
<code>testCallingCurrentOnIteratorReturnsFirstElement</code>
<code>testCallingNextAfterIterationShouldNotThrowException</code>
<code>testCollectionClassNotSubclassingLaminasLDAPCollectionThrowsException</code>
<code>testCountBase</code>
<code>testCountChildren</code>
<code>testCountChildrenWithDnObject</code>
<code>testCountOne</code>
<code>testCountSub</code>
<code>testCountSubWithDnObjectAndFilterObject</code>
<code>testExistsDn</code>
<code>testExistsDnWithDnObject</code>
<code>testGetSingleEntry</code>
<code>testGetSingleEntryWithDnObject</code>
<code>testGetSingleIllegalEntry</code>
<code>testGetSingleIllegalEntryWithException</code>
<code>testIllegalSearch</code>
<code>testInnerIteratorIsOfRequiredType</code>
<code>testMultipleResultIteration</code>
<code>testResultIteration</code>
<code>testResultIterationAfterCallingCurrent</code>
<code>testReverseSortingWithSearchEntriesShortcut</code>
<code>testReverseSortingWithSearchEntriesShortcutWithOptionsArray</code>
<code>testSearchEntriesShortcut</code>
<code>testSearchEntriesShortcutWithDnObjectAndFilterObject</code>
<code>testSearchEntriesShortcutWithOptionsArray</code>
<code>testSearchNoResult</code>
<code>testSearchNothingGetFirst</code>
<code>testSearchNothingIteration</code>
<code>testSearchNothingToArray</code>
<code>testSearchWithDnObjectAndFilterObject</code>
<code>testSearchWithOptionsArray</code>
<code>testSorting</code>
<code>testUnknownCollectionClassThrowsException</code>
<code>testUserIsAutomaticallyBoundOnOperationInDisconnectedState</code>
<code>testUserIsAutomaticallyBoundOnOperationInUnboundState</code>
</MissingReturnType>
<MixedArgument occurrences="2">
<code>$entry['ou']</code>
<code>$entry['ou']</code>
</MixedArgument>
<MixedArrayAccess occurrences="3">
<code>$item['l']</code>
<code>$item['l']</code>
<code>$item['l'][0]</code>
</MixedArrayAccess>
<MixedAssignment occurrences="3">
<code>$item</code>
<code>$item</code>
<code>$item</code>
</MixedAssignment>
<PossiblyFalseArgument occurrences="25">
<code>$dn2</code>
<code>$dn2</code>
<code>$dn2</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
</PossiblyFalseArgument>
<PossiblyNullArgument occurrences="6">
<code>$list->current()</code>
<code>$list->current()</code>
<code>$list->current()</code>
<code>$list->current()</code>
<code>$list->current()</code>
<code>$list->current()</code>
</PossiblyNullArgument>
<PossiblyNullArrayAccess occurrences="1">
<code>$item['l']</code>
</PossiblyNullArrayAccess>
<PossiblyNullArrayOffset occurrences="1">
<code>$lSorted</code>
</PossiblyNullArrayOffset>
<RedundantConditionGivenDocblockType occurrences="2">
<code>assertIsArray</code>
<code>assertIsArray</code>
</RedundantConditionGivenDocblockType>
<UnusedForeachValue occurrences="11">
<code>$item</code>
<code>$item</code>
<code>$item</code>
<code>$item</code>
<code>$item</code>
<code>$item</code>
<code>$item</code>
<code>$item</code>
<code>$item</code>
<code>$item</code>
<code>$item</code>
</UnusedForeachValue>
<UnusedVariable occurrences="7">
<code>$entry</code>
<code>$items</code>
<code>$items</code>
<code>$items</code>
<code>$key</code>
<code>$key</code>
<code>$key</code>
</UnusedVariable>
</file>
<file src="test/SortTest.php">
<InvalidScalarArgument occurrences="2">
<code>bin2hex($a)</code>
<code>bin2hex($b)</code>
</InvalidScalarArgument>
<MissingClosureParamType occurrences="4">
<code>$a</code>
<code>$a</code>
<code>$b</code>
<code>$b</code>
</MissingClosureParamType>
<MissingReturnType occurrences="3">
<code>testCustomSorting</code>
<code>testSettingCallable</code>
<code>testSorting</code>
</MissingReturnType>
<MixedArgument occurrences="4">
<code>$a</code>
<code>$a</code>
<code>$b</code>
<code>$b</code>
</MixedArgument>
<MixedArrayAccess occurrences="2">
<code>$reflectionEntries[$index]</code>
<code>$reflectionEntries[$index]</code>
</MixedArrayAccess>
<MixedAssignment occurrences="2">
<code>$reflectionEntries</code>
<code>$reflectionEntries</code>
</MixedAssignment>
<PossiblyFalseArgument occurrences="3">
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_WRITEABLE_SUBTREE')</code>
</PossiblyFalseArgument>
<UnusedClosureParam occurrences="2">
<code>$a</code>
<code>$b</code>
</UnusedClosureParam>
</file>
<file src="test/TestAsset/BuiltinFunctionMocks.php">
<MissingReturnType occurrences="1">
<code>createMocks</code>
</MissingReturnType>
</file>
<file src="test/bootstrap.php">
<PossiblyFalseArgument occurrences="2">
<code>getenv('TESTS_LAMINAS_LDAP_SASL_CERTIFICATE')</code>
<code>getenv('TESTS_LAMINAS_LDAP_SASL_KEY')</code>
</PossiblyFalseArgument>
</file>
</files>
laminas-ldap/src/Filter.php 0000644 00000012430 15240152650 0011633 0 ustar 00 <?php
namespace Laminas\Ldap;
use function func_get_args;
/**
* Laminas\Ldap\Filter.
*/
class Filter extends Filter\StringFilter
{
public const TYPE_EQUALS = '=';
public const TYPE_GREATER = '>';
public const TYPE_GREATEROREQUAL = '>=';
public const TYPE_LESS = '<';
public const TYPE_LESSOREQUAL = '<=';
public const TYPE_APPROX = '~=';
/**
* Creates an 'equals' filter.
* (attr=value)
*
* @param string $attr
* @param string $value
* @return Filter
*/
public static function equals($attr, $value)
{
return new static($attr, $value, self::TYPE_EQUALS, null, null);
}
/**
* Creates a 'begins with' filter.
* (attr=value*)
*
* @param string $attr
* @param string $value
* @return Filter
*/
public static function begins($attr, $value)
{
return new static($attr, $value, self::TYPE_EQUALS, null, '*');
}
/**
* Creates an 'ends with' filter.
* (attr=*value)
*
* @param string $attr
* @param string $value
* @return Filter
*/
public static function ends($attr, $value)
{
return new static($attr, $value, self::TYPE_EQUALS, '*', null);
}
/**
* Creates a 'contains' filter.
* (attr=*value*)
*
* @param string $attr
* @param string $value
* @return Filter
*/
public static function contains($attr, $value)
{
return new static($attr, $value, self::TYPE_EQUALS, '*', '*');
}
/**
* Creates a 'greater' filter.
* (attr>value)
*
* @param string $attr
* @param string $value
* @return Filter
*/
public static function greater($attr, $value)
{
return new static($attr, $value, self::TYPE_GREATER, null, null);
}
/**
* Creates a 'greater or equal' filter.
* (attr>=value)
*
* @param string $attr
* @param string $value
* @return Filter
*/
public static function greaterOrEqual($attr, $value)
{
return new static($attr, $value, self::TYPE_GREATEROREQUAL, null, null);
}
/**
* Creates a 'less' filter.
* (attr<value)
*
* @param string $attr
* @param string $value
* @return Filter
*/
public static function less($attr, $value)
{
return new static($attr, $value, self::TYPE_LESS, null, null);
}
/**
* Creates an 'less or equal' filter.
* (attr<=value)
*
* @param string $attr
* @param string $value
* @return Filter
*/
public static function lessOrEqual($attr, $value)
{
return new static($attr, $value, self::TYPE_LESSOREQUAL, null, null);
}
/**
* Creates an 'approx' filter.
* (attr~=value)
*
* @param string $attr
* @param string $value
* @return Filter
*/
public static function approx($attr, $value)
{
return new static($attr, $value, self::TYPE_APPROX, null, null);
}
/**
* Creates an 'any' filter.
* (attr=*)
*
* @param string $attr
* @return Filter
*/
public static function any($attr)
{
return new static($attr, '', self::TYPE_EQUALS, '*', null);
}
/**
* Creates a simple custom string filter.
*
* @param string $filter
* @return Filter\StringFilter
*/
public static function string($filter)
{
return new Filter\StringFilter($filter);
}
/**
* Creates a simple string filter to be used with a mask.
*
* @param string $mask
* @param string $value
* @return Filter\MaskFilter
*/
public static function mask($mask, $value)
{
return new Filter\MaskFilter($mask, $value);
}
/**
* Creates an 'and' filter.
*
* @param Filter\AbstractFilter $filter,...
* @return Filter\AndFilter
*/
public static function andFilter($filter)
{
return new Filter\AndFilter(func_get_args());
}
/**
* Creates an 'or' filter.
*
* @param Filter\AbstractFilter $filter,...
* @return Filter\OrFilter
*/
public static function orFilter($filter)
{
return new Filter\OrFilter(func_get_args());
}
/**
* Create a filter string.
*
* @param string $attr
* @param string $value
* @param string $filtertype
* @param string $prepend
* @param string $append
* @return string
*/
private static function createFilterString($attr, $value, $filtertype, $prepend = null, $append = null)
{
$str = $attr . $filtertype;
if ($prepend !== null) {
$str .= $prepend;
}
$str .= ldap_escape($value, '', LDAP_ESCAPE_FILTER);
if ($append !== null) {
$str .= $append;
}
return $str;
}
/**
* Creates a new Laminas\Ldap\Filter.
*
* @param string $attr
* @param string $value
* @param string $filtertype
* @param string $prepend
* @param string $append
*/
public function __construct($attr, $value, $filtertype, $prepend = null, $append = null)
{
$filter = static::createFilterString($attr, $value, $filtertype, $prepend, $append);
parent::__construct($filter);
}
}
laminas-ldap/src/Node.php 0000644 00000070423 15240152650 0011301 0 ustar 00 <?php
namespace Laminas\Ldap;
use ArrayAccess;
use Iterator;
use Laminas\EventManager\EventManager;
use Laminas\Ldap\Node\Collection;
use RecursiveIterator;
use ReturnTypeWillChange;
use function array_key_exists;
use function array_merge;
use function class_exists;
use function count;
use function in_array;
use function is_array;
use function is_string;
use function strtolower;
/**
* Laminas\Ldap\Node provides an object oriented view into a LDAP node.
*/
class Node extends Node\AbstractNode implements Iterator, RecursiveIterator
{
/**
* Holds the node's new Dn if node is renamed.
*
* @var Dn
*/
protected $newDn;
/**
* Holds the node's original attributes (as loaded).
*
* @var array
*/
protected $originalData;
/**
* This node will be added
*
* @var bool
*/
protected $new;
/**
* This node will be deleted
*
* @var bool
*/
protected $delete;
/**
* Holds the connection to the LDAP server if in connected mode.
*
* @var Ldap
*/
protected $ldap;
/**
* Holds an array of the current node's children.
*
* @var Node[]
*/
protected $children;
/**
* Controls iteration status
*/
private bool $iteratorRewind = false;
/** @var EventManager */
protected $events;
/**
* Constructor is protected to enforce the use of factory methods.
*
* @param array $data
* @param bool $fromDataSource
* @throws Exception\LdapException
*/
protected function __construct(Dn $dn, array $data, $fromDataSource, ?Ldap $ldap = null)
{
parent::__construct($dn, $data, $fromDataSource);
if ($ldap !== null) {
$this->attachLdap($ldap);
} else {
$this->detachLdap();
}
}
/**
* Serialization callback
*
* Only Dn and attributes will be serialized.
*
* @return array
*/
public function __sleep()
{
return [
'dn',
'currentData',
'newDn',
'originalData',
'new',
'delete',
'children',
];
}
/**
* Deserialization callback
*
* Enforces a detached node.
*/
public function __wakeup()
{
$this->detachLdap();
}
/**
* Gets the current LDAP connection.
*
* @return Ldap
* @throws Exception\LdapException
*/
public function getLdap()
{
if ($this->ldap === null) {
throw new Exception\LdapException(
null,
'No LDAP connection specified.',
Exception\LdapException::LDAP_OTHER
);
}
return $this->ldap;
}
/**
* Attach node to an LDAP connection
*
* This is an offline method.
*
* @return Node Provides a fluid interface
* @throws Exception\LdapException
*/
public function attachLdap(Ldap $ldap)
{
if (! Dn::isChildOf($this->_getDn(), $ldap->getBaseDn())) {
throw new Exception\LdapException(
null,
'LDAP connection is not responsible for given node.',
Exception\LdapException::LDAP_OTHER
);
}
if ($ldap !== $this->ldap) {
$this->ldap = $ldap;
if (is_array($this->children)) {
foreach ($this->children as $child) {
$child->attachLdap($ldap);
}
}
}
return $this;
}
/**
* Detach node from LDAP connection
*
* This is an offline method.
*
* @return Node Provides a fluid interface
*/
public function detachLdap()
{
$this->ldap = null;
if (is_array($this->children)) {
foreach ($this->children as $child) {
$child->detachLdap();
}
}
return $this;
}
/**
* Checks if the current node is attached to a LDAP server.
*
* This is an offline method.
*
* @return bool
*/
public function isAttached()
{
return $this->ldap !== null;
}
/**
* Trigger an event
*
* @param string $event Event name
* @param array|ArrayAccess $argv Array of arguments; typically, should be associative
*/
protected function triggerEvent($event, $argv = [])
{
$events = $this->getEventManager();
if (! $events) {
return;
}
$events->trigger($event, $this, $argv);
}
/**
* @param array $data
* @param bool $fromDataSource
* @throws Exception\LdapException
*/
protected function loadData(array $data, $fromDataSource)
{
parent::loadData($data, $fromDataSource);
if ($fromDataSource === true) {
$this->originalData = $data;
} else {
$this->originalData = [];
}
$this->children = null;
$this->markAsNew($fromDataSource !== true);
$this->markAsToBeDeleted(false);
}
/**
* Factory method to create a new detached Laminas\Ldap\Node for a given DN.
*
* @param string|array|Dn $dn
* @param array $objectClass
* @return Node
* @throws Exception\LdapException
*/
public static function create($dn, array $objectClass = [])
{
if (is_string($dn) || is_array($dn)) {
$dn = Dn::factory($dn);
} elseif ($dn instanceof Dn) {
$dn = clone $dn;
} else {
throw new Exception\LdapException(null, '$dn is of a wrong data type.');
}
$new = new static($dn, [], false, null);
$new->ensureRdnAttributeValues();
$new->setAttribute('objectClass', $objectClass);
return $new;
}
/**
* Factory method to create an attached Laminas\Ldap\Node for a given DN.
*
* @param string|array|Dn $dn
* @return Node|null
* @throws Exception\LdapException
*/
public static function fromLdap($dn, Ldap $ldap)
{
if (is_string($dn) || is_array($dn)) {
$dn = Dn::factory($dn);
} elseif ($dn instanceof Dn) {
$dn = clone $dn;
} else {
throw new Exception\LdapException(null, '$dn is of a wrong data type.');
}
$data = $ldap->getEntry($dn, ['*', '+'], true);
if ($data === null) {
return;
}
return new static($dn, $data, true, $ldap);
}
/**
* Factory method to create a detached Laminas\Ldap\Node from array data.
*
* @param array $data
* @param bool $fromDataSource
* @return Node
* @throws Exception\LdapException
*/
public static function fromArray(array $data, $fromDataSource = false)
{
if (! array_key_exists('dn', $data)) {
throw new Exception\LdapException(null, '\'dn\' key is missing in array.');
}
if (is_string($data['dn']) || is_array($data['dn'])) {
$dn = Dn::factory($data['dn']);
} elseif ($data['dn'] instanceof Dn) {
$dn = clone $data['dn'];
} else {
throw new Exception\LdapException(null, '\'dn\' key is of a wrong data type.');
}
$fromDataSource = $fromDataSource === true;
$new = new static($dn, $data, $fromDataSource, null);
$new->ensureRdnAttributeValues();
return $new;
}
/**
* Ensures that teh RDN attributes are correctly set.
*
* @param bool $overwrite True to overwrite the RDN attributes
* @return void
*/
protected function ensureRdnAttributeValues($overwrite = false)
{
foreach ($this->getRdnArray() as $key => $value) {
if (! array_key_exists($key, $this->currentData) || $overwrite) {
Attribute::setAttribute($this->currentData, $key, $value, false);
} elseif (! in_array($value, $this->currentData[$key])) {
Attribute::setAttribute($this->currentData, $key, $value, true);
}
}
}
/**
* Marks this node as new.
*
* Node will be added (instead of updated) on calling update() if $new is true.
*
* @param bool $new
*/
protected function markAsNew($new)
{
$this->new = (bool) $new;
}
/**
* Tells if the node is considered as new (not present on the server)
*
* Please note, that this doesn't tell you if the node is present on the server.
* Use {@link exists()} to see if a node is already there.
*
* @return bool
*/
public function isNew()
{
return $this->new;
}
/**
* Marks this node as to be deleted.
*
* Node will be deleted on calling update() if $delete is true.
*
* @param bool $delete
*/
protected function markAsToBeDeleted($delete)
{
$this->delete = (bool) $delete;
}
/**
* Is this node going to be deleted once update() is called?
*
* @return bool
*/
public function willBeDeleted()
{
return $this->delete;
}
/**
* Marks this node as to be deleted
*
* Node will be deleted on calling update() if $delete is true.
*
* @return Node Provides a fluid interface
*/
public function delete()
{
$this->markAsToBeDeleted(true);
return $this;
}
/**
* Is this node going to be moved once update() is called?
*
* @return bool
*/
public function willBeMoved()
{
if ($this->isNew() || $this->willBeDeleted()) {
return false;
} elseif ($this->newDn !== null) {
// non-strict comparison necessary here, as we compare two objects by value
return $this->dn != $this->newDn; // phpcs:ignore
}
return false;
}
/**
* Sends all pending changes to the LDAP server
*
* @return Node Provides a fluid interface
* @throws Exception\LdapException
* @trigger pre-delete
* @trigger post-delete
* @trigger pre-add
* @trigger post-add
* @trigger pre-rename
* @trigger post-rename
* @trigger pre-update
* @trigger post-update
*/
public function update(?Ldap $ldap = null)
{
if ($ldap !== null) {
$this->attachLdap($ldap);
}
$ldap = $this->getLdap();
if (! $ldap instanceof Ldap) {
throw new Exception\LdapException(null, 'No LDAP connection available');
}
if ($this->willBeDeleted()) {
if ($ldap->exists($this->dn)) {
$this->triggerEvent('pre-delete');
$ldap->delete($this->dn);
$this->triggerEvent('post-delete');
}
return $this;
}
if ($this->isNew()) {
$this->triggerEvent('pre-add');
$data = $this->getData();
$ldap->add($this->_getDn(), $data);
$this->loadData($data, true);
$this->triggerEvent('post-add');
return $this;
}
$changedData = $this->getChangedData();
if ($this->willBeMoved()) {
$this->triggerEvent('pre-rename');
$recursive = $this->hasChildren();
$ldap->rename($this->dn, $this->newDn, $recursive, false);
foreach ($this->newDn->getRdn() as $key => $value) {
if (array_key_exists($key, $changedData)) {
unset($changedData[$key]);
}
}
$this->dn = $this->newDn;
$this->newDn = null;
$this->triggerEvent('post-rename');
}
if (count($changedData) > 0) {
$this->triggerEvent('pre-update');
$ldap->update($this->_getDn(), $changedData);
$this->triggerEvent('post-update');
}
$this->originalData = $this->currentData;
return $this;
}
/**
* Gets the DN of the current node as a Laminas\Ldap\Dn.
*
* This is an offline method.
*
* @return Dn
*/
// @codingStandardsIgnoreStart
protected function _getDn()
{
// @codingStandardsIgnoreEnd
return $this->newDn ?? parent::_getDn();
}
/**
* Gets the current DN of the current node as a Laminas\Ldap\Dn.
* The method returns a clone of the node's DN to prohibit modification.
*
* This is an offline method.
*
* @return Dn
*/
public function getCurrentDn()
{
return clone parent::_getDn();
}
/**
* Sets the new DN for this node
*
* This is an offline method.
*
* @param Dn|string|array $newDn
* @throws Exception\LdapException
* @return Node Provides a fluid interface
*/
public function setDn($newDn)
{
if ($newDn instanceof Dn) {
$this->newDn = clone $newDn;
} else {
$this->newDn = Dn::factory($newDn);
}
$this->ensureRdnAttributeValues(true);
return $this;
}
/**
* {@see setDn()}
*
* This is an offline method.
*
* @param Dn|string|array $newDn
* @throws Exception\LdapException
* @return Node Provides a fluid interface
*/
public function move($newDn)
{
return $this->setDn($newDn);
}
/**
* {@see setDn()}
*
* This is an offline method.
*
* @param Dn|string|array $newDn
* @throws Exception\LdapException
* @return Node Provides a fluid interface
*/
public function rename($newDn)
{
return $this->setDn($newDn);
}
/**
* Sets the objectClass.
*
* This is an offline method.
*
* @param array|string $value
* @return Node Provides a fluid interface
* @throws Exception\LdapException
*/
public function setObjectClass($value)
{
$this->setAttribute('objectClass', $value);
return $this;
}
/**
* Appends to the objectClass.
*
* This is an offline method.
*
* @param array|string $value
* @return Node Provides a fluid interface
* @throws Exception\LdapException
*/
public function appendObjectClass($value)
{
$this->appendToAttribute('objectClass', $value);
return $this;
}
/**
* Returns a LDIF representation of the current node
*
* @param array $options Additional options used during encoding
* @return string
*/
public function toLdif(array $options = [])
{
$attributes = array_merge(['dn' => $this->getDnString()], $this->getData(false));
return Ldif\Encoder::encode($attributes, $options);
}
/**
* Gets changed node data.
*
* The array contains all changed attributes.
* This format can be used in {@link Laminas\Ldap\Ldap::add()} and {@link Laminas\Ldap\Ldap::update()}.
*
* This is an offline method.
*
* @return array
*/
public function getChangedData()
{
$changed = [];
foreach ($this->currentData as $key => $value) {
if (! array_key_exists($key, $this->originalData) && ! empty($value)) {
$changed[$key] = $value;
} elseif ($this->originalData[$key] !== $this->currentData[$key]) {
$changed[$key] = $value;
}
}
return $changed;
}
/**
* Returns all changes made.
*
* This is an offline method.
*
* @return array
*/
public function getChanges()
{
$changes = [
'add' => [],
'delete' => [],
'replace' => [],
];
foreach ($this->currentData as $key => $value) {
if (! array_key_exists($key, $this->originalData) && ! empty($value)) {
$changes['add'][$key] = $value;
} elseif (count($this->originalData[$key]) === 0 && ! empty($value)) {
$changes['add'][$key] = $value;
} elseif ($this->originalData[$key] !== $this->currentData[$key]) {
if (empty($value)) {
$changes['delete'][$key] = $value;
} else {
$changes['replace'][$key] = $value;
}
}
}
return $changes;
}
/**
* Sets a LDAP attribute.
*
* This is an offline method.
*
* @param string $name
* @param mixed $value
* @return Node Provides a fluid interface
* @throws Exception\LdapException
*/
public function setAttribute($name, $value)
{
$this->_setAttribute($name, $value, false);
return $this;
}
/**
* Appends to a LDAP attribute.
*
* This is an offline method.
*
* @param string $name
* @param mixed $value
* @return Node Provides a fluid interface
* @throws Exception\LdapException
*/
public function appendToAttribute($name, $value)
{
$this->_setAttribute($name, $value, true);
return $this;
}
/**
* Checks if the attribute can be set and sets it accordingly.
*
* @param string $name
* @param mixed $value
* @param bool $append
* @throws Exception\LdapException
*/
// @codingStandardsIgnoreStart
protected function _setAttribute($name, $value, $append)
{
// @codingStandardsIgnoreEnd
$this->assertChangeableAttribute($name);
Attribute::setAttribute($this->currentData, $name, $value, $append);
}
/**
* Sets a LDAP date/time attribute.
*
* This is an offline method.
*
* @param string $name
* @param int|array $value
* @param bool $utc
* @return Node Provides a fluid interface
* @throws Exception\LdapException
*/
public function setDateTimeAttribute($name, $value, $utc = false)
{
$this->_setDateTimeAttribute($name, $value, $utc, false);
return $this;
}
/**
* Appends to a LDAP date/time attribute.
*
* This is an offline method.
*
* @param string $name
* @param int|array $value
* @param bool $utc
* @return Node Provides a fluid interface
* @throws Exception\LdapException
*/
public function appendToDateTimeAttribute($name, $value, $utc = false)
{
$this->_setDateTimeAttribute($name, $value, $utc, true);
return $this;
}
/**
* Checks if the attribute can be set and sets it accordingly.
*
* @param string $name
* @param int|array $value
* @param bool $utc
* @param bool $append
* @throws Exception\LdapException
*/
// @codingStandardsIgnoreStart
protected function _setDateTimeAttribute($name, $value, $utc, $append)
{
// @codingStandardsIgnoreEnd
$this->assertChangeableAttribute($name);
Attribute::setDateTimeAttribute($this->currentData, $name, $value, $utc, $append);
}
/**
* Sets a LDAP password.
*
* @param string $password
* @param string $hashType
* @param string $attribName
* @return Node Provides a fluid interface
* @throws Exception\LdapException
*/
public function setPasswordAttribute(
$password,
$hashType = Attribute::PASSWORD_HASH_MD5,
$attribName = 'userPassword'
) {
$this->assertChangeableAttribute($attribName);
Attribute::setPassword($this->currentData, $password, $hashType, $attribName);
return $this;
}
/**
* Deletes a LDAP attribute.
*
* This method deletes the attribute.
*
* This is an offline method.
*
* @param string $name
* @return Node Provides a fluid interface
* @throws Exception\LdapException
*/
public function deleteAttribute($name)
{
if ($this->existsAttribute($name, true)) {
$this->_setAttribute($name, null, false);
}
return $this;
}
/**
* Removes duplicate values from a LDAP attribute
*
* @param string $attribName
* @return void
*/
public function removeDuplicatesFromAttribute($attribName)
{
Attribute::removeDuplicatesFromAttribute($this->currentData, $attribName);
}
/**
* Remove given values from a LDAP attribute
*
* @param string $attribName
* @param mixed|array $value
* @return void
*/
public function removeFromAttribute($attribName, $value)
{
Attribute::removeFromAttribute($this->currentData, $attribName, $value);
}
/**
* @param string $name
* @return bool
* @throws Exception\LdapException
*/
protected function assertChangeableAttribute($name)
{
$name = strtolower($name);
$rdn = $this->getRdnArray(Dn::ATTR_CASEFOLD_LOWER);
if ($name === 'dn') {
throw new Exception\LdapException(null, 'DN cannot be changed.');
}
if (array_key_exists($name, $rdn)) {
throw new Exception\LdapException(null, 'Cannot change attribute because it\'s part of the RDN');
}
if (in_array($name, static::$systemAttributes)) {
throw new Exception\LdapException(null, 'Cannot change attribute because it\'s read-only');
}
return true;
}
/**
* Sets a LDAP attribute.
*
* This is an offline method.
*
* @param string $name
* @param mixed $value
*/
public function __set($name, $value)
{
$this->setAttribute($name, $value);
}
/**
* Deletes a LDAP attribute.
*
* This method deletes the attribute.
*
* This is an offline method.
*
* @param string $name
* @throws Exception\LdapException
*/
public function __unset($name)
{
$this->deleteAttribute($name);
}
/**
* Sets a LDAP attribute.
* Implements ArrayAccess.
*
* This is an offline method.
*
* @param string $name
* @param mixed $value
* @throws Exception\LdapException
*/
public function offsetSet($name, $value)
{
$this->setAttribute($name, $value);
}
/**
* Deletes a LDAP attribute.
* Implements ArrayAccess.
*
* This method deletes the attribute.
*
* This is an offline method.
*
* @param string $name
* @throws Exception\LdapException
*/
public function offsetUnset($name)
{
$this->deleteAttribute($name);
}
/**
* Check if node exists on LDAP.
*
* This is an online method.
*
* @return bool
* @throws Exception\LdapException
*/
public function exists(?Ldap $ldap = null)
{
if ($ldap !== null) {
$this->attachLdap($ldap);
}
$ldap = $this->getLdap();
return $ldap->exists($this->_getDn());
}
/**
* Reload node attributes from LDAP.
*
* This is an online method.
*
* @return Node Provides a fluid interface
* @throws Exception\LdapException
*/
public function reload(?Ldap $ldap = null)
{
if ($ldap !== null) {
$this->attachLdap($ldap);
}
$ldap = $this->getLdap();
parent::reload($ldap);
return $this;
}
/**
* Search current subtree with given options.
*
* This is an online method.
*
* @param string|Filter\AbstractFilter $filter
* @param int $scope
* @param string $sort
* @return Collection
* @throws Exception\LdapException
*/
public function searchSubtree($filter, $scope = Ldap::SEARCH_SCOPE_SUB, $sort = null)
{
return $this->getLdap()->search(
$filter,
$this->_getDn(),
$scope,
['*', '+'],
$sort,
Collection::class
);
}
/**
* Count items in current subtree found by given filter.
*
* This is an online method.
*
* @param string|Filter\AbstractFilter $filter
* @param int $scope
* @return int
* @throws Exception\LdapException
*/
public function countSubtree($filter, $scope = Ldap::SEARCH_SCOPE_SUB)
{
return $this->getLdap()->count($filter, $this->_getDn(), $scope);
}
/**
* Count children of current node.
*
* This is an online method.
*
* @return int
* @throws Exception\LdapException
*/
public function countChildren()
{
return $this->countSubtree('(objectClass=*)', Ldap::SEARCH_SCOPE_ONE);
}
/**
* Gets children of current node.
*
* This is an online method.
*
* @param string|Filter\AbstractFilter $filter
* @param string $sort
* @return Collection
* @throws Exception\LdapException
*/
public function searchChildren($filter, $sort = null)
{
return $this->searchSubtree($filter, Ldap::SEARCH_SCOPE_ONE, $sort);
}
/**
* Checks if current node has children.
* Returns whether the current element has children.
*
* Can be used offline but returns false if children have not been retrieved yet.
*
* @return bool
* @throws Exception\LdapException
*/
#[ReturnTypeWillChange]
public function hasChildren()
{
if (! is_array($this->children)) {
if ($this->isAttached()) {
return $this->countChildren() > 0;
}
return false;
}
return count($this->children) > 0;
}
/**
* Returns the children for the current node.
*
* Can be used offline but returns an empty array if children have not been retrieved yet.
*
* @return Node\ChildrenIterator
* @throws Exception\LdapException
*/
#[ReturnTypeWillChange]
public function getChildren()
{
if (! is_array($this->children)) {
$this->children = [];
if ($this->isAttached()) {
$children = $this->searchChildren('(objectClass=*)', null);
foreach ($children as $child) {
$this->children[$child->getRdnString(Dn::ATTR_CASEFOLD_LOWER)] = $child;
}
}
}
return new Node\ChildrenIterator($this->children);
}
/**
* Returns the parent of the current node.
*
* @return Node
* @throws Exception\LdapException
*/
public function getParent(?Ldap $ldap = null)
{
if ($ldap !== null) {
$this->attachLdap($ldap);
}
$ldap = $this->getLdap();
$parentDn = $this->_getDn()->getParentDn(1);
return static::fromLdap($parentDn, $ldap);
}
/**
* Return the current attribute.
* Implements Iterator
*
* @return array
*/
#[ReturnTypeWillChange]
public function current()
{
return $this;
}
/**
* Return the attribute name.
* Implements Iterator
*
* @return string
*/
#[ReturnTypeWillChange]
public function key()
{
return $this->getRdnString();
}
/**
* Move forward to next attribute.
* Implements Iterator
*/
#[ReturnTypeWillChange]
public function next()
{
$this->iteratorRewind = false;
}
/**
* Rewind the Iterator to the first attribute.
* Implements Iterator
*/
#[ReturnTypeWillChange]
public function rewind()
{
$this->iteratorRewind = true;
}
/**
* Check if there is a current attribute
* after calls to rewind() or next().
* Implements Iterator
*
* @return bool
*/
#[ReturnTypeWillChange]
public function valid()
{
return $this->iteratorRewind;
}
/**
* Attempt to marshal an EventManager instance.
*
* If an instance is already available, return it.
*
* If the laminas-eventmanager component is not present, return nothing.
*
* Otherwise, marshal the instance in a version-agnostic way, and return
* it.
*
* @return null|EventManager
*/
private function getEventManager()
{
if ($this->events) {
return $this->events;
}
if (! class_exists(EventManager::class)) {
return;
}
$this->events = new EventManager();
$this->events->setIdentifiers([self::class]);
return $this->events;
}
}
laminas-ldap/src/ErrorHandler.php 0000644 00000004167 15240152650 0013005 0 ustar 00 <?php
namespace Laminas\Ldap;
use function restore_error_handler;
use function set_error_handler;
use const E_WARNING;
/**
* Handle Errors that might occur during execution of ldap_*-functions
*/
class ErrorHandler implements ErrorHandlerInterface
{
/** @var ErrorHandlerInterface The Errror-Handler instance */
protected static $errorHandler;
/**
* Start the Error-Handling
*
* You can specify which errors to handle by passing a combination of PHPs
* Error-constants like E_WARNING or E_NOTICE or E_WARNING ^ E_DEPRECATED
*
* @param int $level The Error-level(s) to handle by this ErrorHandler
* @return void
*/
public static function start($level = E_WARNING)
{
self::getErrorHandler()->startErrorHandling($level);
}
/**
* @param bool|false $throw
* @return mixed
*/
public static function stop($throw = false)
{
return self::getErrorHandler()->stopErrorHandling($throw);
}
/**
* Get an error handler
*
* @return ErrorHandlerInterface
*/
protected static function getErrorHandler()
{
if (! self::$errorHandler && ! self::$errorHandler instanceof ErrorHandlerInterface) {
self::$errorHandler = new self();
}
return self::$errorHandler;
}
/**
* This method does nothing on purpose.
*
* @see ErrorHandlerInterface::startErrorHandling()
*
* @param int $level
* @return void
*/
public function startErrorHandling($level = E_WARNING)
{
set_error_handler(static function ($errNo, $errString): void {
});
}
/**
* This method does nothing on purpose.
*
* @see ErrorHandlerInterface::stopErrorHandling()
*
* @param bool|false $throw
* @return void
*/
public function stopErrorHandling($throw = false)
{
restore_error_handler();
}
/**
* Set the error handler to be used
*
* @return void
*/
public static function setErrorHandler(ErrorHandlerInterface $errorHandler)
{
self::$errorHandler = $errorHandler;
}
}
laminas-ldap/src/Dn.php 0000644 00000055477 15240152650 0010771 0 ustar 00 <?php
namespace Laminas\Ldap;
use ArrayAccess;
use ReturnTypeWillChange;
use function array_change_key_case;
use function array_keys;
use function array_merge;
use function array_pop;
use function array_slice;
use function array_splice;
use function array_unshift;
use function count;
use function implode;
use function in_array;
use function is_array;
use function is_int;
use function is_string;
use function ksort;
use function preg_match;
use function str_replace;
use function strlen;
use function strtolower;
use function strtoupper;
use function substr;
use function trim;
use const CASE_LOWER;
use const CASE_UPPER;
use const SORT_STRING;
/**
* Laminas\Ldap\Dn provides an API for DN manipulation
*/
class Dn implements ArrayAccess
{
public const ATTR_CASEFOLD_NONE = 'none';
public const ATTR_CASEFOLD_UPPER = 'upper';
public const ATTR_CASEFOLD_LOWER = 'lower';
/**
* The default case fold to use
*
* @var string
*/
protected static $defaultCaseFold = self::ATTR_CASEFOLD_NONE;
/**
* The case fold used for this instance
*
* @var string
*/
protected $caseFold;
/**
* The DN data
*
* @var array
*/
protected $dn;
/**
* Creates a DN from an array or a string
*
* @param string|array $dn
* @param string|null $caseFold
* @return Dn
* @throws Exception\LdapException
*/
public static function factory($dn, $caseFold = null)
{
if (is_array($dn)) {
return static::fromArray($dn, $caseFold);
} elseif (is_string($dn)) {
return static::fromString($dn, $caseFold);
}
throw new Exception\LdapException(null, 'Invalid argument type for $dn');
}
/**
* Creates a DN from a string
*
* @param string $dn
* @param string|null $caseFold
* @return Dn
* @throws Exception\LdapException
*/
public static function fromString($dn, $caseFold = null)
{
$dn = trim($dn);
if (empty($dn)) {
$dnArray = [];
} else {
$dnArray = static::explodeDn((string) $dn);
}
return new static($dnArray, $caseFold);
}
/**
* Creates a DN from an array
*
* @param array $dn
* @param string|null $caseFold
* @return Dn
* @throws Exception\LdapException
*/
public static function fromArray(array $dn, $caseFold = null)
{
return new static($dn, $caseFold);
}
/**
* Constructor
*
* @param array $dn
* @param string|null $caseFold
*/
protected function __construct(array $dn, $caseFold)
{
$this->dn = $dn;
$this->setCaseFold($caseFold);
}
/**
* Gets the RDN of the current DN
*
* @param string $caseFold
* @return array
* @throws Exception\LdapException If DN has no RDN (empty array).
*/
public function getRdn($caseFold = null)
{
$caseFold = static::sanitizeCaseFold($caseFold, $this->caseFold);
return static::caseFoldRdn($this->get(0, 1, $caseFold), null);
}
/**
* Gets the RDN of the current DN as a string
*
* @param string $caseFold
* @return string
* @throws Exception\LdapException If DN has no RDN (empty array).
*/
public function getRdnString($caseFold = null)
{
$caseFold = static::sanitizeCaseFold($caseFold, $this->caseFold);
return static::implodeRdn($this->getRdn(), $caseFold);
}
/**
* Get the parent DN $levelUp levels up the tree
*
* @param int $levelUp
* @throws Exception\LdapException
* @return Dn
*/
public function getParentDn($levelUp = 1)
{
$levelUp = (int) $levelUp;
if ($levelUp < 1 || $levelUp >= count($this->dn)) {
throw new Exception\LdapException(null, 'Cannot retrieve parent DN with given $levelUp');
}
$newDn = array_slice($this->dn, $levelUp);
return new static($newDn, $this->caseFold);
}
/**
* Get a DN part
*
* @param int $index
* @param int $length
* @param string $caseFold
* @return array
* @throws Exception\LdapException If index is illegal.
*/
public function get($index, $length = 1, $caseFold = null)
{
$caseFold = static::sanitizeCaseFold($caseFold, $this->caseFold);
$this->assertIndex($index);
$length = (int) $length;
if ($length <= 0) {
$length = 1;
}
if ($length === 1) {
return static::caseFoldRdn($this->dn[$index], $caseFold);
}
return static::caseFoldDn(array_slice($this->dn, $index, $length, false), $caseFold);
}
/**
* Set a DN part
*
* @param int $index
* @param array $value
* @return Dn Provides a fluent interface
* @throws Exception\LdapException If index is illegal.
*/
public function set($index, array $value)
{
$this->assertIndex($index);
static::assertRdn($value);
$this->dn[$index] = $value;
return $this;
}
/**
* Remove a DN part
*
* @param int $index
* @param int $length
* @return Dn Provides a fluent interface
* @throws Exception\LdapException If index is illegal.
*/
public function remove($index, $length = 1)
{
$this->assertIndex($index);
$length = (int) $length;
if ($length <= 0) {
$length = 1;
}
array_splice($this->dn, $index, $length, null);
return $this;
}
/**
* Append a DN part
*
* @param array $value
* @return Dn Provides a fluent interface
*/
public function append(array $value)
{
static::assertRdn($value);
$this->dn[] = $value;
return $this;
}
/**
* Prepend a DN part
*
* @param array $value
* @return Dn Provides a fluent interface
*/
public function prepend(array $value)
{
static::assertRdn($value);
array_unshift($this->dn, $value);
return $this;
}
/**
* Insert a DN part
*
* @param int $index
* @param array $value
* @return Dn Provides a fluent interface
* @throws Exception\LdapException If index is illegal.
*/
public function insert($index, array $value)
{
$this->assertIndex($index);
static::assertRdn($value);
$first = array_slice($this->dn, 0, $index + 1);
$second = array_slice($this->dn, $index + 1);
$this->dn = array_merge($first, [$value], $second);
return $this;
}
/**
* Assert index is correct and usable
*
* @param mixed $index
* @return bool
* @throws Exception\LdapException
*/
protected function assertIndex($index)
{
if (! is_int($index)) {
throw new Exception\LdapException(null, 'Parameter $index must be an integer');
}
if ($index < 0 || $index >= count($this->dn)) {
throw new Exception\LdapException(null, 'Parameter $index out of bounds');
}
return true;
}
/**
* Assert if value is in a correct RDN format
*
* @param array $value
* @return void
* @throws Exception\LdapException
*/
protected static function assertRdn(array $value)
{
if (count($value) < 1) {
throw new Exception\LdapException(null, 'RDN Array is malformed: it must have at least one item');
}
foreach (array_keys($value) as $key) {
if (! is_string($key)) {
throw new Exception\LdapException(null, 'RDN Array is malformed: it must use string keys');
}
}
}
/**
* Sets the case fold
*
* @param string|null $caseFold
*/
public function setCaseFold($caseFold)
{
$this->caseFold = static::sanitizeCaseFold($caseFold, static::$defaultCaseFold);
}
/**
* Return DN as a string
*
* @param string $caseFold
* @return string
* @throws Exception\LdapException
*/
public function toString($caseFold = null)
{
$caseFold = static::sanitizeCaseFold($caseFold, $this->caseFold);
return static::implodeDn($this->dn, $caseFold);
}
/**
* Return DN as an array
*
* @param string $caseFold
* @return array
*/
public function toArray($caseFold = null)
{
$caseFold = static::sanitizeCaseFold($caseFold, $this->caseFold);
if ($caseFold === self::ATTR_CASEFOLD_NONE) {
return $this->dn;
}
return static::caseFoldDn($this->dn, $caseFold);
}
/**
* Do a case folding on a RDN
*
* @param array $part
* @param string $caseFold
* @return array
*/
protected static function caseFoldRdn(array $part, $caseFold)
{
switch ($caseFold) {
case self::ATTR_CASEFOLD_UPPER:
return array_change_key_case($part, CASE_UPPER);
case self::ATTR_CASEFOLD_LOWER:
return array_change_key_case($part, CASE_LOWER);
case self::ATTR_CASEFOLD_NONE:
default:
return $part;
}
}
/**
* Do a case folding on a DN ort part of it
*
* @param array $dn
* @param string $caseFold
* @return array
*/
protected static function caseFoldDn(array $dn, $caseFold)
{
$return = [];
foreach ($dn as $part) {
$return[] = static::caseFoldRdn($part, $caseFold);
}
return $return;
}
/**
* Cast to string representation {@see toString()}
*
* @return string
*/
public function __toString()
{
return $this->toString();
}
/**
* Required by the ArrayAccess implementation
*
* @param int $offset
* @return bool
*/
#[ReturnTypeWillChange]
public function offsetExists($offset)
{
$offset = (int) $offset;
if ($offset < 0 || $offset >= count($this->dn)) {
return false;
}
return true;
}
/**
* Proxy to {@see get()}
* Required by the ArrayAccess implementation
*
* @param int $offset
* @return array
*/
#[ReturnTypeWillChange]
public function offsetGet($offset)
{
return $this->get($offset, 1, null);
}
/**
* Proxy to {@see set()}
* Required by the ArrayAccess implementation
*
* @param int $offset
* @param array $value
*/
#[ReturnTypeWillChange]
public function offsetSet($offset, $value)
{
$this->set($offset, $value);
}
/**
* Proxy to {@see remove()}
* Required by the ArrayAccess implementation
*
* @param int $offset
*/
#[ReturnTypeWillChange]
public function offsetUnset($offset)
{
$this->remove($offset, 1);
}
/**
* Sets the default case fold
*
* @param string $caseFold
*/
public static function setDefaultCaseFold($caseFold)
{
static::$defaultCaseFold = static::sanitizeCaseFold($caseFold, self::ATTR_CASEFOLD_NONE);
}
/**
* Sanitizes the case fold
*
* @param string $caseFold
* @param string $default
* @return string
*/
protected static function sanitizeCaseFold($caseFold, $default)
{
switch ($caseFold) {
case self::ATTR_CASEFOLD_NONE:
case self::ATTR_CASEFOLD_UPPER:
case self::ATTR_CASEFOLD_LOWER:
return $caseFold;
default:
return $default;
}
}
/**
* Escapes a DN value according to RFC 2253
*
* Escapes the given VALUES according to RFC 2253 so that they can be safely used in LDAP DNs.
* The characters ",", "+", """, "\", "<", ">", ";", "#", " = " with a special meaning in RFC 2252
* are preceded by ba backslash. Control characters with an ASCII code < 32 are represented as \hexpair.
* Finally all leading and trailing spaces are converted to sequences of \20.
*
* @link http://pear.php.net/package/Net_LDAP2
* @see Net_LDAP2_Util::escape_dn_value() from Benedikt Hallinger <beni@php.net>
*
* @param string|array $values An array containing the DN values that should be escaped
* @return array The array $values, but escaped
*/
public static function escapeValue($values = [])
{
if (! is_array($values)) {
$values = [$values];
}
foreach ($values as $key => $val) {
// Escaping of filter meta characters
$val = str_replace(
['\\', ',', '+', '"', '<', '>', ';', '#', '='],
['\\\\', '\,', '\+', '\"', '\<', '\>', '\;', '\#', '\='],
$val
);
$val = Converter\Converter::ascToHex32($val);
// Convert all leading and trailing spaces to sequences of \20.
if (preg_match('/^(\s*)(.+?)(\s*)$/', $val, $matches)) {
$val = $matches[2];
for ($i = 0, $len = strlen($matches[1]); $i < $len; $i++) {
$val = '\20' . $val;
}
for ($i = 0, $len = strlen($matches[3]); $i < $len; $i++) {
$val .= '\20';
}
}
if (null === $val) {
$val = '\0'; // apply escaped "null" if string is empty
}
$values[$key] = $val;
}
return count($values) === 1 ? $values[0] : $values;
}
/**
* Undoes the conversion done by {@link escapeValue()}.
*
* Any escape sequence starting with a baskslash - hexpair or special character -
* will be transformed back to the corresponding character.
*
* @link http://pear.php.net/package/Net_LDAP2
* @see Net_LDAP2_Util::escape_dn_value() from Benedikt Hallinger <beni@php.net>
*
* @param string|array $values Array of DN Values
* @return array Same as $values, but unescaped
*/
public static function unescapeValue($values = [])
{
if (! is_array($values)) {
$values = [$values];
}
foreach ($values as $key => $val) {
// strip slashes from special chars
$val = str_replace(
['\\\\', '\,', '\+', '\"', '\<', '\>', '\;', '\#', '\='],
['\\', ',', '+', '"', '<', '>', ';', '#', '='],
$val
);
$values[$key] = Converter\Converter::hex32ToAsc($val);
}
return count($values) === 1 ? $values[0] : $values;
}
/**
* Creates an array containing all parts of the given DN.
*
* Array will be of type
* array(
* array("cn" => "name1", "uid" => "user"),
* array("cn" => "name2"),
* array("dc" => "example"),
* array("dc" => "org")
* )
* for a DN of cn=name1+uid=user,cn=name2,dc=example,dc=org.
*
* @param string $dn
* @param array $keys An optional array to receive DN keys (e.g. CN, OU, DC, ...)
* @param array $vals An optional array to receive DN values
* @param string $caseFold
* @return array
* @throws Exception\LdapException
*/
public static function explodeDn(
$dn,
?array &$keys = null,
?array &$vals = null,
$caseFold = self::ATTR_CASEFOLD_NONE
) {
$k = [];
$v = [];
if (! self::checkDn($dn, $k, $v, $caseFold)) {
throw new Exception\LdapException(null, 'DN is malformed');
}
$ret = [];
for ($i = 0, $count = count($k); $i < $count; $i++) {
if (is_array($k[$i]) && is_array($v[$i]) && (($keyCount = count($k[$i])) === count($v[$i]))) {
$multi = [];
for ($j = 0; $j < $keyCount; $j++) {
$key = $k[$i][$j];
$val = $v[$i][$j];
$multi[$key] = $val;
}
$ret[] = $multi;
} elseif (is_string($k[$i]) && is_string($v[$i])) {
$ret[] = [$k[$i] => $v[$i]];
}
}
if ($keys !== null) {
$keys = $k;
}
if ($vals !== null) {
$vals = $v;
}
return $ret;
}
/**
* @param string $dn The DN to parse
* @param array $keys An optional array to receive DN keys (e.g. CN, OU, DC, ...)
* @param array $vals An optional array to receive DN values
* @param string $caseFold
* @return bool True if the DN was successfully parsed or false if the string is not a valid DN.
*/
public static function checkDn(
$dn,
?array &$keys = null,
?array &$vals = null,
$caseFold = self::ATTR_CASEFOLD_NONE
) {
/* This is a classic state machine parser. Each iteration of the
* loop processes one character. State 1 collects the key. When equals ( = )
* is encountered the state changes to 2 where the value is collected
* until a comma (,) or semicolon (;) is encountered after which we switch back
* to state 1. If a backslash (\) is encountered, state 3 is used to collect the
* following character without engaging the logic of other states.
*/
$slen = strlen($dn);
$state = 1;
$ko = $vo = 0;
$multi = false;
$ka = [];
$va = [];
for ($di = 0; $di <= $slen; $di++) {
$ch = $di === $slen ? 0 : $dn[$di];
switch ($state) {
case 1: // collect key
if ($ch === '=') {
$key = trim(substr($dn, $ko, $di - $ko));
if ($caseFold === self::ATTR_CASEFOLD_LOWER) {
$key = strtolower($key);
} elseif ($caseFold === self::ATTR_CASEFOLD_UPPER) {
$key = strtoupper($key);
}
if (is_array($multi)) {
$keyId = strtolower($key);
if (in_array($keyId, $multi)) {
return false;
}
$ka[count($ka) - 1][] = $key;
$multi[] = $keyId;
} else {
$ka[] = $key;
}
$state = 2;
$vo = $di + 1;
} elseif ($ch === ',' || $ch === ';' || $ch === '+') {
return false;
}
break;
case 2: // collect value
if ($ch === '\\') {
$state = 3;
} elseif ($ch === ',' || $ch === ';' || $ch === 0 || $ch === '+') {
$value = static::unescapeValue(trim(substr($dn, $vo, $di - $vo)));
if (is_array($multi)) {
$va[count($va) - 1][] = $value;
} else {
$va[] = $value;
}
$state = 1;
$ko = $di + 1;
if ($ch === '+' && $multi === false) {
$lastKey = array_pop($ka);
$lastVal = array_pop($va);
$ka[] = [$lastKey];
$va[] = [$lastVal];
$multi = [strtolower($lastKey)];
} elseif ($ch === ',' || $ch === ';' || $ch === 0) {
$multi = false;
}
} elseif ($ch === '=') {
return false;
}
break;
case 3: // escaped
$state = 2;
break;
}
}
if ($keys !== null) {
$keys = $ka;
}
if ($vals !== null) {
$vals = $va;
}
return $state === 1 && $ko > 0;
}
/**
* Returns a DN part in the form $attribute = $value
*
* This method supports the creation of multi-valued RDNs
* $part must contain an even number of elements.
*
* @param array $part
* @param string $caseFold
* @return string
* @throws Exception\LdapException
*/
public static function implodeRdn(array $part, $caseFold = null)
{
static::assertRdn($part);
$part = static::caseFoldRdn($part, $caseFold);
$rdnParts = [];
foreach ($part as $key => $value) {
$value = static::escapeValue($value);
$keyId = strtolower($key);
$rdnParts[$keyId] = implode('=', [$key, $value]);
}
ksort($rdnParts, SORT_STRING);
return implode('+', $rdnParts);
}
/**
* Implodes an array in the form delivered by {@link explodeDn()}
* to a DN string.
*
* $dnArray must be of type
* array(
* array("cn" => "name1", "uid" => "user"),
* array("cn" => "name2"),
* array("dc" => "example"),
* array("dc" => "org")
* )
*
* @param array $dnArray
* @param string $caseFold
* @param string $separator
* @return string
* @throws Exception\LdapException
*/
public static function implodeDn(array $dnArray, $caseFold = null, $separator = ',')
{
$parts = [];
foreach ($dnArray as $p) {
$parts[] = static::implodeRdn($p, $caseFold);
}
return implode($separator, $parts);
}
/**
* Checks if given $childDn is beneath $parentDn subtree.
*
* @param string|Dn $childDn
* @param string|Dn $parentDn
* @return bool
*/
public static function isChildOf($childDn, $parentDn)
{
try {
$keys = [];
$vals = [];
if ($childDn instanceof Dn) {
$cdn = $childDn->toArray(self::ATTR_CASEFOLD_LOWER);
} else {
$cdn = static::explodeDn($childDn, $keys, $vals, self::ATTR_CASEFOLD_LOWER);
}
if ($parentDn instanceof Dn) {
$pdn = $parentDn->toArray(self::ATTR_CASEFOLD_LOWER);
} else {
$pdn = static::explodeDn($parentDn, $keys, $vals, self::ATTR_CASEFOLD_LOWER);
}
} catch (Exception\LdapException $e) {
return false;
}
$startIndex = count($cdn) - count($pdn);
if ($startIndex < 0) {
return false;
}
for ($i = 0, $count = count($pdn); $i < $count; $i++) {
// do not force strict comparison via CS: unsafe here.
if ($cdn[$i + $startIndex] != $pdn[$i]) { // phpcs:ignore
return false;
}
}
return true;
}
}
laminas-ldap/src/Collection/DefaultIterator.php 0000644 00000026015 15240152650 0015603 0 ustar 00 <?php
namespace Laminas\Ldap\Collection;
use Countable;
use Iterator;
use Laminas\Ldap;
use Laminas\Ldap\ErrorHandler;
use Laminas\Ldap\Exception;
use Laminas\Ldap\Exception\LdapException;
use Laminas\Ldap\Handler;
use ReturnTypeWillChange;
use function array_change_key_case;
use function call_user_func;
use function current;
use function function_exists;
use function is_array;
use function is_callable;
use function is_string;
use function ksort;
use function method_exists;
use function next;
use function reset;
use function strtolower;
use function strtoupper;
use function usort;
use const CASE_LOWER;
use const SORT_LOCALE_STRING;
/**
* Laminas\Ldap\Collection\DefaultIterator is the default collection iterator implementation
* using ext/ldap
*/
class DefaultIterator implements Iterator, Countable
{
public const ATTRIBUTE_TO_LOWER = 1;
public const ATTRIBUTE_TO_UPPER = 2;
public const ATTRIBUTE_NATIVE = 3;
/**
* LDAP Connection
*
* @var \Laminas\Ldap\Ldap
*/
protected $ldap;
/**
* Result identifier resource
*
* @var resource|null
*/
protected $resultId;
/**
* Current result entry identifier
*
* @var resource|null
*/
protected $current;
/**
* Number of items in query result
*
* @var int
*/
protected $itemCount = -1;
/**
* The method that will be applied to the attribute's names.
*
* @var integer|callable
*/
protected $attributeNameTreatment = self::ATTRIBUTE_TO_LOWER;
/**
* This array holds a list of resources and sorting-values.
*
* Each result is represented by an array containing the keys <var>resource</var>
* which holds a resource of a result-item and the key <var>sortValue</var>
* which holds the value by which the array will be sorted.
*
* The resources will be filled on creating the instance and the sorting values
* on sorting.
*
* @var array
*/
protected $entries = [];
/**
* The function to sort the entries by
*
* @var callable
*/
protected $sortFunction;
/**
* @param resource $resultId
* @throws LdapException If no entries was found.
*/
public function __construct(Ldap\Ldap $ldap, $resultId)
{
$this->setSortFunction('strnatcasecmp');
$this->ldap = $ldap;
$this->resultId = $resultId;
$resource = $ldap->getResource();
ErrorHandler::start();
$this->itemCount = ldap_count_entries($resource, $resultId);
ErrorHandler::stop();
if ($this->itemCount === false) {
throw new Exception\LdapException($this->ldap, 'counting entries');
}
$identifier = ldap_first_entry(
$ldap->getResource(),
$resultId
);
while (false !== $identifier) {
$this->entries[] = [
'resource' => $identifier,
'sortValue' => '',
];
$identifier = ldap_next_entry(
$ldap->getResource(),
$identifier
);
}
}
public function __destruct()
{
$this->close();
}
/**
* Closes the current result set
*
* @return bool
*/
public function close()
{
$isClosed = false;
if (Handler::isResultHandle($this->resultId)) {
ErrorHandler::start();
$isClosed = ldap_free_result($this->resultId);
ErrorHandler::stop();
$this->resultId = null;
$this->current = null;
}
return $isClosed;
}
/**
* Gets the current LDAP connection.
*
* @return \Laminas\Ldap\Ldap
*/
public function getLDAP()
{
return $this->ldap;
}
/**
* Sets the attribute name treatment.
*
* Can either be one of the following constants
* - Laminas\Ldap\Collection\DefaultIterator::ATTRIBUTE_TO_LOWER
* - Laminas\Ldap\Collection\DefaultIterator::ATTRIBUTE_TO_UPPER
* - Laminas\Ldap\Collection\DefaultIterator::ATTRIBUTE_NATIVE
* or a valid callback accepting the attribute's name as it's only
* argument and returning the new attribute's name.
*
* @param int|callable $attributeNameTreatment
* @return DefaultIterator Provides a fluent interface
*/
public function setAttributeNameTreatment($attributeNameTreatment)
{
if (is_callable($attributeNameTreatment)) {
if (is_string($attributeNameTreatment) && ! function_exists($attributeNameTreatment)) {
$this->attributeNameTreatment = self::ATTRIBUTE_TO_LOWER;
} elseif (
is_array($attributeNameTreatment)
&& ! method_exists($attributeNameTreatment[0], $attributeNameTreatment[1])
) {
$this->attributeNameTreatment = self::ATTRIBUTE_TO_LOWER;
} else {
$this->attributeNameTreatment = $attributeNameTreatment;
}
} else {
$attributeNameTreatment = (int) $attributeNameTreatment;
switch ($attributeNameTreatment) {
case self::ATTRIBUTE_TO_LOWER:
case self::ATTRIBUTE_TO_UPPER:
case self::ATTRIBUTE_NATIVE:
$this->attributeNameTreatment = $attributeNameTreatment;
break;
default:
$this->attributeNameTreatment = self::ATTRIBUTE_TO_LOWER;
break;
}
}
return $this;
}
/**
* Returns the currently set attribute name treatment
*
* @return int|callable
*/
public function getAttributeNameTreatment()
{
return $this->attributeNameTreatment;
}
/**
* Returns the number of items in current result
* Implements Countable
*
* @return int
*/
#[ReturnTypeWillChange]
public function count()
{
return $this->itemCount;
}
/**
* Return the current result item
* Implements Iterator
*
* @return array|null
* @throws LdapException
*/
#[ReturnTypeWillChange]
public function current()
{
if (! Handler::isResultEntryHandle($this->current)) {
$this->rewind();
}
if (! Handler::isResultEntryHandle($this->current)) {
return;
}
$entry = ['dn' => $this->key()];
$resource = $this->ldap->getResource();
ErrorHandler::start();
$name = ldap_first_attribute($resource, $this->current);
ErrorHandler::stop();
while ($name) {
ErrorHandler::start();
$data = ldap_get_values_len($resource, $this->current, $name);
ErrorHandler::stop();
if (! $data) {
$data = [];
}
if (isset($data['count'])) {
unset($data['count']);
}
switch ($this->attributeNameTreatment) {
case self::ATTRIBUTE_TO_LOWER:
$attrName = strtolower($name);
break;
case self::ATTRIBUTE_TO_UPPER:
$attrName = strtoupper($name);
break;
case self::ATTRIBUTE_NATIVE:
$attrName = $name;
break;
default:
$attrName = call_user_func($this->attributeNameTreatment, $name);
break;
}
$entry[$attrName] = $data;
ErrorHandler::start();
$name = ldap_next_attribute($resource, $this->current);
ErrorHandler::stop();
}
ksort($entry, SORT_LOCALE_STRING);
return $entry;
}
/**
* Return the result item key
* Implements Iterator
*
* @throws LdapException
* @return string|null
*/
#[ReturnTypeWillChange]
public function key()
{
if (! Handler::isResultEntryHandle($this->current)) {
$this->rewind();
}
if (Handler::isResultEntryHandle($this->current)) {
$resource = $this->ldap->getResource();
ErrorHandler::start();
$currentDn = ldap_get_dn($resource, $this->current);
ErrorHandler::stop();
if ($currentDn === false) {
throw new Exception\LdapException($this->ldap, 'getting dn');
}
return $currentDn;
} else {
return;
}
}
/**
* Move forward to next result item
*
* @see Iterator
*
* @return void
*/
#[ReturnTypeWillChange]
public function next()
{
next($this->entries);
$nextEntry = current($this->entries);
$this->current = $nextEntry['resource'] ?? null;
}
/**
* Rewind the Iterator to the first result item
*
* @see Iterator
*
* @return void
*/
#[ReturnTypeWillChange]
public function rewind()
{
reset($this->entries);
$nextEntry = current($this->entries);
$this->current = $nextEntry['resource'] ?? null;
}
/**
* Check if there is a current result item
* after calls to rewind() or next()
* Implements Iterator
*
* @return bool
*/
#[ReturnTypeWillChange]
public function valid()
{
return Handler::isResultEntryHandle($this->current);
}
/**
* Set a sorting-algorithm for this iterator
*
* The callable has to accept two parameters that will be compared.
*
* @param callable $sortFunction The algorithm to be used for sorting
* @return DefaultIterator Provides a fluent interface
*/
public function setSortFunction(callable $sortFunction)
{
$this->sortFunction = $sortFunction;
return $this;
}
/**
* Sort the iterator
*
* Sorting is done using the set sortFunction which is by default strnatcasecmp.
*
* The attribute is determined by lowercasing everything.
*
* The sort-value will be the first value of the attribute.
*
* @param string $sortAttribute The attribute to sort by. If not given the
* value set via setSortAttribute is used.
* @return void
*/
public function sort($sortAttribute)
{
foreach ($this->entries as $key => $entry) {
$attributes = ldap_get_attributes(
$this->ldap->getResource(),
$entry['resource']
);
$attributes = array_change_key_case($attributes, CASE_LOWER);
if (isset($attributes[$sortAttribute][0])) {
$this->entries[$key]['sortValue'] =
$attributes[$sortAttribute][0];
}
}
$sortFunction = $this->sortFunction;
$sorted = usort(
$this->entries,
static fn($a, $b) =>
$sortFunction($a['sortValue'], $b['sortValue'])
);
if (! $sorted) {
throw new Exception\LdapException($this, 'sorting result-set');
}
}
}
laminas-ldap/src/Converter/Exception/InvalidArgumentException.php 0000644 00000000227 15240152650 0021264 0 ustar 00 <?php
namespace Laminas\Ldap\Converter\Exception;
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
laminas-ldap/src/Converter/Exception/UnexpectedValueException.php 0000644 00000000227 15240152650 0021274 0 ustar 00 <?php
namespace Laminas\Ldap\Converter\Exception;
class UnexpectedValueException extends \UnexpectedValueException implements ExceptionInterface
{
}
laminas-ldap/src/Converter/Exception/ExceptionInterface.php 0000644 00000000125 15240152650 0020070 0 ustar 00 <?php
namespace Laminas\Ldap\Converter\Exception;
interface ExceptionInterface
{
}
laminas-ldap/src/Converter/Exception/ConverterException.php 0000644 00000000221 15240152650 0020134 0 ustar 00 <?php
namespace Laminas\Ldap\Converter\Exception;
use Exception;
class ConverterException extends Exception implements ExceptionInterface
{
}
laminas-ldap/src/Converter/Converter.php 0000644 00000033600 15240152650 0014326 0 ustar 00 <?php
namespace Laminas\Ldap\Converter;
use DateTime;
use DateTimeZone;
use Exception as PHPException;
use Laminas\Ldap\ErrorHandler;
use function chr;
use function date_default_timezone_get;
use function dechex;
use function get_resource_type;
use function hexdec;
use function is_array;
use function is_bool;
use function is_float;
use function is_int;
use function is_numeric;
use function is_object;
use function is_resource;
use function is_scalar;
use function is_string;
use function ord;
use function preg_match;
use function preg_replace_callback;
use function serialize;
use function str_pad;
use function str_replace;
use function stream_get_contents;
use function strlen;
use function strtolower;
use function substr;
use function unserialize;
use const E_NOTICE;
use const STR_PAD_LEFT;
/**
* Laminas\Ldap\Converter is a collection of useful LDAP related conversion functions.
*/
class Converter
{
public const STANDARD = 0;
public const BOOLEAN = 1;
public const GENERALIZED_TIME = 2;
/**
* Converts all ASCII chars < 32 to "\HEX"
*
* @link http://pear.php.net/package/Net_LDAP2
* @see Net_LDAP2_Util::asc2hex32() from Benedikt Hallinger <beni@php.net>
*
* @param string $string String to convert
* @return string
*/
public static function ascToHex32($string)
{
for ($i = 0, $len = strlen($string); $i < $len; $i++) {
$char = substr($string, $i, 1);
if (ord($char) < 32) {
$hex = dechex(ord($char));
if (strlen($hex) === 1) {
$hex = '0' . $hex;
}
$string = str_replace($char, '\\' . $hex, $string);
}
}
return $string;
}
/**
* Converts all Hex expressions ("\HEX") to their original ASCII characters
*
* @link http://pear.php.net/package/Net_LDAP2
* @see Net_LDAP2_Util::hex2asc() from Benedikt Hallinger <beni@php.net>,
* heavily based on work from DavidSmith@byu.net
*
* @param string $string String to convert
* @return string
*/
public static function hex32ToAsc($string)
{
$string = preg_replace_callback(
'/\\\([0-9A-Fa-f]{2})/',
static fn($matches): string => chr(hexdec($matches[1])),
$string
);
return $string;
}
/**
* Convert any value to an LDAP-compatible value.
*
* By setting the <var>$type</var>-parameter the conversion of a certain
* type can be forced
*
* @param mixed $value The value to convert
* @param int $type The conversion type to use
* @return string|null
* @throws Exception\ConverterException
*/
public static function toLdap($value, $type = self::STANDARD)
{
try {
switch ($type) {
case self::BOOLEAN:
return static::toLdapBoolean($value);
case self::GENERALIZED_TIME:
return static::toLdapDatetime($value);
default:
if (is_string($value)) {
return $value;
} elseif (is_int($value) || is_float($value)) {
return (string) $value;
} elseif (is_bool($value)) {
return static::toLdapBoolean($value);
} elseif (is_object($value)) {
if ($value instanceof DateTime) {
return static::toLdapDatetime($value);
} else {
return static::toLdapSerialize($value);
}
} elseif (is_array($value)) {
return static::toLdapSerialize($value);
} elseif (is_resource($value) && get_resource_type($value) === 'stream') {
return stream_get_contents($value);
}
return null;
}
} catch (PHPException $e) {
throw new Exception\ConverterException($e->getMessage(), $e->getCode(), $e);
}
}
/**
* Converts a date-entity to an LDAP-compatible date-string
*
* The date-entity <var>$date</var> can be either a timestamp, a
* DateTime Object, a string that is parseable by strtotime().
*
* @param int|string|DateTime $date The date-entity
* @param bool $asUtc Whether to return the LDAP-compatible date-string as UTC or as local value
* @return string
* @throws Exception\InvalidArgumentException
*/
public static function toLdapDateTime($date, $asUtc = true)
{
if (! $date instanceof DateTime) {
if (is_int($date)) {
$date = new DateTime('@' . $date);
$date->setTimezone(new DateTimeZone(date_default_timezone_get()));
} elseif (is_string($date)) {
$date = new DateTime($date);
} else {
throw new Exception\InvalidArgumentException('Parameter $date is not of the expected type');
}
}
$timezone = $date->format('O');
if (true === $asUtc) {
$date->setTimezone(new DateTimeZone('UTC'));
$timezone = 'Z';
}
if ('+0000' === $timezone) {
$timezone = 'Z';
}
return $date->format('YmdHis') . $timezone;
}
/**
* Convert a boolean value to an LDAP-compatible string
*
* This converts a boolean value of TRUE, an integer-value of 1 and a
* case-insensitive string 'true' to an LDAP-compatible 'TRUE'. All other
* other values are converted to an LDAP-compatible 'FALSE'.
*
* @param bool|int|string $value The boolean value to encode
* @return string
*/
public static function toLdapBoolean($value)
{
$return = 'FALSE';
if (! is_scalar($value)) {
return $return;
}
if (true === $value || (is_string($value) && 'true' === strtolower($value)) || 1 === $value) {
$return = 'TRUE';
}
return $return;
}
/**
* Serialize any value for storage in LDAP
*
* @param mixed $value The value to serialize
* @return string
*/
public static function toLdapSerialize($value)
{
return serialize($value);
}
/**
* Convert an LDAP-compatible value to a corresponding PHP-value.
*
* By setting the <var>$type</var>-parameter the conversion of a certain
* type can be forced.
*
* @see Converter::STANDARD
* @see Converter::BOOLEAN
* @see Converter::GENERALIZED_TIME
*
* @param string $value The value to convert
* @param int $type The conversion type to use
* @param bool $dateTimeAsUtc Return DateTime values in UTC timezone
* @return mixed
*/
public static function fromLdap($value, $type = self::STANDARD, $dateTimeAsUtc = true)
{
switch ($type) {
case self::BOOLEAN:
return static::fromldapBoolean($value);
case self::GENERALIZED_TIME:
return static::fromLdapDateTime($value);
default:
if (is_numeric($value)) {
// prevent numeric values to be treated as date/time
return $value;
} elseif ('TRUE' === $value || 'FALSE' === $value) {
return static::fromLdapBoolean($value);
}
if (preg_match('/^\d{4}[\d\+\-Z\.]*$/', $value)) {
return static::fromLdapDateTime($value, $dateTimeAsUtc);
}
try {
return static::fromLdapUnserialize($value);
} catch (Exception\UnexpectedValueException $e) {
// Do nothing
}
break;
}
return $value;
}
/**
* Convert an LDAP-Generalized-Time-entry into a DateTime-Object
*
* CAVEAT: The DateTime-Object returned will always be set to UTC-Timezone.
*
* @param string $date The generalized-Time
* @param bool $asUtc Return the DateTime with UTC timezone
* @return DateTime
* @throws Exception\InvalidArgumentException If a non-parseable-format is given.
*/
public static function fromLdapDateTime($date, $asUtc = true)
{
$datepart = [];
if (! preg_match('/^(\d{4})/', $date, $datepart)) {
throw new Exception\InvalidArgumentException('Invalid date format found');
}
if ($datepart[1] < 4) {
throw new Exception\InvalidArgumentException('Invalid date format found (too short)');
}
$time = [
// The year is mandatory!
'year' => $datepart[1],
'month' => 1,
'day' => 1,
'hour' => 0,
'minute' => 0,
'second' => 0,
'offdir' => '+',
'offsethours' => 0,
'offsetminutes' => 0,
];
$length = strlen($date);
// Check for month.
if ($length >= 6) {
$month = substr($date, 4, 2);
if ($month < 1 || $month > 12) {
throw new Exception\InvalidArgumentException('Invalid date format found (invalid month)');
}
$time['month'] = $month;
}
// Check for day
if ($length >= 8) {
$day = substr($date, 6, 2);
if ($day < 1 || $day > 31) {
throw new Exception\InvalidArgumentException('Invalid date format found (invalid day)');
}
$time['day'] = $day;
}
// Check for Hour
if ($length >= 10) {
$hour = substr($date, 8, 2);
if ($hour < 0 || $hour > 23) {
throw new Exception\InvalidArgumentException('Invalid date format found (invalid hour)');
}
$time['hour'] = $hour;
}
// Check for minute
if ($length >= 12) {
$minute = substr($date, 10, 2);
if ($minute < 0 || $minute > 59) {
throw new Exception\InvalidArgumentException('Invalid date format found (invalid minute)');
}
$time['minute'] = $minute;
}
// Check for seconds
if ($length >= 14) {
$second = substr($date, 12, 2);
if ($second < 0 || $second > 59) {
throw new Exception\InvalidArgumentException('Invalid date format found (invalid second)');
}
$time['second'] = $second;
}
// Set Offset
$offsetRegEx = '/([Z\-\+])(\d{2}\'?){0,1}(\d{2}\'?){0,1}$/';
$off = [];
if (preg_match($offsetRegEx, $date, $off)) {
$offset = $off[1];
if ($offset === '+' || $offset === '-') {
$time['offdir'] = $offset;
// we have an offset, so lets calculate it.
if (isset($off[2])) {
$offsetHours = substr($off[2], 0, 2);
if ($offsetHours < 0 || $offsetHours > 12) {
throw new Exception\InvalidArgumentException('Invalid date format found (invalid offset hour)');
}
$time['offsethours'] = $offsetHours;
}
if (isset($off[3])) {
$offsetMinutes = substr($off[3], 0, 2);
if ($offsetMinutes < 0 || $offsetMinutes > 59) {
throw new Exception\InvalidArgumentException(
'Invalid date format found (invalid offset minute)'
);
}
$time['offsetminutes'] = $offsetMinutes;
}
}
}
// Raw-Data is present, so lets create a DateTime-Object from it.
$timestring = $time['year'] . '-'
. str_pad($time['month'], 2, '0', STR_PAD_LEFT) . '-'
. str_pad($time['day'], 2, '0', STR_PAD_LEFT) . ' '
. str_pad($time['hour'], 2, '0', STR_PAD_LEFT) . ':'
. str_pad($time['minute'], 2, '0', STR_PAD_LEFT) . ':'
. str_pad($time['second'], 2, '0', STR_PAD_LEFT)
. $time['offdir']
. str_pad($time['offsethours'], 2, '0', STR_PAD_LEFT)
. str_pad($time['offsetminutes'], 2, '0', STR_PAD_LEFT);
try {
$date = new DateTime($timestring);
} catch (PHPException $e) {
throw new Exception\InvalidArgumentException(
'Invalid date format found',
0,
$e
);
}
if ($asUtc) {
$date->setTimezone(new DateTimeZone('UTC'));
}
return $date;
}
/**
* Convert an LDAP-compatible boolean value into a PHP-compatible one
*
* @param string $value The value to convert
* @return bool
* @throws Exception\InvalidArgumentException
*/
public static function fromLdapBoolean($value)
{
if ('TRUE' === $value) {
return true;
} elseif ('FALSE' === $value) {
return false;
} else {
throw new Exception\InvalidArgumentException('The given value is not a boolean value');
}
}
/**
* Unserialize a serialized value to return the corresponding object
*
* @param string $value The value to convert
* @return mixed
* @throws Exception\UnexpectedValueException
*/
public static function fromLdapUnserialize($value)
{
ErrorHandler::start(E_NOTICE);
$v = unserialize($value);
ErrorHandler::stop();
if (false === $v && $value !== 'b:0;') {
throw new Exception\UnexpectedValueException('The given value could not be unserialized');
}
return $v;
}
}
laminas-ldap/src/Exception/InvalidArgumentException.php 0000644 00000000215 15240152650 0017312 0 ustar 00 <?php
namespace Laminas\Ldap\Exception;
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
laminas-ldap/src/Exception/LdapException.php 0000644 00000013355 15240152650 0015112 0 ustar 00 <?php
namespace Laminas\Ldap\Exception;
use Exception;
use Laminas\Ldap\Ldap;
use function dechex;
class LdapException extends Exception implements ExceptionInterface
{
public const LDAP_SUCCESS = 0x00;
public const LDAP_OPERATIONS_ERROR = 0x01;
public const LDAP_PROTOCOL_ERROR = 0x02;
public const LDAP_TIMELIMIT_EXCEEDED = 0x03;
public const LDAP_SIZELIMIT_EXCEEDED = 0x04;
public const LDAP_COMPARE_FALSE = 0x05;
public const LDAP_COMPARE_TRUE = 0x06;
public const LDAP_AUTH_METHOD_NOT_SUPPORTED = 0x07;
public const LDAP_STRONG_AUTH_REQUIRED = 0x08;
public const LDAP_PARTIAL_RESULTS = 0x09;
public const LDAP_REFERRAL = 0x0a;
public const LDAP_ADMINLIMIT_EXCEEDED = 0x0b;
public const LDAP_UNAVAILABLE_CRITICAL_EXTENSION = 0x0c;
public const LDAP_CONFIDENTIALITY_REQUIRED = 0x0d;
public const LDAP_SASL_BIND_IN_PROGRESS = 0x0e;
public const LDAP_NO_SUCH_ATTRIBUTE = 0x10;
public const LDAP_UNDEFINED_TYPE = 0x11;
public const LDAP_INAPPROPRIATE_MATCHING = 0x12;
public const LDAP_CONSTRAINT_VIOLATION = 0x13;
public const LDAP_TYPE_OR_VALUE_EXISTS = 0x14;
public const LDAP_INVALID_SYNTAX = 0x15;
public const LDAP_NO_SUCH_OBJECT = 0x20;
public const LDAP_ALIAS_PROBLEM = 0x21;
public const LDAP_INVALID_DN_SYNTAX = 0x22;
public const LDAP_IS_LEAF = 0x23;
public const LDAP_ALIAS_DEREF_PROBLEM = 0x24;
public const LDAP_PROXY_AUTHZ_FAILURE = 0x2F;
public const LDAP_INAPPROPRIATE_AUTH = 0x30;
public const LDAP_INVALID_CREDENTIALS = 0x31;
public const LDAP_INSUFFICIENT_ACCESS = 0x32;
public const LDAP_BUSY = 0x33;
public const LDAP_UNAVAILABLE = 0x34;
public const LDAP_UNWILLING_TO_PERFORM = 0x35;
public const LDAP_LOOP_DETECT = 0x36;
public const LDAP_NAMING_VIOLATION = 0x40;
public const LDAP_OBJECT_CLASS_VIOLATION = 0x41;
public const LDAP_NOT_ALLOWED_ON_NONLEAF = 0x42;
public const LDAP_NOT_ALLOWED_ON_RDN = 0x43;
public const LDAP_ALREADY_EXISTS = 0x44;
public const LDAP_NO_OBJECT_CLASS_MODS = 0x45;
public const LDAP_RESULTS_TOO_LARGE = 0x46;
public const LDAP_AFFECTS_MULTIPLE_DSAS = 0x47;
public const LDAP_OTHER = 0x50;
public const LDAP_SERVER_DOWN = 0x51;
public const LDAP_LOCAL_ERROR = 0x52;
public const LDAP_ENCODING_ERROR = 0x53;
public const LDAP_DECODING_ERROR = 0x54;
public const LDAP_TIMEOUT = 0x55;
public const LDAP_AUTH_UNKNOWN = 0x56;
public const LDAP_FILTER_ERROR = 0x57;
public const LDAP_USER_CANCELLED = 0x58;
public const LDAP_PARAM_ERROR = 0x59;
public const LDAP_NO_MEMORY = 0x5a;
public const LDAP_CONNECT_ERROR = 0x5b;
public const LDAP_NOT_SUPPORTED = 0x5c;
public const LDAP_CONTROL_NOT_FOUND = 0x5d;
public const LDAP_NO_RESULTS_RETURNED = 0x5e;
public const LDAP_MORE_RESULTS_TO_RETURN = 0x5f;
public const LDAP_CLIENT_LOOP = 0x60;
public const LDAP_REFERRAL_LIMIT_EXCEEDED = 0x61;
public const LDAP_CUP_RESOURCES_EXHAUSTED = 0x71;
public const LDAP_CUP_SECURITY_VIOLATION = 0x72;
public const LDAP_CUP_INVALID_DATA = 0x73;
public const LDAP_CUP_UNSUPPORTED_SCHEME = 0x74;
public const LDAP_CUP_RELOAD_REQUIRED = 0x75;
public const LDAP_CANCELLED = 0x76;
public const LDAP_NO_SUCH_OPERATION = 0x77;
public const LDAP_TOO_LATE = 0x78;
public const LDAP_CANNOT_CANCEL = 0x79;
public const LDAP_ASSERTION_FAILED = 0x7A;
public const LDAP_SYNC_REFRESH_REQUIRED = 0x1000;
public const LDAP_X_SYNC_REFRESH_REQUIRED = 0x4100;
public const LDAP_X_NO_OPERATION = 0x410e;
public const LDAP_X_ASSERTION_FAILED = 0x410f;
public const LDAP_X_NO_REFERRALS_FOUND = 0x4110;
public const LDAP_X_CANNOT_CHAIN = 0x4111;
/* internal error code constants */
public const LDAP_X_DOMAIN_MISMATCH = 0x7001;
public const LDAP_X_EXTENSION_NOT_LOADED = 0x7002;
/**
* @param Ldap $ldap Laminas\Ldap\Ldap object
* @param string $str Informative exception message
* @param int $code LDAP error code
*/
public function __construct(?Ldap $ldap = null, $str = null, $code = 0)
{
$errorMessages = [];
$message = '';
if ($ldap !== null) {
$oldCode = $code;
$message = $ldap->getLastError($code, $errorMessages) . ': ';
if ($code === 0) {
$message = '';
$code = $oldCode;
}
}
if (empty($message)) {
if ($code > 0) {
$message = '0x' . dechex($code) . ': ';
}
}
if (! empty($str)) {
$message .= $str;
} else {
$message .= 'no exception message';
}
parent::__construct($message, $code);
}
}
laminas-ldap/src/Exception/ExceptionInterface.php 0000644 00000000113 15240152650 0016116 0 ustar 00 <?php
namespace Laminas\Ldap\Exception;
interface ExceptionInterface
{
}
laminas-ldap/src/Exception/BadMethodCallException.php 0000644 00000000211 15240152650 0016640 0 ustar 00 <?php
namespace Laminas\Ldap\Exception;
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
}
laminas-ldap/src/ErrorHandlerInterface.php 0000644 00000001172 15240152650 0014617 0 ustar 00 <?php
namespace Laminas\Ldap;
use const E_WARNING;
/**
* Handle Errors that might occur during execution of ldap_*-functions
*/
interface ErrorHandlerInterface
{
/**
* Start the ErrorHandling-process
*
* @param int $level
* @return void
*/
public function startErrorHandling($level = E_WARNING);
/**
* Stop the error-handling process.
*
* The parameter <var>$throw</var> handles whether the captured errors shall
* be thrown as Exceptions or not
*
* @param bool|false $throw
* @return mixed
*/
public function stopErrorHandling($throw = false);
}
laminas-ldap/src/Handler.php 0000644 00000003703 15240152651 0011767 0 ustar 00 <?php
namespace Laminas\Ldap;
use LDAP\Connection;
use LDAP\Result;
use LDAP\ResultEntry;
use function is_a;
use function is_object;
use function is_resource;
use function version_compare;
use const PHP_VERSION;
/**
* Laminas\Ldap\Handler is a collection of LDAP handler related functions.
*/
class Handler
{
/**
* @param mixed $handle
* @param class-string<Connection>|class-string<ResultEntry>|class-string<Result> $handleClassName
* @psalm-assert-if-true resource|Connection|Result|ResultEntry $handle
*/
private static function isHandle($handle, string $handleClassName): bool
{
$useResource = version_compare(PHP_VERSION, '8.1.0') < 0;
return ($useResource && is_resource($handle))
|| (! $useResource && is_object($handle) && is_a($handle, $handleClassName));
}
/**
* Checks if the given handle is an LDAP connection object or a resource based on the running PHP version.
*
* @param mixed $handle
* @return bool
* @psalm-assert-if-true resource|Connection $handle
*/
public static function isLdapHandle($handle)
{
return self::isHandle($handle, Connection::class);
}
/**
* Checks if the given handle is an LDAP result object or a resource based on the running PHP version.
*
* @param mixed $handle
* @return bool
* @psalm-assert-if-true resource|Result $handle
*/
public static function isResultHandle($handle)
{
return self::isHandle($handle, Result::class);
}
/**
* Checks if the given handle is an LDAP result entry object or a resource based on the running PHP version.
*
* @param mixed $handle
* @return bool
* @psalm-assert-if-true resource|ResultEntry $handle
*/
public static function isResultEntryHandle($handle)
{
return self::isHandle($handle, ResultEntry::class);
}
}
laminas-ldap/src/Filter/MaskFilter.php 0000644 00000001620 15240152651 0013674 0 ustar 00 <?php
namespace Laminas\Ldap\Filter;
use function array_shift;
use function count;
use function func_get_args;
use function vsprintf;
/**
* Laminas\Ldap\Filter\MaskFilter provides a simple string filter to be used with a mask.
*/
class MaskFilter extends StringFilter
{
/**
* Creates a Laminas\Ldap\Filter\MaskFilter.
*
* @param string $mask
* @param string $value,...
*/
public function __construct($mask, $value)
{
$args = func_get_args();
array_shift($args);
for ($i = 0, $count = count($args); $i < $count; $i++) {
$args[$i] = static::escapeValue($args[$i]);
}
$filter = vsprintf($mask, $args);
parent::__construct($filter);
}
/**
* Returns a string representation of the filter.
*
* @return string
*/
public function toString()
{
return $this->filter;
}
}
laminas-ldap/src/Filter/StringFilter.php 0000644 00000001164 15240152651 0014252 0 ustar 00 <?php
namespace Laminas\Ldap\Filter;
/**
* Laminas\Ldap\Filter\StringFilter provides a simple custom string filter.
*/
class StringFilter extends AbstractFilter
{
/**
* The filter.
*
* @var string
*/
protected $filter;
/**
* Creates a Laminas\Ldap\Filter\StringFilter.
*
* @param string $filter
*/
public function __construct($filter)
{
$this->filter = $filter;
}
/**
* Returns a string representation of the filter.
*
* @return string
*/
public function toString()
{
return '(' . $this->filter . ')';
}
}
laminas-ldap/src/Filter/NotFilter.php 0000644 00000001355 15240152651 0013546 0 ustar 00 <?php
namespace Laminas\Ldap\Filter;
/**
* Laminas\Ldap\Filter\NotFilter provides a negation filter.
*/
class NotFilter extends AbstractFilter
{
/**
* The underlying filter.
*/
private AbstractFilter $filter;
/**
* Creates a Laminas\Ldap\Filter\NotFilter.
*/
public function __construct(AbstractFilter $filter)
{
$this->filter = $filter;
}
/**
* Negates the filter.
*
* @return AbstractFilter
*/
public function negate()
{
return $this->filter;
}
/**
* Returns a string representation of the filter.
*
* @return string
*/
public function toString()
{
return '(!' . $this->filter->toString() . ')';
}
}
laminas-ldap/src/Filter/AbstractLogicalFilter.php 0000644 00000003277 15240152651 0016051 0 ustar 00 <?php
namespace Laminas\Ldap\Filter;
use function is_string;
/**
* Laminas\Ldap\Filter\AbstractLogicalFilter provides a base implementation for a grouping filter.
*/
abstract class AbstractLogicalFilter extends AbstractFilter
{
public const TYPE_AND = '&';
public const TYPE_OR = '|';
/**
* All the sub-filters for this grouping filter.
*/
private array $subfilters;
/**
* The grouping symbol.
*/
private string $symbol;
/**
* Creates a new grouping filter.
*
* @param array $subfilters
* @param string $symbol
* @throws Exception\FilterException
*/
protected function __construct(array $subfilters, $symbol)
{
foreach ($subfilters as $key => $s) {
if (is_string($s)) {
$subfilters[$key] = new StringFilter($s);
} elseif (! $s instanceof AbstractFilter) {
throw new Exception\FilterException('Only strings or Laminas\Ldap\Filter\AbstractFilter allowed.');
}
}
$this->subfilters = $subfilters;
$this->symbol = $symbol;
}
/**
* Adds a filter to this grouping filter.
*
* @return AbstractLogicalFilter
*/
public function addFilter(AbstractFilter $filter)
{
$new = clone $this;
$new->subfilters[] = $filter;
return $new;
}
/**
* Returns a string representation of the filter.
*
* @return string
*/
public function toString()
{
$return = '(' . $this->symbol;
foreach ($this->subfilters as $sub) {
$return .= $sub->toString();
}
$return .= ')';
return $return;
}
}
laminas-ldap/src/Filter/Exception/ExceptionInterface.php 0000644 00000000261 15240152651 0017350 0 ustar 00 <?php
namespace Laminas\Ldap\Filter\Exception;
use Laminas\Ldap\Exception\ExceptionInterface as MainLdapException;
interface ExceptionInterface extends MainLdapException
{
}
laminas-ldap/src/Filter/Exception/FilterException.php 0000644 00000000213 15240152652 0016673 0 ustar 00 <?php
namespace Laminas\Ldap\Filter\Exception;
use Exception;
class FilterException extends Exception implements ExceptionInterface
{
}
laminas-ldap/src/Filter/OrFilter.php 0000644 00000000560 15240152652 0013364 0 ustar 00 <?php
namespace Laminas\Ldap\Filter;
/**
* Laminas\Ldap\Filter\OrFilter provides an 'or' filter.
*/
class OrFilter extends AbstractLogicalFilter
{
/**
* Creates an 'or' grouping filter.
*
* @param array $subfilters
*/
public function __construct(array $subfilters)
{
parent::__construct($subfilters, self::TYPE_OR);
}
}
laminas-ldap/src/Filter/AbstractFilter.php 0000644 00000006744 15240152652 0014561 0 ustar 00 <?php
namespace Laminas\Ldap\Filter;
use Laminas\Ldap\Converter\Converter;
use function array_merge;
use function count;
use function func_get_args;
use function is_array;
use function str_replace;
/**
* Laminas\Ldap\Filter\AbstractFilter provides a base implementation for filters.
*/
abstract class AbstractFilter
{
/**
* Returns a string representation of the filter.
*
* @return string
*/
abstract public function toString();
/**
* Returns a string representation of the filter.
*
* @see toString()
*
* @return string
*/
public function __toString()
{
return $this->toString();
}
/**
* Negates the filter.
*
* @return AbstractFilter
*/
public function negate()
{
return new NotFilter($this);
}
/**
* Creates an 'and' filter.
*
* @param AbstractFilter $filter,...
* @return AndFilter
*/
public function addAnd($filter)
{
$fa = func_get_args();
$args = array_merge([$this], $fa);
return new AndFilter($args);
}
/**
* Creates an 'or' filter.
*
* @param AbstractFilter $filter,...
* @return OrFilter
*/
public function addOr($filter)
{
$fa = func_get_args();
$args = array_merge([$this], $fa);
return new OrFilter($args);
}
/**
* Escapes the given VALUES according to RFC 2254 so that they can be safely used in LDAP filters.
*
* Any control characters with an ACII code < 32 as well as the characters with special meaning in
* LDAP filters "*", "(", ")", and "\" (the backslash) are converted into the representation of a
* backslash followed by two hex digits representing the hexadecimal value of the character.
*
* @link http://pear.php.net/package/Net_LDAP2
* @see Net_LDAP2_Util::escape_filter_value() from Benedikt Hallinger <beni@php.net>
*
* @param string|array $values Array of values to escape
* @return array Array $values, but escaped
*/
public static function escapeValue($values = [])
{
if (! is_array($values)) {
$values = [$values];
}
foreach ($values as $key => $val) {
// Escaping of filter meta characters
$val = str_replace(['\\', '*', '(', ')'], ['\5c', '\2a', '\28', '\29'], $val);
// ASCII < 32 escaping
$val = Converter::ascToHex32($val);
if (null === $val) {
$val = '\0'; // apply escaped "null" if string is empty
}
$values[$key] = $val;
}
return count($values) === 1 ? $values[0] : $values;
}
/**
* Undoes the conversion done by {@link escapeValue()}.
*
* Converts any sequences of a backslash followed by two hex digits into the corresponding character.
*
* @link http://pear.php.net/package/Net_LDAP2
* @see Net_LDAP2_Util::escape_filter_value() from Benedikt Hallinger <beni@php.net>
*
* @param string|array $values Array of values to escape
* @return array Array $values, but unescaped
*/
public static function unescapeValue($values = [])
{
if (! is_array($values)) {
$values = [$values];
}
foreach ($values as $key => $value) {
// Translate hex code into ascii
$values[$key] = Converter::hex32ToAsc($value);
}
return count($values) === 1 ? $values[0] : $values;
}
}
laminas-ldap/src/Filter/AndFilter.php 0000644 00000000565 15240152652 0013513 0 ustar 00 <?php
namespace Laminas\Ldap\Filter;
/**
* Laminas\Ldap\Filter\AndFilter provides an 'and' filter.
*/
class AndFilter extends AbstractLogicalFilter
{
/**
* Creates an 'and' grouping filter.
*
* @param array $subfilters
*/
public function __construct(array $subfilters)
{
parent::__construct($subfilters, self::TYPE_AND);
}
}
laminas-ldap/src/Ldap.php 0000644 00000167676 15240152652 0011317 0 ustar 00 <?php
namespace Laminas\Ldap;
use Laminas\Ldap\Collection;
use Laminas\Ldap\Exception;
use Traversable;
use function array_change_key_case;
use function array_key_exists;
use function array_merge;
use function array_reverse;
use function array_shift;
use function array_values;
use function class_exists;
use function count;
use function dechex;
use function extension_loaded;
use function function_exists;
use function implode;
use function in_array;
use function is_array;
use function is_scalar;
use function is_string;
use function is_subclass_of;
use function iterator_to_array;
use function key;
use function mb_strtolower;
use function min;
use function preg_match_all;
use function sprintf;
use function str_replace;
use function strcasecmp;
use function strlen;
use function strpos;
use function strtolower;
use function substr;
use function trim;
use function usleep;
use const CASE_LOWER;
use const E_WARNING;
use const PREG_SET_ORDER;
class Ldap
{
public const SEARCH_SCOPE_SUB = 1;
public const SEARCH_SCOPE_ONE = 2;
public const SEARCH_SCOPE_BASE = 3;
public const ACCTNAME_FORM_DN = 1;
public const ACCTNAME_FORM_USERNAME = 2;
public const ACCTNAME_FORM_BACKSLASH = 3;
public const ACCTNAME_FORM_PRINCIPAL = 4;
/**
* String used with ldap_connect for error handling purposes.
*/
private ?string $connectString = null;
/**
* The options used in connecting, binding, etc.
*
* @var array
*/
protected $options;
/**
* The raw LDAP extension resource.
*
* @var resource|null
*/
protected $resource;
/**
* FALSE if no user is bound to the LDAP resource
* NULL if there has been an anonymous bind
* username of the currently bound user
*
* @var bool|null|string
*/
protected $boundUser = false;
/**
* Caches the RootDse
*
* @var Node\RootDse
*/
protected $rootDse;
/**
* Caches the schema
*
* @var Node\Schema
*/
protected $schema;
/**
* Current connection retry attempt counter.
*
* @var int
*/
protected $reconnectCount = 0;
/**
* Total number of times reconnections were attempted unsuccessfully.
*
* @var int
*/
protected $reconnectsAttempted = 0;
/** @var array */
protected $lastConnectBindParams = [];
/**
* @param array|Traversable $options Options used in connecting, binding, etc.
* @throws Exception\LdapException
*/
public function __construct($options = [])
{
if (! extension_loaded('ldap')) {
throw new Exception\LdapException(
null,
'LDAP extension not loaded',
Exception\LdapException::LDAP_X_EXTENSION_NOT_LOADED
);
}
$this->setOptions($options);
}
/**
* @return void
*/
public function __destruct()
{
$this->disconnect();
}
/**
* @return resource The raw LDAP extension resource.
*/
public function getResource()
{
if (! Handler::isLdapHandle($this->resource) || $this->boundUser === false) {
$this->bind();
}
return $this->resource;
}
/**
* Return the LDAP error number of the last LDAP command
*
* @return int
*/
public function getLastErrorCode()
{
ErrorHandler::start(E_WARNING);
$ret = false;
if (Handler::isLdapHandle($this->resource)) {
$ret = ldap_get_option($this->resource, LDAP_OPT_ERROR_NUMBER, $err);
}
ErrorHandler::stop();
if ($ret === true) {
if ($err <= -1 && $err >= -17) {
/* For some reason draft-ietf-ldapext-ldap-c-api-xx.txt error
* codes in OpenLDAP are negative values from -1 to -17.
*/
$err = Exception\LdapException::LDAP_SERVER_DOWN + (-$err - 1);
}
return $err;
}
return 0;
}
/**
* Return the LDAP error message of the last LDAP command
*
* @param int $errorCode
* @param array $errorMessages
* @return string
*/
public function getLastError(&$errorCode = null, ?array &$errorMessages = null)
{
$errorCode = $this->getLastErrorCode();
$errorMessages = [];
/* The various error retrieval functions can return
* different things so we just try to collect what we
* can and eliminate dupes.
*/
ErrorHandler::start(E_WARNING);
$estr1 = "getLastError: could not call ldap_error because LDAP resource was not of type resource";
if (Handler::isLdapHandle($this->resource)) {
$estr1 = ldap_error($this->resource);
}
ErrorHandler::stop();
if ($errorCode !== 0 && $estr1 === 'Success') {
ErrorHandler::start(E_WARNING);
$estr1 = ldap_err2str($errorCode);
ErrorHandler::stop();
}
if (! empty($estr1)) {
$errorMessages[] = $estr1;
}
ErrorHandler::start(E_WARNING);
$estr2 = "getLastError: could not call ldap_get_option because LDAP resource was not of type resource";
if (Handler::isLdapHandle($this->resource)) {
ldap_get_option($this->resource, LDAP_OPT_ERROR_STRING, $estr2);
}
ErrorHandler::stop();
if (! empty($estr2) && ! in_array($estr2, $errorMessages)) {
$errorMessages[] = $estr2;
}
$message = '';
if ($errorCode > 0) {
$message = '0x' . dechex($errorCode) . ' ';
}
if (count($errorMessages) > 0) {
$message .= '(' . implode('; ', $errorMessages) . ')';
} else {
$message .= '(no error message from LDAP)';
}
return $message;
}
/**
* Get the currently bound user
*
* FALSE if no user is bound to the LDAP resource
* NULL if there has been an anonymous bind
* username of the currently bound user
*
* @return bool|null|string
*/
public function getBoundUser()
{
return $this->boundUser;
}
/**
* Sets the options used in connecting, binding, etc.
*
* Valid option keys:
* host
* port
* useSsl
* username
* password
* bindRequiresDn
* baseDn
* accountCanonicalForm
* accountDomainName
* accountDomainNameShort
* accountFilterFormat
* allowEmptyPassword
* useStartTls
* optReferrals
* tryUsernameSplit
* reconnectAttempts
* networkTimeout
* saslOpts
*
* @param array|Traversable $options Options used in connecting, binding, etc.
* @return Ldap Provides a fluent interface
* @throws Exception\LdapException
*/
public function setOptions($options)
{
if ($options instanceof Traversable) {
$options = iterator_to_array($options);
}
$permittedOptions = [
'host' => null,
'port' => 0,
'useSsl' => false,
'username' => null,
'password' => null,
'bindRequiresDn' => false,
'baseDn' => null,
'accountCanonicalForm' => null,
'accountDomainName' => null,
'accountDomainNameShort' => null,
'accountFilterFormat' => null,
'allowEmptyPassword' => false,
'useStartTls' => false,
'optReferrals' => false,
'tryUsernameSplit' => true,
'reconnectAttempts' => 0,
'networkTimeout' => null,
'saslOpts' => null,
];
foreach ($permittedOptions as $key => $val) {
if (array_key_exists($key, $options)) {
$val = $options[$key];
unset($options[$key]);
/* Enforce typing. This eliminates issues like Laminas\Config\Reader\Ini
* returning '1' as a string (Laminas-3163).
*/
switch ($key) {
case 'port':
case 'accountCanonicalForm':
case 'reconnectAttempts':
case 'networkTimeout':
$permittedOptions[$key] = (int) $val;
break;
case 'useSsl':
case 'bindRequiresDn':
case 'allowEmptyPassword':
case 'useStartTls':
case 'optReferrals':
case 'tryUsernameSplit':
$permittedOptions[$key] = $val === true
|| $val === '1'
|| strcasecmp($val, 'true') === 0;
break;
case 'saslOpts':
$permittedOptions[$key] = $val;
break;
default:
$permittedOptions[$key] = trim((string) $val);
break;
}
}
}
if (count($options) > 0) {
$key = key($options);
throw new Exception\LdapException(null, "Unknown Laminas\\Ldap\\Ldap option: $key");
}
$this->options = $permittedOptions;
return $this;
}
/**
* @return array The current options.
*/
public function getOptions()
{
return $this->options;
}
/** @return int */
public function getReconnectsAttempted()
{
return $this->reconnectsAttempted;
}
/** @return void */
public function resetReconnectsAttempted()
{
$this->reconnectsAttempted = 0;
}
/**
* @return string The hostname of the LDAP server being used to
* authenticate accounts
*/
protected function getHost()
{
return $this->options['host'];
}
/**
* @return int The port of the LDAP server or 0 to indicate that no port
* value is set
*/
protected function getPort()
{
return $this->options['port'];
}
/**
* @return bool The default SSL / TLS encrypted transport control
*/
protected function getUseSsl()
{
return $this->options['useSsl'];
}
/**
* @return string The default acctname for binding
*/
protected function getUsername()
{
return $this->options['username'];
}
/**
* @return string The default password for binding
*/
protected function getPassword()
{
return $this->options['password'];
}
/**
* @return bool Bind requires DN
*/
protected function getBindRequiresDn()
{
return $this->options['bindRequiresDn'];
}
/**
* Gets the base DN under which objects of interest are located
*
* @return string
*/
public function getBaseDn()
{
return $this->options['baseDn'];
}
/**
* Gets any options that have been set for sasl binds.
*
* @return string[]|null
*/
public function getSaslOpts()
{
return $this->options['saslOpts'];
}
/**
* @return int Either ACCTNAME_FORM_BACKSLASH, ACCTNAME_FORM_PRINCIPAL or
* ACCTNAME_FORM_USERNAME indicating the form usernames should be canonicalized to.
*/
protected function getAccountCanonicalForm()
{
/* Account names should always be qualified with a domain. In some scenarios
* using non-qualified account names can lead to security vulnerabilities. If
* no account canonical form is specified, we guess based in what domain
* names have been supplied.
*/
$accountCanonicalForm = $this->options['accountCanonicalForm'];
if (! $accountCanonicalForm) {
$accountDomainName = $this->getAccountDomainName();
$accountDomainNameShort = $this->getAccountDomainNameShort();
if ($accountDomainNameShort) {
$accountCanonicalForm = self::ACCTNAME_FORM_BACKSLASH;
} else {
if ($accountDomainName) {
$accountCanonicalForm = self::ACCTNAME_FORM_PRINCIPAL;
} else {
$accountCanonicalForm = self::ACCTNAME_FORM_USERNAME;
}
}
}
return $accountCanonicalForm;
}
/**
* @return string The account domain name
*/
protected function getAccountDomainName()
{
return $this->options['accountDomainName'];
}
/**
* @return string The short account domain name
*/
protected function getAccountDomainNameShort()
{
return $this->options['accountDomainNameShort'];
}
/**
* @return string A format string for building an LDAP search filter to match
* an account
*/
protected function getAccountFilterFormat()
{
return $this->options['accountFilterFormat'];
}
/**
* @return bool Allow empty passwords
*/
protected function getAllowEmptyPassword()
{
return $this->options['allowEmptyPassword'];
}
/**
* @return bool The default SSL / TLS encrypted transport control
*/
protected function getUseStartTls()
{
return $this->options['useStartTls'];
}
/**
* @return bool Opt. Referrals
*/
protected function getOptReferrals()
{
return $this->options['optReferrals'];
}
/**
* @return bool Try splitting the username into username and domain
*/
protected function getTryUsernameSplit()
{
return $this->options['tryUsernameSplit'];
}
/**
* @return int The number of times reconnect to server should be attempted.
*/
protected function getReconnectsToAttempt()
{
return $this->options['reconnectAttempts'];
}
/**
* @return int The value for network timeout when connect to the LDAP server.
*/
protected function getNetworkTimeout()
{
return $this->options['networkTimeout'];
}
/**
* @param string $acctname
* @return string The LDAP search filter for matching directory accounts
*/
protected function getAccountFilter($acctname)
{
$dname = '';
$aname = '';
$this->splitName($acctname, $dname, $aname);
$accountFilterFormat = $this->getAccountFilterFormat();
$aname = Filter\AbstractFilter::escapeValue($aname);
if ($accountFilterFormat) {
return sprintf($accountFilterFormat, $aname);
}
if (! $this->getBindRequiresDn()) {
// is there a better way to detect this?
return sprintf("(&(objectClass=user)(sAMAccountName=%s))", $aname);
}
return sprintf("(&(objectClass=posixAccount)(uid=%s))", $aname);
}
/**
* @param string $name The name to split
* @param string $dname The resulting domain name (this is an out parameter)
* @param string $aname The resulting account name (this is an out parameter)
* @return void
*/
protected function splitName($name, &$dname, &$aname)
{
$dname = null;
$aname = $name;
if (! $this->getTryUsernameSplit()) {
return;
}
$pos = strpos($name, '@');
if ($pos) {
$dname = substr($name, $pos + 1);
$aname = substr($name, 0, $pos);
} else {
$pos = strpos($name, '\\');
if ($pos) {
$dname = substr($name, 0, $pos);
$aname = substr($name, $pos + 1);
}
}
}
/**
* @param string $acctname The name of the account
* @return string The DN of the specified account
* @throws Exception\LdapException
*/
protected function getAccountDn($acctname)
{
if (Dn::checkDn($acctname)) {
return $acctname;
}
$acctname = $this->getCanonicalAccountName($acctname, self::ACCTNAME_FORM_USERNAME);
$acct = $this->getAccount($acctname, ['dn']);
return $acct['dn'];
}
/**
* @param string $dname The domain name to check
* @return bool
*/
protected function isPossibleAuthority($dname)
{
if ($dname === null) {
return true;
}
$accountDomainName = $this->getAccountDomainName();
$accountDomainNameShort = $this->getAccountDomainNameShort();
if ($accountDomainName === null && $accountDomainNameShort === null) {
return true;
}
if (strcasecmp($dname, $accountDomainName) === 0) {
return true;
}
if (strcasecmp($dname, $accountDomainNameShort) === 0) {
return true;
}
return false;
}
/**
* @param string $acctname The name to canonicalize
* @param int $form The desired form of canonicalization
* @return string The canonicalized name in the desired form
* @throws Exception\LdapException
*/
public function getCanonicalAccountName($acctname, $form = 0)
{
$dname = '';
$uname = '';
$this->splitName($acctname, $dname, $uname);
if (! $this->isPossibleAuthority($dname)) {
throw new Exception\LdapException(
null,
"Binding domain is not an authority for user: $acctname",
Exception\LdapException::LDAP_X_DOMAIN_MISMATCH
);
}
if (! $uname) {
throw new Exception\LdapException(null, "Invalid account name syntax: $acctname");
}
if (function_exists('mb_strtolower')) {
$uname = mb_strtolower($uname, 'UTF-8');
} else {
$uname = strtolower($uname);
}
if ($form === 0) {
$form = $this->getAccountCanonicalForm();
}
switch ($form) {
case self::ACCTNAME_FORM_DN:
return $this->getAccountDn($acctname);
case self::ACCTNAME_FORM_USERNAME:
return $uname;
case self::ACCTNAME_FORM_BACKSLASH:
$accountDomainNameShort = $this->getAccountDomainNameShort();
if (! $accountDomainNameShort) {
throw new Exception\LdapException(null, 'Option required: accountDomainNameShort');
}
return "$accountDomainNameShort\\$uname";
case self::ACCTNAME_FORM_PRINCIPAL:
$accountDomainName = $this->getAccountDomainName();
if (! $accountDomainName) {
throw new Exception\LdapException(null, 'Option required: accountDomainName');
}
return "$uname@$accountDomainName";
default:
throw new Exception\LdapException(null, "Unknown canonical name form: $form");
}
}
/**
* @param string $acctname
* @param array $attrs An array of names of desired attributes
* @return array An array of the attributes representing the account
* @throws Exception\LdapException
*/
protected function getAccount($acctname, ?array $attrs = null)
{
$baseDn = $this->getBaseDn();
if (! $baseDn) {
throw new Exception\LdapException(null, 'Base DN not set');
}
$accountFilter = $this->getAccountFilter($acctname);
if (! $accountFilter) {
throw new Exception\LdapException(null, 'Invalid account filter');
}
if (! Handler::isLdapHandle($this->getResource())) {
$this->bind();
}
$accounts = $this->search($accountFilter, $baseDn, self::SEARCH_SCOPE_SUB, $attrs);
$count = $accounts->count();
if ($count === 1) {
$acct = $accounts->getFirst();
$accounts->close();
return $acct;
} else {
if ($count === 0) {
$code = Exception\LdapException::LDAP_NO_SUCH_OBJECT;
$str = "No object found for: $accountFilter";
} else {
$code = Exception\LdapException::LDAP_OPERATIONS_ERROR;
$str = "Unexpected result count ($count) for: $accountFilter";
}
}
$accounts->close();
throw new Exception\LdapException($this, $str, $code);
}
/**
* Selects current parameters on new connections, last when reconnecting.
*
* @param string $method
* Whether the connect or bind method is the caller.
* @param string $parameter
* The parameter name.
* @param mixed $property
* The value of the parameter as set in an instance property.
* @return mixed
* If a reconnect attempt is being made, the value used for the parameter
* last time it was supplied by an external invocation. Otherwise, the
* value.
*/
protected function selectParam($method, $parameter, $property)
{
if ($this->reconnectCount > 0) {
return self::coalesce(
isset($this->lastConnectBindParams[$method]) ? $this->lastConnectBindParams[$method][$parameter] : null,
$property
);
} else {
return $property;
}
}
/**
* @template TA of mixed
* @template TB of mixed
* @param TA $a
* @param TB $b
* @psalm-return (TA is null ? TB : TA|TB)
*/
protected static function coalesce($a, $b)
{
if ($a !== null) {
return $a;
}
return $b;
}
/**
* @return Ldap Provides a fluent interface
*/
public function disconnect()
{
$this->unbind();
$this->resetReconnectsAttempted();
return $this;
}
/** @return $this */
protected function unbind()
{
if (Handler::isLdapHandle($this->resource) && is_string($this->boundUser)) {
ErrorHandler::start(E_WARNING);
ldap_unbind($this->resource);
ErrorHandler::stop();
}
$this->resource = null;
$this->boundUser = false;
return $this;
}
/**
* To connect using SSL it seems the client tries to verify the server
* certificate by default. One way to disable this behavior is to set
* 'TLS_REQCERT never' in OpenLDAP's ldap.conf and restarting Apache. Or,
* if you really care about the server's cert you can put a cert on the
* web server.
*
* @param string $host The hostname of the LDAP server to connect to
* @param int $port The port number of the LDAP server to connect to
* @param bool $useSsl Use SSL
* @param bool $useStartTls Use STARTTLS
* @param int $networkTimeout The value for network timeout when connect to the LDAP server.
* @return Ldap Provides a fluent interface
* @throws Exception\LdapException
*/
public function connect($host = null, $port = null, $useSsl = null, $useStartTls = null, $networkTimeout = null)
{
if ($this->reconnectCount === 0) {
$this->lastConnectBindParams[__METHOD__] = [
'host' => $host,
'port' => $port,
'useSsl' => $useSsl,
'useStartTls' => $useStartTls,
'networkTimeout' => $networkTimeout,
];
}
if ($host === null) {
$host = $this->selectParam(__METHOD__, 'host', $this->getHost());
}
if ($port === null) {
$port = $this->selectParam(__METHOD__, 'port', $this->getPort());
} else {
$port = (int) $port;
}
if ($useSsl === null) {
$useSsl = $this->selectParam(__METHOD__, 'useSsl', $this->getUseSsl());
} else {
$useSsl = (bool) $useSsl;
}
if ($port === 0) {
$port = $useSsl ? 636 : 389;
}
if ($useStartTls === null) {
$useStartTls = $this->selectParam(__METHOD__, 'useStartTls', $this->getUseStartTls());
} else {
$useStartTls = (bool) $useStartTls;
}
if ($networkTimeout === null) {
$networkTimeout = $this->selectParam(__METHOD__, 'networkTimeout', $this->getNetworkTimeout());
} else {
$networkTimeout = (int) $networkTimeout;
}
if (! $host) {
throw new Exception\LdapException(null, 'A host parameter is required');
}
/* Because ldap_connect doesn't really try to connect, any connect error
* will actually occur during the ldap_bind call. Therefore, we save the
* connect string here for reporting it in error handling in bind().
*/
$hosts = [];
if (preg_match_all('~ldap(i|s)?://~', $host, $hosts, PREG_SET_ORDER) > 0) {
$this->connectString = $host;
// assign $useSsl to true in case of ldaps schema
$useSsl = isset($hosts[0][1]) && $hosts[0][1] === 's' ? true : false;
} else {
if ($useSsl) {
$this->connectString = 'ldaps://' . $host;
} else {
$this->connectString = 'ldap://' . $host;
}
if ($port) {
$this->connectString .= ':' . $port;
}
}
$this->disconnect();
// We supporting here only OpenLDAP 2.2 + which uses URLs for connections
// (drop support of old-style host/port connections).
ErrorHandler::start();
$resource = ldap_connect($this->connectString);
ErrorHandler::stop();
if (Handler::isLdapHandle($resource)) {
$this->resource = $resource;
$this->boundUser = false;
$optReferrals = $this->getOptReferrals() ? 1 : 0;
ErrorHandler::start(E_WARNING);
if (
ldap_set_option($resource, LDAP_OPT_PROTOCOL_VERSION, 3)
&& ldap_set_option($resource, LDAP_OPT_REFERRALS, $optReferrals)
) {
if ($networkTimeout) {
ldap_set_option($resource, LDAP_OPT_NETWORK_TIMEOUT, $networkTimeout);
}
if ($useSsl || ! $useStartTls || ldap_start_tls($resource)) {
ErrorHandler::stop();
return $this;
}
}
ErrorHandler::stop();
$zle = new Exception\LdapException($this, "$host:$port");
$this->disconnect();
throw $zle;
}
throw new Exception\LdapException(null, "Failed to connect to LDAP server: $host:$port", -1);
}
/**
* @param string $username The username for authenticating the bind
* @param string $password The password for authenticating the bind
* @param string[]|null $saslOpts Options when performing SASL binds.
* @return Ldap Provides a fluent interface
* @throws Exception\LdapException
*/
public function bind($username = null, $password = null, $saslOpts = null)
{
$moreCreds = true;
if (is_string($password)) {
// Security check: remove null bytes in password
// @see https://net.educause.edu/ir/library/pdf/csd4875.pdf
$password = str_replace("\0", '', $password);
}
if ($this->reconnectCount === 0) {
$this->lastConnectBindParams[__METHOD__] = [
'username' => $username,
'password' => $password,
];
}
if ($username === null) {
$username = $this->selectParam(__METHOD__, 'username', $this->getUsername());
$password = $this->selectParam(__METHOD__, 'password', $this->getPassword());
$moreCreds = false;
}
if ($saslOpts === null) {
$saslOpts = $this->getSaslOpts();
}
if (empty($username)) {
/* Perform anonymous bind
*/
$username = null;
$password = null;
} else {
/* Check to make sure the username is in DN form.
*/
if (! Dn::checkDn($username)) {
if ($this->getBindRequiresDn()) {
/* moreCreds stops an infinite loop if getUsername does not
* return a DN and the bind requires it
*/
if ($moreCreds) {
try {
$username = $this->getAccountDn($username);
} catch (Exception\LdapException $zle) {
switch ($zle->getCode()) {
case Exception\LdapException::LDAP_NO_SUCH_OBJECT:
case Exception\LdapException::LDAP_X_DOMAIN_MISMATCH:
case Exception\LdapException::LDAP_X_EXTENSION_NOT_LOADED:
throw $zle;
}
throw new Exception\LdapException(
null,
'Failed to retrieve DN for account: ' . $username
. ' [' . $zle->getMessage() . ']',
Exception\LdapException::LDAP_OPERATIONS_ERROR
);
}
} else {
throw new Exception\LdapException(null, 'Binding requires username in DN form');
}
} else {
$username = $this->getCanonicalAccountName(
$username,
$this->getAccountCanonicalForm()
);
}
}
}
if (! Handler::isLdapHandle($this->resource)) {
$this->connect();
}
if ($username !== null && $password === '' && $this->getAllowEmptyPassword() !== true) {
$zle = new Exception\LdapException(
null,
'Empty password not allowed - see allowEmptyPassword option.'
);
} else {
ErrorHandler::start(E_WARNING);
if (is_array($saslOpts)) {
$sasl_mech = array_key_exists('sasl_mech', $saslOpts) ? $saslOpts['sasl_mech'] : null;
$sasl_realm = array_key_exists('sasl_realm', $saslOpts) ? $saslOpts['sasl_realm'] : null;
$sasl_authc_id = array_key_exists('sasl_authc_id', $saslOpts) ? $saslOpts['sasl_authc_id'] : null;
$sasl_authz_id = array_key_exists('sasl_authz_id', $saslOpts) ? $saslOpts['sasl_authz_id'] : null;
$sasl_props = array_key_exists('props', $saslOpts) ? $saslOpts['props'] : null;
$bind = ldap_sasl_bind(
$this->resource,
$username,
$password,
$sasl_mech,
$sasl_realm,
$sasl_authc_id,
$sasl_authz_id,
$sasl_props
);
} else {
$bind = ldap_bind($this->resource, $username, $password);
}
ErrorHandler::stop();
if ($bind !== false) {
$this->boundUser = $username;
return $this;
}
$this->boundUser = false;
if ($this->shouldReconnect($this->resource)) {
return $this;
}
$message = $username ?? $this->connectString;
switch ($this->getLastErrorCode()) {
case Exception\LdapException::LDAP_SERVER_DOWN:
/* If the error is related to establishing a connection rather than binding,
* the connect string is more informative than the username.
*/
$message = $this->connectString;
}
$zle = new Exception\LdapException($this, $message);
}
$this->unbind();
throw $zle;
}
/**
* @param resource $resource
* @return bool
*/
protected function shouldReconnect($resource)
{
if (
$this->reconnectCount >= $this->getReconnectsToAttempt()
|| ldap_errno($resource) !== -1
) {
$this->reconnectsAttempted = $this->reconnectCount;
$this->reconnectCount = 0;
return false;
}
$this->reconnectCount++;
$this->reconnectSleep();
try {
$this->connect();
$this->bind();
$this->reconnectsAttempted = $this->reconnectCount;
$this->reconnectCount = 0;
return true;
} catch (Exception\LdapException $e) {
if ($e->getCode() !== -1) {
return false;
}
}
return $this->shouldReconnect($this->getResource());
}
protected function reconnectSleep()
{
$duration = min((pow(2, min($this->reconnectCount - 1, 0)) - 1) / 4, 10);
usleep($duration * 1000000);
}
/**
* A global LDAP search routine for finding information.
*
* Options can be either passed as single parameters according to the
* method signature or as an array with one or more of the following keys
* - filter
* - baseDn
* - scope
* - attributes
* - sort
* - collectionClass
* - sizelimit
* - timelimit
*
* @param string|Filter\AbstractFilter|array $filter
* @param string|Dn|null $basedn
* @param int $scope
* @param array $attributes
* @param string|null $sort
* @param string|null $collectionClass
* @param int $sizelimit
* @param int $timelimit
* @return Collection
* @throws Exception\LdapException
*/
public function search(
$filter,
$basedn = null,
$scope = self::SEARCH_SCOPE_SUB,
array $attributes = [],
$sort = null,
$collectionClass = null,
$sizelimit = 0,
$timelimit = 0
) {
if (is_array($filter)) {
$options = array_change_key_case($filter, CASE_LOWER);
foreach ($options as $key => $value) {
switch ($key) {
case 'filter':
case 'basedn':
case 'scope':
case 'sort':
$$key = $value;
break;
case 'attributes':
if (is_array($value)) {
$attributes = $value;
}
break;
case 'collectionclass':
$collectionClass = $value;
break;
case 'sizelimit':
case 'timelimit':
$$key = (int) $value;
break;
}
}
}
if ($basedn === null) {
$basedn = $this->getBaseDn();
} elseif ($basedn instanceof Dn) {
$basedn = $basedn->toString();
}
if ($filter instanceof Filter\AbstractFilter) {
$filter = $filter->toString();
}
do {
$resource = $this->getResource();
ErrorHandler::start(E_WARNING);
switch ($scope) {
case self::SEARCH_SCOPE_ONE:
$search = ldap_list($resource, $basedn, $filter, $attributes, 0, $sizelimit, $timelimit);
break;
case self::SEARCH_SCOPE_BASE:
$search = ldap_read($resource, $basedn, $filter, $attributes, 0, $sizelimit, $timelimit);
break;
case self::SEARCH_SCOPE_SUB:
default:
$search = ldap_search($resource, $basedn, $filter, $attributes, 0, $sizelimit, $timelimit);
break;
}
ErrorHandler::stop();
} while ($search === false && $this->shouldReconnect($resource));
if ($search === false) {
throw new Exception\LdapException($this, 'searching: ' . $filter);
}
$iterator = new Collection\DefaultIterator($this, $search);
if ($sort !== null && is_string($sort)) {
$iterator->sort($sort);
}
return $this->createCollection($iterator, $collectionClass);
}
/**
* Extension point for collection creation
*
* @param string|null $collectionClass
* @return Collection
* @throws Exception\LdapException
*/
protected function createCollection(Collection\DefaultIterator $iterator, $collectionClass)
{
if ($collectionClass === null) {
return new Collection($iterator);
} else {
$collectionClass = (string) $collectionClass;
if (! class_exists($collectionClass)) {
throw new Exception\LdapException(
null,
"Class '$collectionClass' can not be found"
);
}
if (! is_subclass_of($collectionClass, Collection::class)) {
throw new Exception\LdapException(
null,
"Class '$collectionClass' must subclass 'Laminas\\Ldap\\Collection'"
);
}
return new $collectionClass($iterator);
}
}
/**
* Count items found by given filter.
*
* @param string|Filter\AbstractFilter $filter
* @param string|Dn|null $basedn
* @param int $scope
* @return int
* @throws Exception\LdapException
*/
public function count($filter, $basedn = null, $scope = self::SEARCH_SCOPE_SUB)
{
try {
$result = $this->search($filter, $basedn, $scope, ['dn'], null);
} catch (Exception\LdapException $e) {
if ($e->getCode() === Exception\LdapException::LDAP_NO_SUCH_OBJECT) {
return 0;
}
throw $e;
}
return $result->count();
}
/**
* Count children for a given DN.
*
* @param string|Dn $dn
* @return int
* @throws Exception\LdapException
*/
public function countChildren($dn)
{
return $this->count('(objectClass=*)', $dn, self::SEARCH_SCOPE_ONE);
}
/**
* Check if a given DN exists.
*
* @param string|Dn $dn
* @return bool
* @throws Exception\LdapException
*/
public function exists($dn)
{
return $this->count('(objectClass=*)', $dn, self::SEARCH_SCOPE_BASE) === 1;
}
/**
* Search LDAP registry for entries matching filter and optional attributes
*
* Options can be either passed as single parameters according to the
* method signature or as an array with one or more of the following keys
* - filter
* - baseDn
* - scope
* - attributes
* - sort
* - reverseSort
* - sizelimit
* - timelimit
*
* @param string|Filter\AbstractFilter|array $filter
* @param string|Dn|null $basedn
* @param int $scope
* @param array $attributes
* @param string|null $sort
* @param bool $reverseSort
* @param int $sizelimit
* @param int $timelimit
* @return array
* @throws Exception\LdapException
*/
public function searchEntries(
$filter,
$basedn = null,
$scope = self::SEARCH_SCOPE_SUB,
array $attributes = [],
$sort = null,
$reverseSort = false,
$sizelimit = 0,
$timelimit = 0
) {
if (is_array($filter)) {
$filter = array_change_key_case($filter, CASE_LOWER);
if (isset($filter['collectionclass'])) {
unset($filter['collectionclass']);
}
if (isset($filter['reversesort'])) {
$reverseSort = $filter['reversesort'];
unset($filter['reversesort']);
}
}
$result = $this->search($filter, $basedn, $scope, $attributes, $sort, null, $sizelimit, $timelimit);
$items = $result->toArray();
if ((bool) $reverseSort === true) {
$items = array_reverse($items, false);
}
return $items;
}
/**
* Get LDAP entry by DN
*
* @param string|Dn $dn
* @param array $attributes
* @param bool $throwOnNotFound
* @return array
* @throws null|Exception\LdapException
*/
public function getEntry($dn, array $attributes = [], $throwOnNotFound = false)
{
try {
$result = $this->search(
"(objectClass=*)",
$dn,
self::SEARCH_SCOPE_BASE,
$attributes,
null
);
return $result->getFirst();
} catch (Exception\LdapException $e) {
if ($throwOnNotFound !== false) {
throw $e;
}
}
return null;
}
/**
* Prepares an ldap data entry array for insert/update operation
*
* @param array $entry
* @throws Exception\InvalidArgumentException
* @return void
*/
public static function prepareLdapEntryArray(array &$entry)
{
if (array_key_exists('dn', $entry)) {
unset($entry['dn']);
}
foreach ($entry as $key => $value) {
if (is_array($value)) {
foreach ($value as $i => $v) {
if ($v === null) {
unset($value[$i]);
} elseif (! is_scalar($v)) {
throw new Exception\InvalidArgumentException('Only scalar values allowed in LDAP data');
} else {
$v = (string) $v;
if (strlen($v) === 0) {
unset($value[$i]);
} else {
$value[$i] = $v;
}
}
}
$entry[$key] = array_values($value);
} else {
if ($value === null) {
$entry[$key] = [];
} elseif (! is_scalar($value)) {
throw new Exception\InvalidArgumentException('Only scalar values allowed in LDAP data');
} else {
$value = (string) $value;
if (strlen($value) === 0) {
$entry[$key] = [];
} else {
$entry[$key] = [$value];
}
}
}
}
$entry = array_change_key_case($entry, CASE_LOWER);
}
/**
* Add new information to the LDAP repository
*
* @param string|Dn $dn
* @param array $entry
* @return Ldap Provides a fluid interface
* @throws Exception\LdapException
*/
public function add($dn, array $entry)
{
if (! $dn instanceof Dn) {
$dn = Dn::factory($dn, null);
}
static::prepareLdapEntryArray($entry);
foreach ($entry as $key => $value) {
if (is_array($value) && count($value) === 0) {
unset($entry[$key]);
}
}
$rdnParts = $dn->getRdn(Dn::ATTR_CASEFOLD_LOWER);
foreach ($rdnParts as $key => $value) {
$value = Dn::unescapeValue($value);
if (! array_key_exists($key, $entry)) {
$entry[$key] = [$value];
} elseif (! in_array($value, $entry[$key])) {
$entry[$key] = array_merge([$value], $entry[$key]);
}
}
$adAttributes = [
'distinguishedname',
'instancetype',
'name',
'objectcategory',
'objectguid',
'usnchanged',
'usncreated',
'whenchanged',
'whencreated',
];
foreach ($adAttributes as $attr) {
if (array_key_exists($attr, $entry)) {
unset($entry[$attr]);
}
}
do {
$resource = $this->getResource();
ErrorHandler::start(E_WARNING);
$isAdded = ldap_add($resource, $dn->toString(), $entry);
ErrorHandler::stop();
} while ($isAdded === false && $this->shouldReconnect($resource));
if ($isAdded === false) {
throw new Exception\LdapException($this, 'adding: ' . $dn->toString());
}
return $this;
}
/**
* Update LDAP registry
*
* @param string|Dn $dn
* @param array $entry
* @return Ldap Provides a fluid interface
* @throws Exception\LdapException
*/
public function update($dn, array $entry)
{
if (! $dn instanceof Dn) {
$dn = Dn::factory($dn, null);
}
static::prepareLdapEntryArray($entry);
$rdnParts = $dn->getRdn(Dn::ATTR_CASEFOLD_LOWER);
foreach ($rdnParts as $key => $value) {
$value = Dn::unescapeValue($value);
if (array_key_exists($key, $entry) && ! in_array($value, $entry[$key])) {
$entry[$key] = array_merge([$value], $entry[$key]);
}
}
$adAttributes = [
'distinguishedname',
'instancetype',
'name',
'objectcategory',
'objectguid',
'usnchanged',
'usncreated',
'whenchanged',
'whencreated',
];
foreach ($adAttributes as $attr) {
if (array_key_exists($attr, $entry)) {
unset($entry[$attr]);
}
}
if (count($entry) > 0) {
do {
$resource = $this->getResource();
ErrorHandler::start(E_WARNING);
$isModified = ldap_modify($resource, $dn->toString(), $entry);
ErrorHandler::stop();
} while ($isModified === false && $this->shouldReconnect($resource));
if ($isModified === false) {
throw new Exception\LdapException($this, 'updating: ' . $dn->toString());
}
}
return $this;
}
/**
* Save entry to LDAP registry.
*
* Internally decides if entry will be updated to added by calling
* {@link exists()}.
*
* @param string|Dn $dn
* @param array $entry
* @return Ldap Provides a fluid interface
* @throws Exception\LdapException
*/
public function save($dn, array $entry)
{
if ($dn instanceof Dn) {
$dn = $dn->toString();
}
if ($this->exists($dn)) {
$this->update($dn, $entry);
} else {
$this->add($dn, $entry);
}
return $this;
}
/**
* Delete an LDAP entry
*
* @param string|Dn $dn
* @param bool $recursively
* @return Ldap Provides a fluid interface
* @throws Exception\LdapException
*/
public function delete($dn, $recursively = false)
{
if ($dn instanceof Dn) {
$dn = $dn->toString();
}
if ($recursively === true) {
if ($this->countChildren($dn) > 0) {
$children = $this->getChildrenDns($dn);
foreach ($children as $c) {
$this->delete($c, true);
}
}
}
do {
$resource = $this->getResource();
ErrorHandler::start(E_WARNING);
$isDeleted = ldap_delete($resource, $dn);
ErrorHandler::stop();
} while ($isDeleted === false && $this->shouldReconnect($resource));
if ($isDeleted === false) {
throw new Exception\LdapException($this, 'deleting: ' . $dn);
}
return $this;
}
/**
* Add one or more attributes to the specified dn
*
* @param string|Dn $dn
* @param array $attributes
* @param bool $allowEmptyAttributes
* @return Ldap Provides a fluid interface
* @throws Exception\LdapException
*/
public function addAttributes($dn, array $attributes, $allowEmptyAttributes = false)
{
// Safety-flap: Check whether there are empty arrays that would cause
// complete removal of entries without the emptyAll flag.
if ($allowEmptyAttributes !== true) {
foreach ($attributes as $key => $value) {
if (empty($value)) {
unset($attributes[$key]);
}
}
}
if ($dn instanceof Dn) {
$dn = $dn->toString();
}
do {
ErrorHandler::start(E_WARNING);
$entryAdded = ldap_mod_add($this->resource, $dn, $attributes);
ErrorHandler::stop();
} while ($entryAdded === false && $this->shouldReconnect($this->resource));
if ($entryAdded === false) {
throw new Exception\LdapException($this, 'adding attribute: ' . $dn);
}
return $this;
}
/**
* Update one or more attributes to the specified dn
*
* @param string|Dn $dn
* @param array $attributes
* @param bool $allowEmptyAttributes
* @return Ldap Provides a fluid interface
* @throws Exception\LdapException
*/
public function updateAttributes($dn, array $attributes, $allowEmptyAttributes = false)
{
// Safety-flap: Check whether there are empty arrays that would cause
// complete removal of entries without the emptyAll flag.
if ($allowEmptyAttributes !== true) {
foreach ($attributes as $key => $value) {
if (empty($value)) {
unset($attributes[$key]);
}
}
}
if ($dn instanceof Dn) {
$dn = $dn->toString();
}
do {
ErrorHandler::start(E_WARNING);
$entryUpdated = ldap_mod_replace($this->resource, $dn, $attributes);
ErrorHandler::stop();
} while ($entryUpdated === false && $this->shouldReconnect($this->resource));
if ($entryUpdated === false) {
throw new Exception\LdapException($this, 'updating attribute: ' . $dn);
}
return $this;
}
/**
* Delete single attributes from a LDAP-Node
*
* This method removes single attributes from a node identified by
* <var>$dn</var>. The attributes have to be given as array where the
* array-key is the attribute-name and the array-value is the attribute-value
* that is to be removed.
*
* To remove multiple entries of an attribute pass an array with the values
* to be removed as value of the key. So if you want to remove more than
* one <strong>memberUid</strong>-attribute you would pass
* <code>array('memberUid' => ['uid1', 'uid2',...]);</code> as
* <var>$attributes</var>
*
* Beware that passing an empty array will remove <strong>all</strong>
* entries of the attribute. Therefore you will have to set the
* <var>$emptyAll</var>-flag!
*
* @param Dn|string $dn The DN for which to remove attributes
* @param array $attributes The attributes to be removed
* @param bool $allowEmptyAttributes Whether empty attribute-array
* should remove all attribute-
* values or not.
* @throws Exception\LdapException Is thrown when the LDAP-server reported an error.
* @return Ldap Provides a fluent interface
*/
public function deleteAttributes($dn, array $attributes, $allowEmptyAttributes = false)
{
// Safety-flap: Check whether there are empty arrays that would cause
// complete removal of entries without the emptyAll flag.
if ($allowEmptyAttributes !== true) {
foreach ($attributes as $key => $value) {
if (empty($value)) {
unset($attributes[$key]);
}
}
}
if ($dn instanceof Dn) {
$dn = $dn->toString();
}
do {
ErrorHandler::start(E_WARNING);
$isDeleted = ldap_mod_del($this->resource, $dn, $attributes);
ErrorHandler::stop();
} while ($isDeleted === false && $this->shouldReconnect($this->resource));
if ($isDeleted === false) {
throw new Exception\LdapException($this, 'deleting: ' . $dn);
}
return $this;
}
/**
* Retrieve the immediate children DNs of the given $parentDn
*
* This method is used in recursive methods like {@see delete()}
* or {@see copy()}
*
* @param string|Dn $parentDn
* @throws Exception\LdapException
* @return array of DNs
*/
protected function getChildrenDns($parentDn)
{
if ($parentDn instanceof Dn) {
$parentDn = $parentDn->toString();
}
$children = [];
do {
$resource = $this->getResource();
ErrorHandler::start(E_WARNING);
$search = ldap_list($resource, $parentDn, '(objectClass=*)', ['dn']);
ErrorHandler::stop();
} while ($search === false && $this->shouldReconnect($resource));
if ($search === false) {
throw new Exception\LdapException($this, 'listing: ' . $parentDn);
}
ErrorHandler::start(E_WARNING);
for (
$entry = ldap_first_entry($resource, $search);
$entry !== false;
$entry = ldap_next_entry($resource, $entry)
) {
$childDn = ldap_get_dn($resource, $entry);
if ($childDn === false) {
ErrorHandler::stop();
throw new Exception\LdapException($this, 'getting dn');
}
$children[] = $childDn;
}
ldap_free_result($search);
ErrorHandler::stop();
return $children;
}
/**
* Moves a LDAP entry from one DN to another subtree.
*
* @param string|Dn $from
* @param string|Dn $to
* @param bool $recursively
* @param bool $alwaysEmulate
* @return Ldap Provides a fluid interface
* @throws Exception\LdapException
*/
public function moveToSubtree($from, $to, $recursively = false, $alwaysEmulate = false)
{
if ($from instanceof Dn) {
$orgDnParts = $from->toArray();
} else {
$orgDnParts = Dn::explodeDn($from);
}
if ($to instanceof Dn) {
$newParentDnParts = $to->toArray();
} else {
$newParentDnParts = Dn::explodeDn($to);
}
$newDnParts = array_merge([array_shift($orgDnParts)], $newParentDnParts);
$newDn = Dn::fromArray($newDnParts);
return $this->rename($from, $newDn, $recursively, $alwaysEmulate);
}
/**
* Moves a LDAP entry from one DN to another DN.
*
* This is an alias for {@link rename()}
*
* @param string|Dn $from
* @param string|Dn $to
* @param bool $recursively
* @param bool $alwaysEmulate
* @return Ldap Provides a fluid interface
* @throws Exception\LdapException
*/
public function move($from, $to, $recursively = false, $alwaysEmulate = false)
{
return $this->rename($from, $to, $recursively, $alwaysEmulate);
}
/**
* Renames a LDAP entry from one DN to another DN.
*
* This method implicitly moves the entry to another location within the tree.
*
* @param string|Dn $from
* @param string|Dn $to
* @param bool $recursively
* @param bool $alwaysEmulate
* @return Ldap Provides a fluid interface
* @throws Exception\LdapException
*/
public function rename($from, $to, $recursively = false, $alwaysEmulate = false)
{
$emulate = (bool) $alwaysEmulate;
if (! function_exists('ldap_rename')) {
$emulate = true;
} elseif ($recursively) {
$emulate = true;
}
if ($emulate === false) {
if ($from instanceof Dn) {
$from = $from->toString();
}
if ($to instanceof Dn) {
$newDnParts = $to->toArray();
} else {
$newDnParts = Dn::explodeDn($to);
}
$newRdn = Dn::implodeRdn(array_shift($newDnParts));
$newParent = Dn::implodeDn($newDnParts);
do {
$resource = $this->getResource();
ErrorHandler::start(E_WARNING);
$isOK = ldap_rename($resource, $from, $newRdn, $newParent, true);
ErrorHandler::stop();
} while ($isOK === false && $this->shouldReconnect($resource));
if ($isOK === false) {
throw new Exception\LdapException($this, 'renaming ' . $from . ' to ' . $to);
} elseif (! $this->exists($to)) {
$emulate = true;
}
}
if ($emulate) {
$this->copy($from, $to, $recursively);
$this->delete($from, $recursively);
}
return $this;
}
/**
* Copies a LDAP entry from one DN to another subtree.
*
* @param string|Dn $from
* @param string|Dn $to
* @param bool $recursively
* @return Ldap Provides a fluid interface
* @throws Exception\LdapException
*/
public function copyToSubtree($from, $to, $recursively = false)
{
if ($from instanceof Dn) {
$orgDnParts = $from->toArray();
} else {
$orgDnParts = Dn::explodeDn($from);
}
if ($to instanceof Dn) {
$newParentDnParts = $to->toArray();
} else {
$newParentDnParts = Dn::explodeDn($to);
}
$newDnParts = array_merge([array_shift($orgDnParts)], $newParentDnParts);
$newDn = Dn::fromArray($newDnParts);
return $this->copy($from, $newDn, $recursively);
}
/**
* Copies a LDAP entry from one DN to another DN.
*
* @param string|Dn $from
* @param string|Dn $to
* @param bool $recursively
* @return Ldap Provides a fluid interface
* @throws Exception\LdapException
*/
public function copy($from, $to, $recursively = false)
{
$entry = $this->getEntry($from, [], true);
if ($to instanceof Dn) {
$toDnParts = $to->toArray();
} else {
$toDnParts = Dn::explodeDn($to);
}
$this->add($to, $entry);
if ($recursively === true && $this->countChildren($from) > 0) {
$children = $this->getChildrenDns($from);
foreach ($children as $c) {
$cDnParts = Dn::explodeDn($c);
$newChildParts = array_merge([array_shift($cDnParts)], $toDnParts);
$newChild = Dn::implodeDn($newChildParts);
$this->copy($c, $newChild, true);
}
}
return $this;
}
/**
* Returns the specified DN as a Laminas\Ldap\Node
*
* @param string|Dn $dn
* @return Node|null
* @throws Exception\LdapException
*/
public function getNode($dn)
{
return Node::fromLdap($dn, $this);
}
/**
* Returns the base node as a Laminas\Ldap\Node
*
* @return Node
* @throws Exception\LdapException
*/
public function getBaseNode()
{
$baseNode = $this->getNode($this->getBaseDn());
assert($baseNode instanceof Node);
return $baseNode;
}
/**
* Returns the RootDse
*
* @return Node\RootDse
* @throws Exception\LdapException
*/
public function getRootDse()
{
if ($this->rootDse === null) {
$this->rootDse = Node\RootDse::create($this);
}
return $this->rootDse;
}
/**
* Returns the schema
*
* @return Node\Schema
* @throws Exception\LdapException
*/
public function getSchema()
{
if ($this->schema === null) {
$this->schema = Node\Schema::create($this);
}
return $this->schema;
}
}
laminas-ldap/src/Collection.php 0000644 00000010321 15240152652 0012500 0 ustar 00 <?php
namespace Laminas\Ldap;
use Countable;
use Iterator;
use ReturnTypeWillChange;
use function array_key_exists;
/**
* Laminas\Ldap\Collection wraps a list of LDAP entries.
*/
class Collection implements Iterator, Countable
{
/**
* Iterator
*
* @var Collection\DefaultIterator
*/
protected $iterator;
/**
* Current item number
*
* @var int
*/
protected $current = -1;
/**
* Container for item caching to speed up multiple iterations
*
* @var array
*/
protected $cache = [];
public function __construct(Collection\DefaultIterator $iterator)
{
$this->iterator = $iterator;
}
public function __destruct()
{
$this->close();
}
/**
* Closes the current result set
*
* @return bool
*/
public function close()
{
return $this->iterator->close();
}
/**
* Get all entries as an array
*
* @return array
*/
public function toArray()
{
$data = [];
foreach ($this as $item) {
$data[] = $item;
}
return $data;
}
/**
* Get first entry
*
* @return array|null
*/
public function getFirst()
{
if ($this->count() < 1) {
return null;
}
$this->rewind();
return $this->current();
}
/**
* Returns the underlying iterator
*
* @return Collection\DefaultIterator
*/
public function getInnerIterator()
{
return $this->iterator;
}
/**
* Returns the number of items in current result
* Implements Countable
*
* @return int
*/
#[ReturnTypeWillChange]
public function count()
{
return $this->iterator->count();
}
/**
* Return the current result item
* Implements Iterator
*
* @return array|null
* @throws Exception\LdapException
*/
#[ReturnTypeWillChange]
public function current()
{
if ($this->count() < 1) {
return null;
}
if ($this->current < 0) {
$this->rewind();
}
if (! array_key_exists($this->current, $this->cache)) {
$current = $this->iterator->current();
if ($current === null) {
return null;
}
$this->cache[$this->current] = $this->createEntry($current);
}
return $this->cache[$this->current];
}
/**
* Creates the data structure for the given entry data
*
* @param array $data
* @return array
*/
protected function createEntry(array $data)
{
return $data;
}
/**
* Return the current result item DN
*
* @return string|null
*/
public function dn()
{
if ($this->count() > 0) {
if ($this->current < 0) {
$this->rewind();
}
return $this->iterator->key();
}
return null;
}
/**
* Return the current result item key
* Implements Iterator
*
* @return int|null
*/
#[ReturnTypeWillChange]
public function key()
{
if ($this->count() > 0) {
if ($this->current < 0) {
$this->rewind();
}
return $this->current;
}
return null;
}
/**
* Move forward to next result item
* Implements Iterator
*
* @throws Exception\LdapException
*/
#[ReturnTypeWillChange]
public function next()
{
$this->iterator->next();
$this->current++;
}
/**
* Rewind the Iterator to the first result item
* Implements Iterator
*
* @throws Exception\LdapException
*/
#[ReturnTypeWillChange]
public function rewind()
{
$this->iterator->rewind();
$this->current = 0;
}
/**
* Check if there is a current result item
* after calls to rewind() or next()
* Implements Iterator
*
* @return bool
*/
#[ReturnTypeWillChange]
public function valid()
{
if (isset($this->cache[$this->current])) {
return true;
}
return $this->iterator->valid();
}
}
laminas-ldap/src/Ldif/Encoder.php 0000644 00000021755 15240152652 0012657 0 ustar 00 <?php
namespace Laminas\Ldap\Ldif;
use Laminas\Ldap;
use function array_change_key_case;
use function array_key_exists;
use function array_merge;
use function base64_decode;
use function base64_encode;
use function chunk_split;
use function count;
use function explode;
use function in_array;
use function is_array;
use function is_numeric;
use function is_scalar;
use function ksort;
use function ord;
use function preg_match;
use function rtrim;
use function sprintf;
use function strlen;
use function strtolower;
use function substr;
use function trim;
use const CASE_LOWER;
use const PHP_EOL;
use const SORT_STRING;
/**
* Laminas\Ldap\Ldif\Encoder provides methods to encode and decode LDAP data into/from Ldif.
*/
class Encoder
{
/**
* Additional options used during encoding
*
* @var array
*/
protected $options = [
'sort' => true,
'version' => 1,
'wrap' => 78,
];
/** @var bool */
protected $versionWritten = false;
/**
* @param array $options Additional options used during encoding
*/
protected function __construct(array $options = [])
{
$this->options = array_merge($this->options, $options);
}
/**
* Decodes the string $string into an array of Ldif items
*
* @param string $string
* @return array
*/
public static function decode($string)
{
$encoder = new static([]);
return $encoder->_decode($string);
}
/**
* Decodes the string $string into an array of Ldif items
*
* @param string $string
* @return array
*/
// @codingStandardsIgnoreStart
protected function _decode($string)
{
// @codingStandardsIgnoreEnd
$items = [];
$item = [];
$last = null;
$inComment = false;
foreach (explode("\n", $string) as $line) {
$line = rtrim($line, "\x09\x0A\x0D\x00\x0B");
$matches = [];
if (substr($line, 0, 1) === ' ' && $last !== null && ! $inComment) {
$last[2] .= substr($line, 1);
} elseif (substr($line, 0, 1) === '#') {
$inComment = true;
continue;
} elseif (preg_match('/^([a-z0-9;-]+)(:[:<]?\s*)([^<]*)$/i', $line, $matches)) {
$inComment = false;
$name = strtolower($matches[1]);
$type = trim($matches[2]);
$value = $matches[3];
if ($last !== null) {
$this->pushAttribute($last, $item);
}
if ($name === 'version') {
continue;
} elseif (count($item) > 0 && $name === 'dn') {
$items[] = $item;
$item = [];
}
$last = [$name, $type, $value];
} elseif (trim($line) === '') {
continue;
}
}
if ($last !== null) {
$this->pushAttribute($last, $item);
}
$items[] = $item;
return count($items) > 1 ? $items : $items[0];
}
/**
* Pushes a decoded attribute to the stack
*
* @param array $attribute
* @param array $entry
*/
protected function pushAttribute(array $attribute, array &$entry)
{
$name = $attribute[0];
$type = $attribute[1];
$value = $attribute[2];
if ($type === '::') {
$value = base64_decode($value);
}
if ($name === 'dn') {
$entry[$name] = $value;
} elseif (isset($entry[$name]) && $value !== '') {
$entry[$name][] = $value;
} else {
$entry[$name] = $value !== '' ? [$value] : [];
}
}
/**
* Encode $value into a Ldif representation
*
* @param mixed $value The value to be encoded
* @param array $options Additional options used during encoding
* @return string The encoded value
*/
public static function encode($value, array $options = [])
{
$encoder = new static($options);
return $encoder->_encode($value);
}
/**
* Recursive driver which determines the type of value to be encoded
* and then dispatches to the appropriate method.
*
* @param mixed $value The value to be encoded
* @return string Encoded value
*/
// @codingStandardsIgnoreStart
protected function _encode($value)
{
// @codingStandardsIgnoreEnd
if (is_scalar($value)) {
return $this->encodeString($value);
} elseif (is_array($value)) {
return $this->encodeAttributes($value);
} elseif ($value instanceof Ldap\Node) {
return $value->toLdif($this->options);
}
return null;
}
/**
* Encodes $string according to RFC2849
*
* @link http://www.faqs.org/rfcs/rfc2849.html
*
* @param string $string
* @param bool $base64
* @return string
*/
protected function encodeString($string, &$base64 = null)
{
$string = (string) $string;
if (! is_numeric($string) && empty($string)) {
return '';
}
/*
* SAFE-INIT-CHAR = %x01-09 / %x0B-0C / %x0E-1F /
* %x21-39 / %x3B / %x3D-7F
* ; any value <= 127 except NUL, LF, CR,
* ; SPACE, colon (":", ASCII 58 decimal)
* ; and less-than ("<" , ASCII 60 decimal)
*
*/
$unsafeInitChar = [0, 10, 13, 32, 58, 60];
/*
* SAFE-CHAR = %x01-09 / %x0B-0C / %x0E-7F
* ; any value <= 127 decimal except NUL, LF,
* ; and CR
*/
$unsafeChar = [0, 10, 13];
$base64 = false;
for ($i = 0, $len = strlen($string); $i < $len; $i++) {
$char = ord(substr($string, $i, 1));
if ($char >= 127) {
$base64 = true;
break;
} elseif ($i === 0 && in_array($char, $unsafeInitChar)) {
$base64 = true;
break;
} elseif (in_array($char, $unsafeChar)) {
$base64 = true;
break;
}
}
// Test for ending space
if (substr($string, -1) === ' ') {
$base64 = true;
}
if ($base64 === true) {
$string = base64_encode($string);
}
return $string;
}
/**
* Encodes an attribute with $name and $value according to RFC2849
*
* @link http://www.faqs.org/rfcs/rfc2849.html
*
* @param string $name
* @param array|string $value
* @return string
*/
protected function encodeAttribute($name, $value)
{
if (! is_array($value)) {
$value = [$value];
}
$output = '';
if (count($value) < 1) {
return $name . ': ';
}
foreach ($value as $v) {
$base64 = null;
$v = $this->encodeString($v, $base64);
$attribute = $name . ':';
if ($base64 === true) {
$attribute .= ': ' . $v;
} else {
$attribute .= ' ' . $v;
}
if (isset($this->options['wrap']) && strlen($attribute) > $this->options['wrap']) {
$attribute = trim(chunk_split($attribute, $this->options['wrap'], PHP_EOL . ' '));
}
$output .= $attribute . PHP_EOL;
}
return trim($output, PHP_EOL);
}
/**
* Encodes a collection of attributes according to RFC2849
*
* @link http://www.faqs.org/rfcs/rfc2849.html
*
* @param array $attributes
* @return string
*/
protected function encodeAttributes(array $attributes)
{
$string = '';
$attributes = array_change_key_case($attributes, CASE_LOWER);
if (
! $this->versionWritten && array_key_exists('dn', $attributes) && isset($this->options['version'])
&& array_key_exists('objectclass', $attributes)
) {
$string .= sprintf('version: %d', $this->options['version']) . PHP_EOL;
$this->versionWritten = true;
}
if (isset($this->options['sort']) && $this->options['sort'] === true) {
ksort($attributes, SORT_STRING);
if (array_key_exists('objectclass', $attributes)) {
$oc = $attributes['objectclass'];
unset($attributes['objectclass']);
$attributes = array_merge(['objectclass' => $oc], $attributes);
}
if (array_key_exists('dn', $attributes)) {
$dn = $attributes['dn'];
unset($attributes['dn']);
$attributes = array_merge(['dn' => $dn], $attributes);
}
}
foreach ($attributes as $key => $value) {
$string .= $this->encodeAttribute($key, $value) . PHP_EOL;
}
return trim($string, PHP_EOL);
}
}
laminas-ldap/src/Node/AbstractNode.php 0000644 00000025772 15240152652 0013663 0 ustar 00 <?php
namespace Laminas\Ldap\Node;
use ArrayAccess;
use Countable;
use Laminas\Ldap;
use Laminas\Ldap\Dn;
use Laminas\Ldap\Exception;
use Laminas\Ldap\Exception\BadMethodCallException;
use Laminas\Ldap\Exception\LdapException;
use ReturnTypeWillChange;
use function array_key_exists;
use function array_merge;
use function count;
use function in_array;
use function json_encode;
use function ksort;
use function strtolower;
use const SORT_STRING;
/**
* This class provides a base implementation for LDAP nodes
*/
abstract class AbstractNode implements ArrayAccess, Countable
{
/** @var non-empty-list<non-empty-string> */
protected static $systemAttributes = [
'createtimestamp',
'creatorsname',
'entrycsn',
'entrydn',
'entryuuid',
'hassubordinates',
'modifiersname',
'modifytimestamp',
'structuralobjectclass',
'subschemasubentry',
'distinguishedname',
'instancetype',
'name',
'objectcategory',
'objectguid',
'usnchanged',
'usncreated',
'whenchanged',
'whencreated',
];
/**
* Holds the node's DN.
*
* @var Dn
*/
protected $dn;
/**
* Holds the node's current data.
*
* @var array
*/
protected $currentData;
/**
* Constructor is protected to enforce the use of factory methods.
*
* @param array $data
* @param bool $fromDataSource
*/
protected function __construct(Ldap\Dn $dn, array $data, $fromDataSource)
{
$this->dn = $dn;
$this->loadData($data, $fromDataSource);
}
/**
* @param array $data
* @param bool $fromDataSource
*/
protected function loadData(array $data, $fromDataSource)
{
if (array_key_exists('dn', $data)) {
unset($data['dn']);
}
ksort($data, SORT_STRING);
$this->currentData = $data;
}
/**
* Reload node attributes from LDAP.
*
* This is an online method.
*
* @return AbstractNode Provides a fluid interface
*/
public function reload(?Ldap\Ldap $ldap = null)
{
if ($ldap !== null) {
$data = $ldap->getEntry($this->_getDn(), ['*', '+'], true);
$this->loadData($data, true);
}
return $this;
}
/**
* Gets the DN of the current node as a Laminas\Ldap\Dn.
*
* This is an offline method.
*
* @return Dn
*/
// @codingStandardsIgnoreStart
protected function _getDn()
{
// @codingStandardsIgnoreEnd
return $this->dn;
}
/**
* Gets the DN of the current node as a Laminas\Ldap\Dn.
* The method returns a clone of the node's DN to prohibit modification.
*
* This is an offline method.
*
* @return Dn
*/
public function getDn()
{
return clone $this->_getDn();
}
/**
* Gets the DN of the current node as a string.
*
* This is an offline method.
*
* @param string $caseFold
* @return string
*/
public function getDnString($caseFold = null)
{
return $this->_getDn()->toString($caseFold);
}
/**
* Gets the DN of the current node as an array.
*
* This is an offline method.
*
* @param string $caseFold
* @return array
*/
public function getDnArray($caseFold = null)
{
return $this->_getDn()->toArray($caseFold);
}
/**
* Gets the RDN of the current node as a string.
*
* This is an offline method.
*
* @param string $caseFold
* @return string
*/
public function getRdnString($caseFold = null)
{
return $this->_getDn()->getRdnString($caseFold);
}
/**
* Gets the RDN of the current node as an array.
*
* This is an offline method.
*
* @param string $caseFold
* @return array
*/
public function getRdnArray($caseFold = null)
{
return $this->_getDn()->getRdn($caseFold);
}
/**
* Gets the objectClass of the node
*
* @return array
*/
public function getObjectClass()
{
return $this->getAttribute('objectClass', null);
}
/**
* Gets all attributes of node.
*
* The collection contains all attributes.
*
* This is an offline method.
*
* @param bool $includeSystemAttributes
* @return array
*/
public function getAttributes($includeSystemAttributes = true)
{
$data = [];
foreach ($this->getData($includeSystemAttributes) as $name => $value) {
$data[$name] = $this->getAttribute($name, null);
}
return $data;
}
/**
* Returns the DN of the current node. {@see getDnString()}
*
* @return string
*/
public function toString()
{
return $this->getDnString();
}
/**
* Cast to string representation {@see toString()}
*
* @return string
*/
public function __toString()
{
return $this->toString();
}
/**
* Returns an array representation of the current node
*
* @param bool $includeSystemAttributes
* @return array
*/
public function toArray($includeSystemAttributes = true)
{
$attributes = $this->getAttributes($includeSystemAttributes);
return array_merge(['dn' => $this->getDnString()], $attributes);
}
/**
* Returns a JSON representation of the current node
*
* @param bool $includeSystemAttributes
* @return string
*/
public function toJson($includeSystemAttributes = true)
{
return json_encode($this->toArray($includeSystemAttributes));
}
/**
* Gets node attributes.
*
* The array contains all attributes in its internal format (no conversion).
*
* This is an offline method.
*
* @param bool $includeSystemAttributes
* @return array
*/
public function getData($includeSystemAttributes = true)
{
if ($includeSystemAttributes === false) {
$data = [];
foreach ($this->currentData as $key => $value) {
if (! in_array($key, static::$systemAttributes)) {
$data[$key] = $value;
}
}
return $data;
}
return $this->currentData;
}
/**
* Checks whether a given attribute exists.
*
* If $emptyExists is false empty attributes (containing only array()) are
* treated as non-existent returning false.
* If $emptyExists is true empty attributes are treated as existent returning
* true. In this case method returns false only if the attribute name is
* missing in the key-collection.
*
* @param string $name
* @param bool $emptyExists
* @return bool
*/
public function existsAttribute($name, $emptyExists = false)
{
$name = strtolower($name);
if (isset($this->currentData[$name])) {
if ($emptyExists) {
return true;
}
return count($this->currentData[$name]) > 0;
}
return false;
}
/**
* Checks if the given value(s) exist in the attribute
*
* @param string $attribName
* @param mixed|array $value
* @return bool
*/
public function attributeHasValue($attribName, $value)
{
return Ldap\Attribute::attributeHasValue($this->currentData, $attribName, $value);
}
/**
* Gets a LDAP attribute.
*
* This is an offline method.
*
* @param string $name
* @param int $index
* @return mixed
* @throws LdapException
*/
public function getAttribute($name, $index = null)
{
if ($name === 'dn') {
return $this->getDnString();
}
return Ldap\Attribute::getAttribute($this->currentData, $name, $index);
}
/**
* Gets a LDAP date/time attribute.
*
* This is an offline method.
*
* @param string $name
* @param int $index
* @return array|int
* @throws LdapException
*/
public function getDateTimeAttribute($name, $index = null)
{
return Ldap\Attribute::getDateTimeAttribute($this->currentData, $name, $index);
}
/**
* Sets a LDAP attribute.
*
* This is an offline method.
*
* @param string $name
* @param mixed $value
* @throws BadMethodCallException
*/
public function __set($name, $value)
{
throw new Exception\BadMethodCallException();
}
/**
* Gets a LDAP attribute.
*
* This is an offline method.
*
* @param string $name
* @return mixed
* @throws LdapException
*/
public function __get($name)
{
return $this->getAttribute($name, null);
}
/**
* Deletes a LDAP attribute.
*
* This method deletes the attribute.
*
* This is an offline method.
*
* @param string $name
* @throws BadMethodCallException
*/
public function __unset($name)
{
throw new Exception\BadMethodCallException();
}
/**
* Checks whether a given attribute exists.
*
* Empty attributes will be treated as non-existent.
*
* @param string $name
* @return bool
*/
public function __isset($name)
{
return $this->existsAttribute($name, false);
}
/**
* Sets a LDAP attribute.
* Implements ArrayAccess.
*
* This is an offline method.
*
* @param string $name
* @param mixed $value
* @throws BadMethodCallException
*/
#[ReturnTypeWillChange]
public function offsetSet($name, $value)
{
throw new Exception\BadMethodCallException();
}
/**
* Gets a LDAP attribute.
* Implements ArrayAccess.
*
* This is an offline method.
*
* @param string $name
* @return mixed
* @throws LdapException
*/
#[ReturnTypeWillChange]
public function offsetGet($name)
{
return $this->getAttribute($name, null);
}
/**
* Deletes a LDAP attribute.
* Implements ArrayAccess.
*
* This method deletes the attribute.
*
* This is an offline method.
*
* @param string $name
* @throws BadMethodCallException
*/
#[ReturnTypeWillChange]
public function offsetUnset($name)
{
throw new Exception\BadMethodCallException();
}
/**
* Checks whether a given attribute exists.
* Implements ArrayAccess.
*
* Empty attributes will be treated as non-existent.
*
* @param string $name
* @return bool
*/
#[ReturnTypeWillChange]
public function offsetExists($name)
{
return $this->existsAttribute($name, false);
}
/**
* Returns the number of attributes in node.
* Implements Countable
*
* @return int
*/
#[ReturnTypeWillChange]
public function count()
{
return count($this->currentData);
}
}
laminas-ldap/src/Node/RootDse.php 0000644 00000005254 15240152652 0012662 0 ustar 00 <?php
namespace Laminas\Ldap\Node;
use Laminas\Ldap;
use Laminas\Ldap\Dn;
/**
* Laminas\Ldap\Node\RootDse provides a simple data-container for the RootDse node.
*/
class RootDse extends AbstractNode
{
public const SERVER_TYPE_GENERIC = 1;
public const SERVER_TYPE_OPENLDAP = 2;
public const SERVER_TYPE_ACTIVEDIRECTORY = 3;
public const SERVER_TYPE_EDIRECTORY = 4;
/**
* Factory method to create the RootDse.
*
* @return RootDse
*/
public static function create(Ldap\Ldap $ldap)
{
$dn = Ldap\Dn::fromString('');
$data = $ldap->getEntry($dn, ['*', '+'], true);
if (isset($data['domainfunctionality'])) {
return new RootDse\ActiveDirectory($dn, $data);
} elseif (isset($data['dsaname'])) {
return new RootDse\eDirectory($dn, $data);
} elseif (
isset($data['structuralobjectclass'])
&& $data['structuralobjectclass'][0] === 'OpenLDAProotDSE'
) {
return new RootDse\OpenLdap($dn, $data);
}
return new static($dn, $data);
}
/**
* Constructor is protected to enforce the use of factory methods.
*
* @param array $data
*/
protected function __construct(Ldap\Dn $dn, array $data)
{
parent::__construct($dn, $data, true);
}
/**
* Gets the namingContexts.
*
* @return array
*/
public function getNamingContexts()
{
return $this->getAttribute('namingContexts', null);
}
/**
* Gets the subschemaSubentry.
*
* @return string|null
*/
public function getSubschemaSubentry()
{
return $this->getAttribute('subschemaSubentry', 0);
}
/**
* Determines if the version is supported
*
* @param string|int|array $versions version(s) to check
* @return bool
*/
public function supportsVersion($versions)
{
return $this->attributeHasValue('supportedLDAPVersion', $versions);
}
/**
* Determines if the sasl mechanism is supported
*
* @param string|array $mechlist SASL mechanisms to check
* @return bool
*/
public function supportsSaslMechanism($mechlist)
{
return $this->attributeHasValue('supportedSASLMechanisms', $mechlist);
}
/**
* Gets the server type
*
* @return int
*/
public function getServerType()
{
return self::SERVER_TYPE_GENERIC;
}
/**
* Returns the schema DN
*
* @return Dn
*/
public function getSchemaDn()
{
$schemaDn = $this->getSubschemaSubentry();
return Ldap\Dn::fromString($schemaDn);
}
}
laminas-ldap/src/Node/Schema.php 0000644 00000003525 15240152652 0012502 0 ustar 00 <?php
namespace Laminas\Ldap\Node;
use Laminas\Ldap;
/**
* Laminas\Ldap\Node\Schema provides a simple data-container for the Schema node.
*/
class Schema extends AbstractNode
{
public const OBJECTCLASS_TYPE_UNKNOWN = 0;
public const OBJECTCLASS_TYPE_STRUCTURAL = 1;
public const OBJECTCLASS_TYPE_ABSTRACT = 3;
public const OBJECTCLASS_TYPE_AUXILIARY = 4;
/**
* Factory method to create the Schema node.
*
* @return Schema
*/
public static function create(Ldap\Ldap $ldap)
{
$dn = $ldap->getRootDse()->getSchemaDn();
$data = $ldap->getEntry($dn, ['*', '+'], true);
switch ($ldap->getRootDse()->getServerType()) {
case RootDse::SERVER_TYPE_ACTIVEDIRECTORY:
return new Schema\ActiveDirectory($dn, $data, $ldap);
case RootDse::SERVER_TYPE_OPENLDAP:
return new Schema\OpenLdap($dn, $data, $ldap);
case RootDse::SERVER_TYPE_EDIRECTORY:
default:
return new static($dn, $data, $ldap);
}
}
/**
* Constructor is protected to enforce the use of factory methods.
*
* @param array $data
*/
protected function __construct(Ldap\Dn $dn, array $data, Ldap\Ldap $ldap)
{
parent::__construct($dn, $data, true);
$this->parseSchema($dn, $ldap);
}
/**
* Parses the schema
*
* @return Schema Provides a fluid interface
*/
protected function parseSchema(Ldap\Dn $dn, Ldap\Ldap $ldap)
{
return $this;
}
/**
* Gets the attribute Types
*
* @return array
*/
public function getAttributeTypes()
{
return [];
}
/**
* Gets the object classes
*
* @return array
*/
public function getObjectClasses()
{
return [];
}
}
laminas-ldap/src/Node/Collection.php 0000644 00000001317 15240152652 0013372 0 ustar 00 <?php
namespace Laminas\Ldap\Node;
use Laminas\Ldap;
use Laminas\Ldap\Node;
/**
* Laminas\Ldap\Node\Collection provides a collection of nodes.
*/
class Collection extends Ldap\Collection
{
/**
* Creates the data structure for the given entry data
*
* @param array $data
* @return Node
*/
protected function createEntry(array $data)
{
$node = Ldap\Node::fromArray($data, true);
$node->attachLDAP($this->iterator->getLDAP());
return $node;
}
/**
* Return the child key (DN).
* Implements Iterator and RecursiveIterator
*
* @return string
*/
public function key()
{
return $this->iterator->key();
}
}
laminas-ldap/src/Node/ChildrenIterator.php 0000644 00000007002 15240152652 0014536 0 ustar 00 <?php
namespace Laminas\Ldap\Node;
use ArrayAccess;
use Countable;
use Iterator;
use Laminas\Ldap;
use Laminas\Ldap\Node;
use RecursiveIterator;
use function array_key_exists;
use function count;
use function current;
use function key;
use function next;
use function reset;
/**
* Laminas\Ldap\Node\ChildrenIterator provides an iterator to a collection of children nodes.
*/
class ChildrenIterator implements Iterator, Countable, RecursiveIterator, ArrayAccess
{
/**
* An array of Laminas\Ldap\Node objects
*/
private array $data;
/**
* @param array $data
*/
public function __construct(array $data)
{
$this->data = $data;
}
/**
* Returns the number of child nodes.
* Implements Countable
*
* @return int
*/
public function count()
{
return count($this->data);
}
/**
* Return the current child.
* Implements Iterator
*
* @return Node
*/
public function current()
{
return current($this->data);
}
/**
* Return the child'd RDN.
* Implements Iterator
*
* @return string
*/
public function key()
{
return key($this->data);
}
/**
* Move forward to next child.
* Implements Iterator
*/
public function next()
{
next($this->data);
}
/**
* Rewind the Iterator to the first child.
* Implements Iterator
*/
public function rewind()
{
reset($this->data);
}
/**
* Check if there is a current child
* after calls to rewind() or next().
* Implements Iterator
*
* @return bool
*/
public function valid()
{
return current($this->data) !== false;
}
/**
* Checks if current node has children.
* Returns whether the current element has children.
*
* @return bool
*/
public function hasChildren()
{
if ($this->current() instanceof Ldap\Node) {
return $this->current()->hasChildren();
}
return false;
}
/**
* Returns the children for the current node.
*
* @return ChildrenIterator
*/
public function getChildren()
{
if ($this->current() instanceof Ldap\Node) {
return $this->current()->getChildren();
}
return null;
}
/**
* Returns a child with a given RDN.
* Implements ArrayAccess.
*
* @param string $rdn
* @return array|null
*/
public function offsetGet($rdn)
{
if ($this->offsetExists($rdn)) {
return $this->data[$rdn];
}
return null;
}
/**
* Checks whether a given rdn exists.
* Implements ArrayAccess.
*
* @param string $rdn
* @return bool
*/
public function offsetExists($rdn)
{
return array_key_exists($rdn, $this->data);
}
/**
* Does nothing.
* Implements ArrayAccess.
*
* @param string $name
* @return void
*/
public function offsetUnset($name)
{
}
/**
* Does nothing.
* Implements ArrayAccess.
*
* @param string $name
* @param mixed $value
* @return void
*/
public function offsetSet($name, $value)
{
}
/**
* Get all children as an array
*
* @return array
*/
public function toArray()
{
$data = [];
foreach ($this as $rdn => $node) {
$data[$rdn] = $node;
}
return $data;
}
}
laminas-ldap/src/Node/Schema/ObjectClass/ObjectClassInterface.php 0000644 00000002121 15240152652 0020702 0 ustar 00 <?php
namespace Laminas\Ldap\Node\Schema\ObjectClass;
/**
* This class provides a contract for schema objectClasses.
*/
interface ObjectClassInterface
{
/**
* Gets the objectClass name
*
* @return string
*/
public function getName();
/**
* Gets the objectClass OID
*
* @return string
*/
public function getOid();
/**
* Gets the attributes that this objectClass must contain
*
* @return array
*/
public function getMustContain();
/**
* Gets the attributes that this objectClass may contain
*
* @return array
*/
public function getMayContain();
/**
* Gets the objectClass description
*
* @return string
*/
public function getDescription();
/**
* Gets the objectClass type
*
* @return int
*/
public function getType();
/**
* Returns the parent objectClasses of this class.
* This includes structural, abstract and auxiliary objectClasses
*
* @return array
*/
public function getParentClasses();
}
laminas-ldap/src/Node/Schema/ObjectClass/OpenLdap.php 0000644 00000006220 15240152652 0016373 0 ustar 00 <?php
namespace Laminas\Ldap\Node\Schema\ObjectClass;
use Laminas\Ldap\Node\Schema;
use function array_diff;
use function array_merge;
use function array_unique;
use function sort;
use const SORT_STRING;
/**
* Laminas\Ldap\Node\Schema\ObjectClass\OpenLdap provides access to the objectClass
* schema information on an OpenLDAP server.
*/
class OpenLdap extends Schema\AbstractItem implements ObjectClassInterface
{
/**
* All inherited "MUST" attributes
*
* @var array
*/
protected $inheritedMust;
/**
* All inherited "MAY" attributes
*
* @var array
*/
protected $inheritedMay;
/**
* Gets the objectClass name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Gets the objectClass OID
*
* @return string
*/
public function getOid()
{
return $this->oid;
}
/**
* Gets the attributes that this objectClass must contain
*
* @return array
*/
public function getMustContain()
{
if ($this->inheritedMust === null) {
$this->resolveInheritance();
}
return $this->inheritedMust;
}
/**
* Gets the attributes that this objectClass may contain
*
* @return array
*/
public function getMayContain()
{
if ($this->inheritedMay === null) {
$this->resolveInheritance();
}
return $this->inheritedMay;
}
/**
* Resolves the inheritance tree
*
* @return void
*/
protected function resolveInheritance()
{
$must = $this->must;
$may = $this->may;
foreach ($this->getParents() as $p) {
$must = array_merge($must, $p->getMustContain());
$may = array_merge($may, $p->getMayContain());
}
$must = array_unique($must);
$may = array_unique($may);
$may = array_diff($may, $must);
sort($must, SORT_STRING);
sort($may, SORT_STRING);
$this->inheritedMust = $must;
$this->inheritedMay = $may;
}
/**
* Gets the objectClass description
*
* @return string
*/
public function getDescription()
{
return $this->desc;
}
/**
* Gets the objectClass type
*
* @return int
*/
public function getType()
{
if ($this->structural) {
return Schema::OBJECTCLASS_TYPE_STRUCTURAL;
} elseif ($this->abstract) {
return Schema::OBJECTCLASS_TYPE_ABSTRACT;
} elseif ($this->auxiliary) {
return Schema::OBJECTCLASS_TYPE_AUXILIARY;
}
return Schema::OBJECTCLASS_TYPE_UNKNOWN;
}
/**
* Returns the parent objectClasses of this class.
* This includes structural, abstract and auxiliary objectClasses
*
* @return array
*/
public function getParentClasses()
{
return $this->sup;
}
/**
* Returns the parent object classes in the inheritance tree if one exists
*
* @return array of OpenLdap
*/
public function getParents()
{
return $this->_parents;
}
}
laminas-ldap/src/Node/Schema/ObjectClass/ActiveDirectory.php 0000644 00000002746 15240152652 0020002 0 ustar 00 <?php
namespace Laminas\Ldap\Node\Schema\ObjectClass;
use Laminas\Ldap\Node\Schema;
/**
* Laminas\Ldap\Node\Schema\ObjectClass\ActiveDirectory provides access to the objectClass
* schema information on an Active Directory server.
*/
class ActiveDirectory extends Schema\AbstractItem implements ObjectClassInterface
{
/**
* Gets the objectClass name
*
* @return string
*/
public function getName()
{
return $this->ldapdisplayname[0];
}
/**
* Gets the objectClass OID
*
* @return null
*/
public function getOid()
{
return null;
}
/**
* Gets the attributes that this objectClass must contain
*
* @return null
*/
public function getMustContain()
{
return null;
}
/**
* Gets the attributes that this objectClass may contain
*
* @return null
*/
public function getMayContain()
{
return null;
}
/**
* Gets the objectClass description
*
* @return null
*/
public function getDescription()
{
return null;
}
/**
* Gets the objectClass type
*
* @return null
*/
public function getType()
{
return null;
}
/**
* Returns the parent objectClasses of this class.
* This includes structural, abstract and auxiliary objectClasses
*
* @return null
*/
public function getParentClasses()
{
return null;
}
}
laminas-ldap/src/Node/Schema/AbstractItem.php 0000644 00000005470 15240152652 0015065 0 ustar 00 <?php
namespace Laminas\Ldap\Node\Schema;
use ArrayAccess;
use Countable;
use Laminas\Ldap\Exception;
use Laminas\Ldap\Exception\BadMethodCallException;
use function array_key_exists;
use function count;
/**
* This class provides a base implementation for managing schema
* items like objectClass and attributeType.
*/
abstract class AbstractItem implements ArrayAccess, Countable
{
/**
* The underlying data
*
* @var array
*/
protected $data;
/**
* @param array $data
*/
public function __construct(array $data)
{
$this->setData($data);
}
/**
* Sets the data
*
* @param array $data
* @return AbstractItem Provides a fluid interface
*/
public function setData(array $data)
{
$this->data = $data;
return $this;
}
/**
* Gets the data
*
* @return array
*/
public function getData()
{
return $this->data;
}
/**
* Gets a specific attribute from this item
*
* @param string $name
* @return mixed
*/
public function __get($name)
{
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
return null;
}
/**
* Checks whether a specific attribute exists.
*
* @param string $name
* @return bool
*/
public function __isset($name)
{
return array_key_exists($name, $this->data);
}
/**
* Always throws Laminas\Ldap\Exception\BadMethodCallException
* Implements ArrayAccess.
*
* This method is needed for a full implementation of ArrayAccess
*
* @param string $name
* @param mixed $value
* @throws BadMethodCallException
*/
public function offsetSet($name, $value)
{
throw new Exception\BadMethodCallException();
}
/**
* Gets a specific attribute from this item
*
* @param string $name
* @return mixed
*/
public function offsetGet($name)
{
return $this->__get($name);
}
/**
* Always throws Laminas\Ldap\Exception\BadMethodCallException
* Implements ArrayAccess.
*
* This method is needed for a full implementation of ArrayAccess
*
* @param string $name
* @throws BadMethodCallException
*/
public function offsetUnset($name)
{
throw new Exception\BadMethodCallException();
}
/**
* Checks whether a specific attribute exists.
*
* @param string $name
* @return bool
*/
public function offsetExists($name)
{
return $this->__isset($name);
}
/**
* Returns the number of attributes.
* Implements Countable
*
* @return int
*/
public function count()
{
return count($this->data);
}
}
laminas-ldap/src/Node/Schema/AttributeType/AttributeTypeInterface.php 0000644 00000001545 15240152653 0021736 0 ustar 00 <?php
namespace Laminas\Ldap\Node\Schema\AttributeType;
/**
* This class provides a contract for schema attribute-types.
*/
interface AttributeTypeInterface
{
/**
* Gets the attribute name
*
* @return string
*/
public function getName();
/**
* Gets the attribute OID
*
* @return string
*/
public function getOid();
/**
* Gets the attribute syntax
*
* @return string
*/
public function getSyntax();
/**
* Gets the attribute maximum length
*
* @return int|null
*/
public function getMaxLength();
/**
* Returns if the attribute is single-valued.
*
* @return bool
*/
public function isSingleValued();
/**
* Gets the attribute description
*
* @return string
*/
public function getDescription();
}
laminas-ldap/src/Node/Schema/AttributeType/OpenLdap.php 0000644 00000004046 15240152653 0017011 0 ustar 00 <?php
namespace Laminas\Ldap\Node\Schema\AttributeType;
use Laminas\Ldap\Node\Schema;
use function count;
/**
* Laminas\Ldap\Node\Schema\AttributeType\OpenLdap provides access to the attribute type
* schema information on an OpenLDAP server.
*/
class OpenLdap extends Schema\AbstractItem implements AttributeTypeInterface
{
/**
* Gets the attribute name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Gets the attribute OID
*
* @return string
*/
public function getOid()
{
return $this->oid;
}
/**
* Gets the attribute syntax
*
* @return string
*/
public function getSyntax()
{
if ($this->syntax === null) {
$parent = $this->getParent();
if ($parent === null) {
return;
} else {
return $parent->getSyntax();
}
}
return $this->syntax;
}
/**
* Gets the attribute maximum length
*
* @return int|null
*/
public function getMaxLength()
{
$maxLength = $this->{'max-length'};
if ($maxLength === null) {
$parent = $this->getParent();
if ($parent === null) {
return;
} else {
return $parent->getMaxLength();
}
}
return (int) $maxLength;
}
/**
* Returns if the attribute is single-valued.
*
* @return bool
*/
public function isSingleValued()
{
return $this->{'single-value'};
}
/**
* Gets the attribute description
*
* @return string
*/
public function getDescription()
{
return $this->desc;
}
/**
* Returns the parent attribute type in the inheritance tree if one exists
*
* @return OpenLdap|null
*/
public function getParent()
{
if (count($this->_parents) === 1) {
return $this->_parents[0];
}
return null;
}
}
laminas-ldap/src/Node/Schema/AttributeType/ActiveDirectory.php 0000644 00000002335 15240152653 0020406 0 ustar 00 <?php
namespace Laminas\Ldap\Node\Schema\AttributeType;
use Laminas\Ldap\Node\Schema;
/**
* Laminas\Ldap\Node\Schema\AttributeType\ActiveDirectory provides access to the attribute type
* schema information on an Active Directory server.
*/
class ActiveDirectory extends Schema\AbstractItem implements AttributeTypeInterface
{
/**
* Gets the attribute name
*
* @return string
*/
public function getName()
{
return $this->ldapdisplayname[0];
}
/**
* Gets the attribute OID
*
* @return null
*/
public function getOid()
{
return null;
}
/**
* Gets the attribute syntax
*
* @return null
*/
public function getSyntax()
{
return null;
}
/**
* Gets the attribute maximum length
*
* @return int|null
*/
public function getMaxLength()
{
return null;
}
/**
* Returns if the attribute is single-valued.
*
* @return null
*/
public function isSingleValued()
{
return null;
}
/**
* Gets the attribute description
*
* @return null
*/
public function getDescription()
{
return null;
}
}
laminas-ldap/src/Node/Schema/OpenLdap.php 0000644 00000033523 15240152653 0014206 0 ustar 00 <?php
namespace Laminas\Ldap\Node\Schema;
use Laminas\Ldap;
use Laminas\Ldap\Converter;
use Laminas\Ldap\Node;
use function array_key_exists;
use function array_pop;
use function array_shift;
use function count;
use function in_array;
use function is_array;
use function ksort;
use function preg_match;
use function preg_match_all;
use function strtolower;
use function trim;
use const SORT_STRING;
/**
* Laminas\Ldap\Node\Schema\OpenLDAP provides a simple data-container for the Schema node of
* an OpenLDAP server.
*/
class OpenLdap extends Node\Schema
{
/**
* The attribute Types
*
* @var array
*/
protected $attributeTypes;
/**
* The object classes
*
* @var array
*/
protected $objectClasses;
/**
* The LDAP syntaxes
*
* @var array
*/
protected $ldapSyntaxes;
/**
* The matching rules
*
* @var array
*/
protected $matchingRules;
/**
* The matching rule use
*
* @var array
*/
protected $matchingRuleUse;
/**
* Parses the schema
*
* @return OpenLdap Provides a fluid interface
*/
protected function parseSchema(Ldap\Dn $dn, Ldap\Ldap $ldap)
{
parent::parseSchema($dn, $ldap);
$this->loadAttributeTypes();
$this->loadLdapSyntaxes();
$this->loadMatchingRules();
$this->loadMatchingRuleUse();
$this->loadObjectClasses();
return $this;
}
/**
* Gets the attribute Types
*
* @return array
*/
public function getAttributeTypes()
{
return $this->attributeTypes;
}
/**
* Gets the object classes
*
* @return array
*/
public function getObjectClasses()
{
return $this->objectClasses;
}
/**
* Gets the LDAP syntaxes
*
* @return array
*/
public function getLdapSyntaxes()
{
return $this->ldapSyntaxes;
}
/**
* Gets the matching rules
*
* @return array
*/
public function getMatchingRules()
{
return $this->matchingRules;
}
/**
* Gets the matching rule use
*
* @return array
*/
public function getMatchingRuleUse()
{
return $this->matchingRuleUse;
}
/**
* Loads the attribute Types
*
* @return void
*/
protected function loadAttributeTypes()
{
$this->attributeTypes = [];
foreach ($this->getAttribute('attributeTypes') as $value) {
$val = $this->parseAttributeType($value);
$val = new AttributeType\OpenLdap($val);
$this->attributeTypes[$val->getName()] = $val;
}
foreach ($this->attributeTypes as $val) {
if (! empty($val->sup) && count($val->sup) > 0) {
$this->resolveInheritance($val, $this->attributeTypes);
}
foreach ($val->aliases as $alias) {
$this->attributeTypes[$alias] = $val;
}
}
ksort($this->attributeTypes, SORT_STRING);
}
/**
* Parses an attributeType value
*
* @param string $value
* @return array
*/
protected function parseAttributeType($value)
{
$attributeType = [
'oid' => null,
'name' => null,
'desc' => null,
'obsolete' => false,
'sup' => null,
'equality' => null,
'ordering' => null,
'substr' => null,
'syntax' => null,
'max-length' => null,
'single-value' => false,
'collective' => false,
'no-user-modification' => false,
'usage' => 'userApplications',
'_string' => $value,
'_parents' => [],
];
$tokens = $this->tokenizeString($value);
$attributeType['oid'] = array_shift($tokens); // first token is the oid
$this->parseLdapSchemaSyntax($attributeType, $tokens);
if (array_key_exists('syntax', $attributeType)) {
// get max length from syntax
if (preg_match('/^(.+){(\d+)}$/', $attributeType['syntax'], $matches)) {
$attributeType['syntax'] = $matches[1];
$attributeType['max-length'] = $matches[2];
}
}
$this->ensureNameAttribute($attributeType);
return $attributeType;
}
/**
* Loads the object classes
*
* @return void
*/
protected function loadObjectClasses()
{
$this->objectClasses = [];
foreach ($this->getAttribute('objectClasses') as $value) {
$val = $this->parseObjectClass($value);
$val = new ObjectClass\OpenLdap($val);
$this->objectClasses[$val->getName()] = $val;
}
foreach ($this->objectClasses as $val) {
if (count($val->sup) > 0) {
$this->resolveInheritance($val, $this->objectClasses);
}
foreach ($val->aliases as $alias) {
$this->objectClasses[$alias] = $val;
}
}
ksort($this->objectClasses, SORT_STRING);
}
/**
* Parses an objectClasses value
*
* @param string $value
* @return array
*/
protected function parseObjectClass($value)
{
$objectClass = [
'oid' => null,
'name' => null,
'desc' => null,
'obsolete' => false,
'sup' => [],
'abstract' => false,
'structural' => false,
'auxiliary' => false,
'must' => [],
'may' => [],
'_string' => $value,
'_parents' => [],
];
$tokens = $this->tokenizeString($value);
$objectClass['oid'] = array_shift($tokens); // first token is the oid
$this->parseLdapSchemaSyntax($objectClass, $tokens);
$this->ensureNameAttribute($objectClass);
return $objectClass;
}
/**
* Resolves inheritance in objectClasses and attributes
*
* @param array $repository
*/
protected function resolveInheritance(AbstractItem $node, array $repository)
{
$data = $node->getData();
$parents = $data['sup'];
if ($parents === null || ! is_array($parents) || count($parents) < 1) {
return;
}
foreach ($parents as $parent) {
if (! array_key_exists($parent, $repository)) {
continue;
}
if (! array_key_exists('_parents', $data) || ! is_array($data['_parents'])) {
$data['_parents'] = [];
}
$data['_parents'][] = $repository[$parent];
}
$node->setData($data);
}
/**
* Loads the LDAP syntaxes
*
* @return void
*/
protected function loadLdapSyntaxes()
{
$this->ldapSyntaxes = [];
foreach ($this->getAttribute('ldapSyntaxes') as $value) {
$val = $this->parseLdapSyntax($value);
$this->ldapSyntaxes[$val['oid']] = $val;
}
ksort($this->ldapSyntaxes, SORT_STRING);
}
/**
* Parses an ldapSyntaxes value
*
* @param string $value
* @return array
*/
protected function parseLdapSyntax($value)
{
$ldapSyntax = [
'oid' => null,
'desc' => null,
'_string' => $value,
];
$tokens = $this->tokenizeString($value);
$ldapSyntax['oid'] = array_shift($tokens); // first token is the oid
$this->parseLdapSchemaSyntax($ldapSyntax, $tokens);
return $ldapSyntax;
}
/**
* Loads the matching rules
*
* @return void
*/
protected function loadMatchingRules()
{
$this->matchingRules = [];
foreach ($this->getAttribute('matchingRules') as $value) {
$val = $this->parseMatchingRule($value);
$this->matchingRules[$val['name']] = $val;
}
ksort($this->matchingRules, SORT_STRING);
}
/**
* Parses a matchingRules value
*
* @param string $value
* @return array
*/
protected function parseMatchingRule($value)
{
$matchingRule = [
'oid' => null,
'name' => null,
'desc' => null,
'obsolete' => false,
'syntax' => null,
'_string' => $value,
];
$tokens = $this->tokenizeString($value);
$matchingRule['oid'] = array_shift($tokens); // first token is the oid
$this->parseLdapSchemaSyntax($matchingRule, $tokens);
$this->ensureNameAttribute($matchingRule);
return $matchingRule;
}
/**
* Loads the matching rule use
*
* @return void
*/
protected function loadMatchingRuleUse()
{
$this->matchingRuleUse = [];
foreach ($this->getAttribute('matchingRuleUse') as $value) {
$val = $this->parseMatchingRuleUse($value);
$this->matchingRuleUse[$val['name']] = $val;
}
ksort($this->matchingRuleUse, SORT_STRING);
}
/**
* Parses a matchingRuleUse value
*
* @param string $value
* @return array
*/
protected function parseMatchingRuleUse($value)
{
$matchingRuleUse = [
'oid' => null,
'name' => null,
'desc' => null,
'obsolete' => false,
'applies' => [],
'_string' => $value,
];
$tokens = $this->tokenizeString($value);
$matchingRuleUse['oid'] = array_shift($tokens); // first token is the oid
$this->parseLdapSchemaSyntax($matchingRuleUse, $tokens);
$this->ensureNameAttribute($matchingRuleUse);
return $matchingRuleUse;
}
/**
* Ensures that a name element is present and that it is single-values.
*
* @param array $data
*/
protected function ensureNameAttribute(array &$data)
{
if (! array_key_exists('name', $data) || empty($data['name'])) {
// force a name
$data['name'] = $data['oid'];
}
if (is_array($data['name'])) {
// make one name the default and put the other ones into aliases
$aliases = $data['name'];
$data['name'] = array_shift($aliases);
$data['aliases'] = $aliases;
} else {
$data['aliases'] = [];
}
}
/**
* Parse the given tokens into a data structure
*
* @param array $data
* @param array $tokens
* @return void
*/
protected function parseLdapSchemaSyntax(array &$data, array $tokens)
{
// tokens that have no value associated
$noValue = [
'single-value',
'obsolete',
'collective',
'no-user-modification',
'abstract',
'structural',
'auxiliary',
];
// tokens that can have multiple values
$multiValue = ['must', 'may', 'sup'];
while (count($tokens) > 0) {
$token = strtolower(array_shift($tokens));
if (in_array($token, $noValue)) {
$data[$token] = true; // single value token
} else {
$data[$token] = array_shift($tokens);
// this one follows a string or a list if it is multivalued
if ($data[$token] === '(') {
// this creates the list of values and cycles through the tokens
// until the end of the list is reached ')'
$data[$token] = [];
$tmp = array_shift($tokens);
while ($tmp) {
if ($tmp === ')') {
break;
}
if ($tmp !== '$') {
$data[$token][] = Converter\Converter::fromLdap($tmp);
}
$tmp = array_shift($tokens);
}
} else {
$data[$token] = Converter\Converter::fromLdap($data[$token]);
}
// create an array if the value should be multivalued but was not
if (in_array($token, $multiValue) && ! is_array($data[$token])) {
$data[$token] = [$data[$token]];
}
}
}
}
/**
* Tokenizes the given value into an array
*
* @param string $value
* @return array tokens
*/
protected function tokenizeString($value)
{
$tokens = [];
$matches = [];
// this one is taken from PEAR::Net_LDAP2
$pattern = "/\\s* (?:([()]) | ([^'\\s()]+) | '((?:[^']+|'[^\\s)])*)') \\s*/x";
preg_match_all($pattern, $value, $matches);
$cMatches = count($matches[0]);
$cPattern = count($matches);
for ($i = 0; $i < $cMatches; $i++) { // number of tokens (full pattern match)
for ($j = 1; $j < $cPattern; $j++) { // each subpattern
$tok = trim($matches[$j][$i]);
if (! empty($tok)) { // pattern match in this subpattern
$tokens[$i] = $tok; // this is the token
}
}
}
if ($tokens[0] === '(') {
array_shift($tokens);
}
if ($tokens[count($tokens) - 1] === ')') {
array_pop($tokens);
}
return $tokens;
}
}
laminas-ldap/src/Node/Schema/ActiveDirectory.php 0000644 00000003344 15240152653 0015602 0 ustar 00 <?php
namespace Laminas\Ldap\Node\Schema;
use Laminas\Ldap;
use Laminas\Ldap\Node;
/**
* Laminas\Ldap\Node\Schema\ActiveDirectory provides a simple data-container for the Schema node of
* an Active Directory server.
*/
class ActiveDirectory extends Node\Schema
{
/**
* The attribute Types
*
* @var array
*/
protected $attributeTypes = [];
/**
* The object classes
*
* @var array
*/
protected $objectClasses = [];
/**
* Parses the schema
*
* @return ActiveDirectory Provides a fluid interface
*/
protected function parseSchema(Ldap\Dn $dn, Ldap\Ldap $ldap)
{
parent::parseSchema($dn, $ldap);
foreach (
$ldap->search(
'(objectClass=classSchema)',
$dn,
Ldap\Ldap::SEARCH_SCOPE_ONE
) as $node
) {
$val = new ObjectClass\ActiveDirectory($node);
$this->objectClasses[$val->getName()] = $val;
}
foreach (
$ldap->search(
'(objectClass=attributeSchema)',
$dn,
Ldap\Ldap::SEARCH_SCOPE_ONE
) as $node
) {
$val = new AttributeType\ActiveDirectory($node);
$this->attributeTypes[$val->getName()] = $val;
}
return $this;
}
/**
* Gets the attribute Types
*
* @return array
*/
public function getAttributeTypes()
{
return $this->attributeTypes;
}
/**
* Gets the object classes
*
* @return array
*/
public function getObjectClasses()
{
return $this->objectClasses;
}
}
laminas-ldap/src/Node/RootDse/OpenLdap.php 0000644 00000003065 15240152653 0014363 0 ustar 00 <?php
namespace Laminas\Ldap\Node\RootDse;
use Laminas\Ldap\Node;
/**
* Laminas\Ldap\Node\RootDse\OpenLdap provides a simple data-container for the
* RootDse node of an OpenLDAP server.
*/
class OpenLdap extends Node\RootDse
{
/**
* Gets the configContext.
*
* @return string|null
*/
public function getConfigContext()
{
return $this->getAttribute('configContext', 0);
}
/**
* Gets the monitorContext.
*
* @return string|null
*/
public function getMonitorContext()
{
return $this->getAttribute('monitorContext', 0);
}
/**
* Determines if the control is supported
*
* @param string|array $oids control oid(s) to check
* @return bool
*/
public function supportsControl($oids)
{
return $this->attributeHasValue('supportedControl', $oids);
}
/**
* Determines if the extension is supported
*
* @param string|array $oids oid(s) to check
* @return bool
*/
public function supportsExtension($oids)
{
return $this->attributeHasValue('supportedExtension', $oids);
}
/**
* Determines if the feature is supported
*
* @param string|array $oids feature oid(s) to check
* @return bool
*/
public function supportsFeature($oids)
{
return $this->attributeHasValue('supportedFeatures', $oids);
}
/**
* Gets the server type
*
* @return int
*/
public function getServerType()
{
return self::SERVER_TYPE_OPENLDAP;
}
}
laminas-ldap/src/Node/RootDse/eDirectory.php 0000644 00000005367 15240152654 0015002 0 ustar 00 <?php
namespace Laminas\Ldap\Node\RootDse;
use Laminas\Ldap\Node;
/**
* Laminas\Ldap\Node\RootDse\eDirectory provides a simple data-container for the
* RootDse node of a Novell eDirectory server.
*/
// @codingStandardsIgnoreStart
class eDirectory extends Node\RootDse
{
// @codingStandardsIgnoreEnd
/**
* Determines if the extension is supported
*
* @param string|array $oids oid(s) to check
* @return bool
*/
public function supportsExtension($oids)
{
return $this->attributeHasValue('supportedExtension', $oids);
}
/**
* Gets the vendorName.
*
* @return string|null
*/
public function getVendorName()
{
return $this->getAttribute('vendorName', 0);
}
/**
* Gets the vendorVersion.
*
* @return string|null
*/
public function getVendorVersion()
{
return $this->getAttribute('vendorVersion', 0);
}
/**
* Gets the dsaName.
*
* @return string|null
*/
public function getDsaName()
{
return $this->getAttribute('dsaName', 0);
}
/**
* Gets the server statistics "errors".
*
* @return string|null
*/
public function getStatisticsErrors()
{
return $this->getAttribute('errors', 0);
}
/**
* Gets the server statistics "securityErrors".
*
* @return string|null
*/
public function getStatisticsSecurityErrors()
{
return $this->getAttribute('securityErrors', 0);
}
/**
* Gets the server statistics "chainings".
*
* @return string|null
*/
public function getStatisticsChainings()
{
return $this->getAttribute('chainings', 0);
}
/**
* Gets the server statistics "referralsReturned".
*
* @return string|null
*/
public function getStatisticsReferralsReturned()
{
return $this->getAttribute('referralsReturned', 0);
}
/**
* Gets the server statistics "extendedOps".
*
* @return string|null
*/
public function getStatisticsExtendedOps()
{
return $this->getAttribute('extendedOps', 0);
}
/**
* Gets the server statistics "abandonOps".
*
* @return string|null
*/
public function getStatisticsAbandonOps()
{
return $this->getAttribute('abandonOps', 0);
}
/**
* Gets the server statistics "wholeSubtreeSearchOps".
*
* @return string|null
*/
public function getStatisticsWholeSubtreeSearchOps()
{
return $this->getAttribute('wholeSubtreeSearchOps', 0);
}
/**
* Gets the server type
*
* @return int
*/
public function getServerType()
{
return self::SERVER_TYPE_EDIRECTORY;
}
}
laminas-ldap/src/Node/RootDse/ActiveDirectory.php 0000644 00000010735 15240152654 0015764 0 ustar 00 <?php
namespace Laminas\Ldap\Node\RootDse;
use Laminas\Ldap;
use Laminas\Ldap\Dn;
use Laminas\Ldap\Node;
/**
* Laminas\Ldap\Node\RootDse\ActiveDirectory provides a simple data-container for
* the RootDse node of an Active Directory server.
*/
class ActiveDirectory extends Node\RootDse
{
/**
* Gets the configurationNamingContext.
*
* @return string|null
*/
public function getConfigurationNamingContext()
{
return $this->getAttribute('configurationNamingContext', 0);
}
/**
* Gets the currentTime.
*
* @return string|null
*/
public function getCurrentTime()
{
return $this->getAttribute('currentTime', 0);
}
/**
* Gets the defaultNamingContext.
*
* @return string|null
*/
public function getDefaultNamingContext()
{
return $this->getAttribute('defaultNamingContext', 0);
}
/**
* Gets the dnsHostName.
*
* @return string|null
*/
public function getDnsHostName()
{
return $this->getAttribute('dnsHostName', 0);
}
/**
* Gets the domainControllerFunctionality.
*
* @return string|null
*/
public function getDomainControllerFunctionality()
{
return $this->getAttribute('domainControllerFunctionality', 0);
}
/**
* Gets the domainFunctionality.
*
* @return string|null
*/
public function getDomainFunctionality()
{
return $this->getAttribute('domainFunctionality', 0);
}
/**
* Gets the dsServiceName.
*
* @return string|null
*/
public function getDsServiceName()
{
return $this->getAttribute('dsServiceName', 0);
}
/**
* Gets the forestFunctionality.
*
* @return string|null
*/
public function getForestFunctionality()
{
return $this->getAttribute('forestFunctionality', 0);
}
/**
* Gets the highestCommittedUSN.
*
* @return string|null
*/
public function getHighestCommittedUSN()
{
return $this->getAttribute('highestCommittedUSN', 0);
}
/**
* Gets the isGlobalCatalogReady.
*
* @return string|null
*/
public function getIsGlobalCatalogReady()
{
return $this->getAttribute('isGlobalCatalogReady', 0);
}
/**
* Gets the isSynchronized.
*
* @return string|null
*/
public function getIsSynchronized()
{
return $this->getAttribute('isSynchronized', 0);
}
/**
* Gets the ldapServiceName.
*
* @return string|null
*/
public function getLDAPServiceName()
{
return $this->getAttribute('ldapServiceName', 0);
}
/**
* Gets the rootDomainNamingContext.
*
* @return string|null
*/
public function getRootDomainNamingContext()
{
return $this->getAttribute('rootDomainNamingContext', 0);
}
/**
* Gets the schemaNamingContext.
*
* @return string|null
*/
public function getSchemaNamingContext()
{
return $this->getAttribute('schemaNamingContext', 0);
}
/**
* Gets the serverName.
*
* @return string|null
*/
public function getServerName()
{
return $this->getAttribute('serverName', 0);
}
/**
* Determines if the capability is supported
*
* @param string|string|array $oids capability(s) to check
* @return bool
*/
public function supportsCapability($oids)
{
return $this->attributeHasValue('supportedCapabilities', $oids);
}
/**
* Determines if the control is supported
*
* @param string|array $oids control oid(s) to check
* @return bool
*/
public function supportsControl($oids)
{
return $this->attributeHasValue('supportedControl', $oids);
}
/**
* Determines if the version is supported
*
* @param string|array $policies policy(s) to check
* @return bool
*/
public function supportsPolicy($policies)
{
return $this->attributeHasValue('supportedLDAPPolicies', $policies);
}
/**
* Gets the server type
*
* @return int
*/
public function getServerType()
{
return self::SERVER_TYPE_ACTIVEDIRECTORY;
}
/**
* Returns the schema DN
*
* @return Dn
*/
public function getSchemaDn()
{
$schemaDn = $this->getSchemaNamingContext();
return Ldap\Dn::fromString($schemaDn);
}
}
laminas-ldap/src/Attribute.php 0000644 00000026132 15240152654 0012361 0 ustar 00 <?php
namespace Laminas\Ldap;
use DateTime;
use Traversable;
use function array_keys;
use function array_merge;
use function array_unique;
use function array_values;
use function base64_encode;
use function count;
use function function_exists;
use function iconv;
use function in_array;
use function is_array;
use function is_int;
use function is_scalar;
use function is_string;
use function mb_convert_encoding;
use function md5;
use function mt_rand;
use function sha1;
use function strlen;
use function strtolower;
use function substr;
use function uniqid;
/**
* Laminas\Ldap\Attribute is a collection of LDAP attribute related functions.
*/
class Attribute
{
public const PASSWORD_HASH_MD5 = 'md5';
public const PASSWORD_HASH_SMD5 = 'smd5';
public const PASSWORD_HASH_SHA = 'sha';
public const PASSWORD_HASH_SSHA = 'ssha';
public const PASSWORD_UNICODEPWD = 'unicodePwd';
/**
* Sets a LDAP attribute.
*
* @param array $data
* @param string $attribName
* @param string|array|Traversable $value
* @param bool $append
* @return void
*/
public static function setAttribute(array &$data, $attribName, $value, $append = false)
{
$attribName = strtolower($attribName);
$valArray = [];
if (is_array($value) || $value instanceof Traversable) {
foreach ($value as $v) {
$v = self::valueToLdap($v);
if ($v !== null) {
$valArray[] = $v;
}
}
} elseif ($value !== null) {
$value = self::valueToLdap($value);
if ($value !== null) {
$valArray[] = $value;
}
}
if ($append === true && isset($data[$attribName])) {
if (is_string($data[$attribName])) {
$data[$attribName] = [$data[$attribName]];
}
$data[$attribName] = array_merge($data[$attribName], $valArray);
} else {
$data[$attribName] = $valArray;
}
}
/**
* Gets a LDAP attribute.
*
* @param array $data
* @param string $attribName
* @param int $index
* @return array|mixed
*/
public static function getAttribute(array $data, $attribName, $index = null)
{
$attribName = strtolower($attribName);
if ($index === null) {
if (! isset($data[$attribName])) {
return [];
}
$retArray = [];
foreach ($data[$attribName] as $v) {
$retArray[] = self::valueFromLdap($v);
}
return $retArray;
} elseif (is_int($index)) {
if (! isset($data[$attribName])) {
return;
} elseif ($index >= 0 && $index < count($data[$attribName])) {
return self::valueFromLdap($data[$attribName][$index]);
} else {
return;
}
}
return null;
}
/**
* Checks if the given value(s) exist in the attribute
*
* @param array $data
* @param string $attribName
* @param mixed|array $value
* @return bool
*/
public static function attributeHasValue(array &$data, $attribName, $value)
{
$attribName = strtolower($attribName);
if (! isset($data[$attribName])) {
return false;
}
if (is_scalar($value)) {
$value = [$value];
}
foreach ($value as $v) {
$v = self::valueToLdap($v);
if (! in_array($v, $data[$attribName], true)) {
return false;
}
}
return true;
}
/**
* Removes duplicate values from a LDAP attribute
*
* @param array $data
* @param string $attribName
* @return void
*/
public static function removeDuplicatesFromAttribute(array &$data, $attribName)
{
$attribName = strtolower($attribName);
if (! isset($data[$attribName])) {
return;
}
$data[$attribName] = array_values(array_unique($data[$attribName]));
}
/**
* Remove given values from a LDAP attribute
*
* @param array $data
* @param string $attribName
* @param mixed|array $value
* @return void
*/
public static function removeFromAttribute(array &$data, $attribName, $value)
{
$attribName = strtolower($attribName);
if (! isset($data[$attribName])) {
return;
}
if (is_scalar($value)) {
$value = [$value];
}
$valArray = [];
foreach ($value as $v) {
$v = self::valueToLdap($v);
if ($v !== null) {
$valArray[] = $v;
}
}
$resultArray = $data[$attribName];
foreach ($valArray as $rv) {
$keys = array_keys($resultArray, $rv);
foreach ($keys as $k) {
unset($resultArray[$k]);
}
}
$resultArray = array_values($resultArray);
$data[$attribName] = $resultArray;
}
/**
* @param mixed $value
* @return string|null
*/
private static function valueToLdap($value)
{
return Converter\Converter::toLdap($value);
}
/**
* @param string $value
* @return mixed
*/
private static function valueFromLdap($value)
{
try {
$return = Converter\Converter::fromLdap($value, Converter\Converter::STANDARD, false);
if ($return instanceof DateTime) {
return Converter\Converter::toLdapDateTime($return, false);
} else {
return $return;
}
} catch (Converter\Exception\InvalidArgumentException $e) {
return $value;
}
}
/**
* Sets a LDAP password.
*
* @param array $data
* @param string $password
* @param string $hashType Optional by default MD5
* @param string $attribName Optional
*/
public static function setPassword(
array &$data,
$password,
$hashType = self::PASSWORD_HASH_MD5,
$attribName = null
) {
if ($attribName === null) {
if ($hashType === self::PASSWORD_UNICODEPWD) {
$attribName = 'unicodePwd';
} else {
$attribName = 'userPassword';
}
}
$hash = static::createPassword($password, $hashType);
static::setAttribute($data, $attribName, $hash, false);
}
/**
* Creates a LDAP password.
*
* @param string $password
* @param string $hashType
* @return string
*/
public static function createPassword($password, $hashType = self::PASSWORD_HASH_MD5)
{
switch ($hashType) {
case self::PASSWORD_UNICODEPWD:
/* see:
* http://msdn.microsoft.com/en-us/library/cc223248(PROT.10).aspx
*/
$password = '"' . $password . '"';
if (function_exists('mb_convert_encoding')) {
$password = mb_convert_encoding($password, 'UTF-16LE', 'UTF-8');
} elseif (function_exists('iconv')) {
$password = iconv('UTF-8', 'UTF-16LE', $password);
} else {
$len = strlen($password);
$new = '';
for ($i = 0; $i < $len; $i++) {
$new .= $password[$i] . "\x00";
}
$password = $new;
}
return $password;
case self::PASSWORD_HASH_SSHA:
$salt = substr(sha1(uniqid(mt_rand(), true), true), 0, 4);
$rawHash = sha1($password . $salt, true) . $salt;
$method = '{SSHA}';
break;
case self::PASSWORD_HASH_SHA:
$rawHash = sha1($password, true);
$method = '{SHA}';
break;
case self::PASSWORD_HASH_SMD5:
$salt = substr(sha1(uniqid(mt_rand(), true), true), 0, 4);
$rawHash = md5($password . $salt, true) . $salt;
$method = '{SMD5}';
break;
case self::PASSWORD_HASH_MD5:
default:
$rawHash = md5($password, true);
$method = '{MD5}';
break;
}
return $method . base64_encode($rawHash);
}
/**
* Sets a LDAP date/time attribute.
*
* @param array $data
* @param string $attribName
* @param int|array|Traversable $value
* @param bool $utc
* @param bool $append
*/
public static function setDateTimeAttribute(
array &$data,
$attribName,
$value,
$utc = false,
$append = false
) {
$convertedValues = [];
if (is_array($value) || $value instanceof Traversable) {
foreach ($value as $v) {
$v = self::valueToLdapDateTime($v, $utc);
if ($v !== null) {
$convertedValues[] = $v;
}
}
} elseif ($value !== null) {
$value = self::valueToLdapDateTime($value, $utc);
if ($value !== null) {
$convertedValues[] = $value;
}
}
static::setAttribute($data, $attribName, $convertedValues, $append);
}
/**
* @param int $value
* @param bool $utc
* @return string|null
*/
private static function valueToLdapDateTime($value, $utc)
{
if (! is_int($value)) {
return null;
}
return Converter\Converter::toLdapDateTime($value, $utc);
}
/**
* Gets a LDAP date/time attribute.
*
* @param array $data
* @param string $attribName
* @param int $index
* @return array|int
*/
public static function getDateTimeAttribute(array $data, $attribName, $index = null)
{
$values = static::getAttribute($data, $attribName, $index);
if (is_array($values)) {
for ($i = 0, $count = count($values); $i < $count; $i++) {
$newVal = self::valueFromLdapDateTime($values[$i]);
if ($newVal !== null) {
$values[$i] = $newVal;
}
}
} else {
$newVal = self::valueFromLdapDateTime($values);
if ($newVal !== null) {
$values = $newVal;
}
}
return $values;
}
/**
* @param string|DateTime $value
* @return int|null
*/
private static function valueFromLdapDateTime($value)
{
if ($value instanceof DateTime) {
return $value->format('U');
}
if (! is_string($value)) {
return null;
}
try {
return Converter\Converter::fromLdapDateTime($value, false)->format('U');
} catch (Converter\Exception\InvalidArgumentException $e) {
return null;
}
}
}
laminas-ldap/psalm.xml.dist 0000644 00000002413 15240152654 0011712 0 ustar 00 <?xml version="1.0"?>
<psalm
errorLevel="1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
errorBaseline="psalm-baseline.xml"
findUnusedPsalmSuppress="true"
>
<projectFiles>
<directory name="src"/>
<directory name="test"/>
<ignoreFiles>
<directory name=".github"/>
<directory name="docs"/>
<directory name="vendor"/>
</ignoreFiles>
</projectFiles>
<issueHandlers>
<InternalMethod>
<errorLevel type="suppress">
<referencedMethod name="PHPUnit\Framework\MockObject\Builder\InvocationMocker::method"/>
</errorLevel>
<errorLevel type="suppress">
<referencedMethod name="PHPUnit\Framework\MockObject\Builder\InvocationMocker::willReturn"/>
</errorLevel>
<errorLevel type="suppress">
<referencedMethod name="PHPUnit\Framework\MockObject\Builder\InvocationMocker::with"/>
</errorLevel>
</InternalMethod>
</issueHandlers>
<plugins>
<pluginClass class="Psalm\PhpUnitPlugin\Plugin"/>
</plugins>
</psalm> laminas-ldap/README.md 0000644 00000006420 15240152654 0010373 0 ustar 00 # laminas-ldap
[](https://github.com/laminas/laminas-ldap/actions/workflows/continuous-integration.yml)
[](https://coveralls.io/github/laminas/laminas-ldap?branch=master)
> ## 🇷🇺 Русским гражданам
>
> Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм.
>
> У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую.
>
> Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!"
>
> ## 🇺🇸 To Citizens of Russia
>
> We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism.
>
> One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences.
>
> You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!"
laminas-ldap provides functionality for performing LDAP operations, including, but
not limited to, binding, searching and modifying entries in an LDAP directory.
- File issues at https://github.com/laminas/laminas-ldap/issues
- Documentation is at https://docs.laminas.dev/laminas-ldap/
laminas-ldap/composer.json 0000644 00000004062 15240152654 0011636 0 ustar 00 {
"name": "laminas/laminas-ldap",
"description": "Provides support for LDAP operations including but not limited to binding, searching and modifying entries in an LDAP directory",
"license": "BSD-3-Clause",
"keywords": [
"laminas",
"ldap"
],
"homepage": "https://laminas.dev",
"support": {
"docs": "https://docs.laminas.dev/laminas-ldap/",
"issues": "https://github.com/laminas/laminas-ldap/issues",
"source": "https://github.com/laminas/laminas-ldap",
"rss": "https://github.com/laminas/laminas-ldap/releases.atom",
"chat": "https://laminas.dev/chat",
"forum": "https://discourse.laminas.dev"
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
},
"platform": {
"php": "8.0.99"
},
"sort-packages": true
},
"extra": {
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"ext-ldap": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"laminas/laminas-config": "^3.8.0",
"laminas/laminas-eventmanager": "^3.6.0",
"laminas/laminas-stdlib": "^3.15.0",
"php-mock/php-mock-phpunit": "^2.6.1",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.29.0"
},
"suggest": {
"laminas/laminas-eventmanager": "Laminas\\EventManager component"
},
"autoload": {
"psr-4": {
"Laminas\\Ldap\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"LaminasTest\\Ldap\\": "test/"
}
},
"scripts": {
"check": [
"@cs-check",
"@test"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"static-analysis": "psalm --shepherd --stats",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
},
"conflict": {
"zendframework/zend-ldap": "*"
}
}
laminas-ldap/COPYRIGHT.md 0000644 00000000133 15240152654 0011001 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/)
laminas-ldap/Vagrantfile 0000644 00000002336 15240152654 0011303 0 ustar 00 # -*- mode: ruby -*-
# vi: set ft=ruby :
$install_ldap = <<SCRIPT
export DEBIAN_FRONTEND=noninteractive
apt-get -yq update
apt-get -yq --no-install-suggests --no-install-recommends --force-yes install slapd ldap-utils apparmor-utils conntrack php5-cli
sudo aa-complain /usr/sbin/slapd
SCRIPT
$setup_vagrant_user_environment = <<SCRIPT
if ! grep "cd /vagrant" /home/vagrant/.profile > /dev/null; then
echo "cd /vagrant" >> /home/vagrant/.profile
fi
SCRIPT
Vagrant.configure(2) do |config|
config.vm.box = 'bento/ubuntu-14.04'
# LDAP port
config.vm.network 'forwarded_port', guest: 3890, host: 3890
config.vm.network 'forwarded_port', guest: 6360, host: 6360
# PHP embedded webserver port, running in .ci/php_scripts
config.vm.network 'forwarded_port', guest: 3891, host: 3891
config.vm.provision 'shell', privileged: true, inline: '/vagrant/.ci/config_iptables.sh', :run => 'always'
config.vm.provision 'shell', inline: $install_ldap
config.vm.provision 'shell', privileged: false, inline: '/vagrant/.ci/OpenLDAP_run.sh', :run => 'always'
config.vm.provision 'shell', privileged: false, inline: '/vagrant/.ci/load_fixtures.sh', :run => 'always'
config.vm.provision 'shell', inline: $setup_vagrant_user_environment
end
laminas-ldap/composer.lock 0000644 00000476447 15240152654 0011641 0 ustar 00 {
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "1099a636679a33bd69b1a631231da4e6",
"packages": [],
"packages-dev": [
{
"name": "amphp/amp",
"version": "v2.6.2",
"source": {
"type": "git",
"url": "https://github.com/amphp/amp.git",
"reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb",
"reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"amphp/php-cs-fixer-config": "dev-master",
"amphp/phpunit-util": "^1",
"ext-json": "*",
"jetbrains/phpstorm-stubs": "^2019.3",
"phpunit/phpunit": "^7 | ^8 | ^9",
"psalm/phar": "^3.11@dev",
"react/promise": "^2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
},
"autoload": {
"files": [
"lib/functions.php",
"lib/Internal/functions.php"
],
"psr-4": {
"Amp\\": "lib"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Daniel Lowrey",
"email": "rdlowrey@php.net"
},
{
"name": "Aaron Piotrowski",
"email": "aaron@trowski.com"
},
{
"name": "Bob Weinand",
"email": "bobwei9@hotmail.com"
},
{
"name": "Niklas Keller",
"email": "me@kelunik.com"
}
],
"description": "A non-blocking concurrency framework for PHP applications.",
"homepage": "https://amphp.org/amp",
"keywords": [
"async",
"asynchronous",
"awaitable",
"concurrency",
"event",
"event-loop",
"future",
"non-blocking",
"promise"
],
"support": {
"irc": "irc://irc.freenode.org/amphp",
"issues": "https://github.com/amphp/amp/issues",
"source": "https://github.com/amphp/amp/tree/v2.6.2"
},
"funding": [
{
"url": "https://github.com/amphp",
"type": "github"
}
],
"time": "2022-02-20T17:52:18+00:00"
},
{
"name": "amphp/byte-stream",
"version": "v1.8.1",
"source": {
"type": "git",
"url": "https://github.com/amphp/byte-stream.git",
"reference": "acbd8002b3536485c997c4e019206b3f10ca15bd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd",
"reference": "acbd8002b3536485c997c4e019206b3f10ca15bd",
"shasum": ""
},
"require": {
"amphp/amp": "^2",
"php": ">=7.1"
},
"require-dev": {
"amphp/php-cs-fixer-config": "dev-master",
"amphp/phpunit-util": "^1.4",
"friendsofphp/php-cs-fixer": "^2.3",
"jetbrains/phpstorm-stubs": "^2019.3",
"phpunit/phpunit": "^6 || ^7 || ^8",
"psalm/phar": "^3.11.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"files": [
"lib/functions.php"
],
"psr-4": {
"Amp\\ByteStream\\": "lib"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Aaron Piotrowski",
"email": "aaron@trowski.com"
},
{
"name": "Niklas Keller",
"email": "me@kelunik.com"
}
],
"description": "A stream abstraction to make working with non-blocking I/O simple.",
"homepage": "http://amphp.org/byte-stream",
"keywords": [
"amp",
"amphp",
"async",
"io",
"non-blocking",
"stream"
],
"support": {
"irc": "irc://irc.freenode.org/amphp",
"issues": "https://github.com/amphp/byte-stream/issues",
"source": "https://github.com/amphp/byte-stream/tree/v1.8.1"
},
"funding": [
{
"url": "https://github.com/amphp",
"type": "github"
}
],
"time": "2021-03-30T17:13:30+00:00"
},
{
"name": "composer/package-versions-deprecated",
"version": "1.11.99.5",
"source": {
"type": "git",
"url": "https://github.com/composer/package-versions-deprecated.git",
"reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d",
"reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.1.0 || ^2.0",
"php": "^7 || ^8"
},
"replace": {
"ocramius/package-versions": "1.11.99"
},
"require-dev": {
"composer/composer": "^1.9.3 || ^2.0@dev",
"ext-zip": "^1.13",
"phpunit/phpunit": "^6.5 || ^7"
},
"type": "composer-plugin",
"extra": {
"class": "PackageVersions\\Installer",
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"PackageVersions\\": "src/PackageVersions"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be"
}
],
"description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
"support": {
"issues": "https://github.com/composer/package-versions-deprecated/issues",
"source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-01-17T14:14:24+00:00"
},
{
"name": "composer/pcre",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
"reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/e300eb6c535192decd27a85bc72a9290f0d6b3bd",
"reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1.3",
"phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Pcre\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "PCRE wrapping library that offers type-safe preg_* replacements.",
"keywords": [
"PCRE",
"preg",
"regex",
"regular expression"
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.0.0"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-02-25T20:21:48+00:00"
},
{
"name": "composer/semver",
"version": "3.3.2",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1.4",
"symfony/phpunit-bridge": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Semver\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
},
{
"name": "Rob Bast",
"email": "rob.bast@gmail.com",
"homepage": "http://robbast.nl"
}
],
"description": "Semver library that offers utilities, version constraint parsing and validation.",
"keywords": [
"semantic",
"semver",
"validation",
"versioning"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.3.2"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-04-01T19:23:25+00:00"
},
{
"name": "composer/xdebug-handler",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
"reference": "ced299686f41dce890debac69273b47ffe98a40c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c",
"reference": "ced299686f41dce890debac69273b47ffe98a40c",
"shasum": ""
},
"require": {
"composer/pcre": "^1 || ^2 || ^3",
"php": "^7.2.5 || ^8.0",
"psr/log": "^1 || ^2 || ^3"
},
"require-dev": {
"phpstan/phpstan": "^1.0",
"phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Composer\\XdebugHandler\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "John Stevenson",
"email": "john-stevenson@blueyonder.co.uk"
}
],
"description": "Restarts a process without Xdebug.",
"keywords": [
"Xdebug",
"performance"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/xdebug-handler/issues",
"source": "https://github.com/composer/xdebug-handler/tree/3.0.3"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-02-25T21:32:43+00:00"
},
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
"version": "v0.7.2",
"source": {
"type": "git",
"url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
"phpcompatibility/php-compatibility": "^9.0"
},
"type": "composer-plugin",
"extra": {
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
"Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Franck Nijhof",
"email": "franck.nijhof@dealerdirect.com",
"homepage": "http://www.frenck.nl",
"role": "Developer / IT Manager"
},
{
"name": "Contributors",
"homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
"homepage": "http://www.dealerdirect.com",
"keywords": [
"PHPCodeSniffer",
"PHP_CodeSniffer",
"code quality",
"codesniffer",
"composer",
"installer",
"phpcbf",
"phpcs",
"plugin",
"qa",
"quality",
"standard",
"standards",
"style guide",
"stylecheck",
"tests"
],
"support": {
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
"time": "2022-02-04T12:51:07+00:00"
},
{
"name": "dnoegel/php-xdg-base-dir",
"version": "v0.1.1",
"source": {
"type": "git",
"url": "https://github.com/dnoegel/php-xdg-base-dir.git",
"reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd",
"reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"require-dev": {
"phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35"
},
"type": "library",
"autoload": {
"psr-4": {
"XdgBaseDir\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "implementation of xdg base directory specification for php",
"support": {
"issues": "https://github.com/dnoegel/php-xdg-base-dir/issues",
"source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1"
},
"time": "2019-12-04T15:06:13+00:00"
},
{
"name": "doctrine/instantiator",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9",
"ext-pdo": "*",
"ext-phar": "*",
"phpbench/phpbench": "^0.16 || ^1",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-phpunit": "^1",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"vimeo/psalm": "^4.22"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "https://ocramius.github.io/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://www.doctrine-project.org/projects/instantiator.html",
"keywords": [
"constructor",
"instantiate"
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/1.4.1"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
"type": "tidelift"
}
],
"time": "2022-03-03T08:28:38+00:00"
},
{
"name": "felixfbecker/advanced-json-rpc",
"version": "v3.2.1",
"source": {
"type": "git",
"url": "https://github.com/felixfbecker/php-advanced-json-rpc.git",
"reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447",
"reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447",
"shasum": ""
},
"require": {
"netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0",
"php": "^7.1 || ^8.0",
"phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0"
},
"require-dev": {
"phpunit/phpunit": "^7.0 || ^8.0"
},
"type": "library",
"autoload": {
"psr-4": {
"AdvancedJsonRpc\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"ISC"
],
"authors": [
{
"name": "Felix Becker",
"email": "felix.b@outlook.com"
}
],
"description": "A more advanced JSONRPC implementation",
"support": {
"issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues",
"source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1"
},
"time": "2021-06-11T22:34:44+00:00"
},
{
"name": "felixfbecker/language-server-protocol",
"version": "v1.5.2",
"source": {
"type": "git",
"url": "https://github.com/felixfbecker/php-language-server-protocol.git",
"reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842",
"reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"phpstan/phpstan": "*",
"squizlabs/php_codesniffer": "^3.1",
"vimeo/psalm": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"LanguageServerProtocol\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"ISC"
],
"authors": [
{
"name": "Felix Becker",
"email": "felix.b@outlook.com"
}
],
"description": "PHP classes for the Language Server Protocol",
"keywords": [
"language",
"microsoft",
"php",
"server"
],
"support": {
"issues": "https://github.com/felixfbecker/php-language-server-protocol/issues",
"source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2"
},
"time": "2022-03-02T22:36:06+00:00"
},
{
"name": "laminas/laminas-coding-standard",
"version": "2.4.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-coding-standard.git",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7",
"php": "^7.4 || ^8.0",
"slevomat/coding-standard": "^7.0",
"squizlabs/php_codesniffer": "^3.6",
"webimpress/coding-standard": "^1.2"
},
"conflict": {
"phpstan/phpdoc-parser": ">=1.6.0"
},
"type": "phpcodesniffer-standard",
"autoload": {
"psr-4": {
"LaminasCodingStandard\\": "src/LaminasCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Laminas Coding Standard",
"homepage": "https://laminas.dev",
"keywords": [
"Coding Standard",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-coding-standard/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-coding-standard/issues",
"rss": "https://github.com/laminas/laminas-coding-standard/releases.atom",
"source": "https://github.com/laminas/laminas-coding-standard"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-08-24T17:45:47+00:00"
},
{
"name": "laminas/laminas-config",
"version": "3.8.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-config.git",
"reference": "46baad58d0b12cf98539e04334eff40a1fdfb9a0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-config/zipball/46baad58d0b12cf98539e04334eff40a1fdfb9a0",
"reference": "46baad58d0b12cf98539e04334eff40a1fdfb9a0",
"shasum": ""
},
"require": {
"ext-json": "*",
"laminas/laminas-stdlib": "^3.6",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"psr/container": "^1.0"
},
"conflict": {
"container-interop/container-interop": "<1.2.0",
"zendframework/zend-config": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"laminas/laminas-filter": "~2.23.0",
"laminas/laminas-i18n": "~2.19.0",
"laminas/laminas-servicemanager": "~3.19.0",
"phpunit/phpunit": "~9.5.25"
},
"suggest": {
"laminas/laminas-filter": "^2.7.2; install if you want to use the Filter processor",
"laminas/laminas-i18n": "^2.7.4; install if you want to use the Translator processor",
"laminas/laminas-servicemanager": "^2.7.8 || ^3.3; if you need an extensible plugin manager for use with the Config Factory"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Config\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "provides a nested object property based user interface for accessing this configuration data within application code",
"homepage": "https://laminas.dev",
"keywords": [
"config",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-config/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-config/issues",
"rss": "https://github.com/laminas/laminas-config/releases.atom",
"source": "https://github.com/laminas/laminas-config"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-16T14:21:22+00:00"
},
{
"name": "laminas/laminas-eventmanager",
"version": "3.6.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-eventmanager.git",
"reference": "3f1afbad86cd34a431fdc069f265cfe6f8fc8308"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-eventmanager/zipball/3f1afbad86cd34a431fdc069f265cfe6f8fc8308",
"reference": "3f1afbad86cd34a431fdc069f265cfe6f8fc8308",
"shasum": ""
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"container-interop/container-interop": "<1.2",
"zendframework/zend-eventmanager": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"laminas/laminas-stdlib": "^3.15",
"phpbench/phpbench": "^1.2.6",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"psr/container": "^1.1.2 || ^2.0.2",
"vimeo/psalm": "^4.28"
},
"suggest": {
"laminas/laminas-stdlib": "^2.7.3 || ^3.0, to use the FilterChain feature",
"psr/container": "^1.1.2 || ^2.0.2, to use the lazy listeners feature"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\EventManager\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Trigger and listen to events within a PHP application",
"homepage": "https://laminas.dev",
"keywords": [
"event",
"eventmanager",
"events",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-eventmanager/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-eventmanager/issues",
"rss": "https://github.com/laminas/laminas-eventmanager/releases.atom",
"source": "https://github.com/laminas/laminas-eventmanager"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-11T12:46:13+00:00"
},
{
"name": "laminas/laminas-stdlib",
"version": "3.15.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-stdlib.git",
"reference": "63b66bd4b696f024f42616b9d95cdb10e5109c27"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/63b66bd4b696f024f42616b9d95cdb10e5109c27",
"reference": "63b66bd4b696f024f42616b9d95cdb10e5109c27",
"shasum": ""
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-stdlib": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "^2.4.0",
"phpbench/phpbench": "^1.2.6",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.28"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Stdlib\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "SPL extensions, array utilities, error handlers, and more",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"stdlib"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-stdlib/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-stdlib/issues",
"rss": "https://github.com/laminas/laminas-stdlib/releases.atom",
"source": "https://github.com/laminas/laminas-stdlib"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-10T19:10:24+00:00"
},
{
"name": "myclabs/deep-copy",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"conflict": {
"doctrine/collections": "<1.6.8",
"doctrine/common": "<2.13.3 || >=3,<3.2.2"
},
"require-dev": {
"doctrine/collections": "^1.6.8",
"doctrine/common": "^2.13.3 || ^3.2.2",
"phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
},
"type": "library",
"autoload": {
"files": [
"src/DeepCopy/deep_copy.php"
],
"psr-4": {
"DeepCopy\\": "src/DeepCopy/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Create deep copies (clones) of your objects",
"keywords": [
"clone",
"copy",
"duplicate",
"object",
"object graph"
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
},
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
"type": "tidelift"
}
],
"time": "2022-03-03T13:19:32+00:00"
},
{
"name": "netresearch/jsonmapper",
"version": "v4.0.0",
"source": {
"type": "git",
"url": "https://github.com/cweiske/jsonmapper.git",
"reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
"reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-pcre": "*",
"ext-reflection": "*",
"ext-spl": "*",
"php": ">=7.1"
},
"require-dev": {
"phpunit/phpunit": "~7.5 || ~8.0 || ~9.0",
"squizlabs/php_codesniffer": "~3.5"
},
"type": "library",
"autoload": {
"psr-0": {
"JsonMapper": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"OSL-3.0"
],
"authors": [
{
"name": "Christian Weiske",
"email": "cweiske@cweiske.de",
"homepage": "http://github.com/cweiske/jsonmapper/",
"role": "Developer"
}
],
"description": "Map nested JSON structures onto PHP classes",
"support": {
"email": "cweiske@cweiske.de",
"issues": "https://github.com/cweiske/jsonmapper/issues",
"source": "https://github.com/cweiske/jsonmapper/tree/v4.0.0"
},
"time": "2020-12-01T19:48:11+00:00"
},
{
"name": "nikic/php-parser",
"version": "v4.15.1",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=7.0"
},
"require-dev": {
"ircmaxell/php-yacc": "^0.0.7",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
},
"bin": [
"bin/php-parse"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.9-dev"
}
},
"autoload": {
"psr-4": {
"PhpParser\\": "lib/PhpParser"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov"
}
],
"description": "A PHP parser written in PHP",
"keywords": [
"parser",
"php"
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1"
},
"time": "2022-09-04T07:30:47+00:00"
},
{
"name": "openlss/lib-array2xml",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/nullivex/lib-array2xml.git",
"reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90",
"reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"type": "library",
"autoload": {
"psr-0": {
"LSS": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Bryan Tong",
"email": "bryan@nullivex.com",
"homepage": "https://www.nullivex.com"
},
{
"name": "Tony Butler",
"email": "spudz76@gmail.com",
"homepage": "https://www.nullivex.com"
}
],
"description": "Array2XML conversion library credit to lalit.org",
"homepage": "https://www.nullivex.com",
"keywords": [
"array",
"array conversion",
"xml",
"xml conversion"
],
"support": {
"issues": "https://github.com/nullivex/lib-array2xml/issues",
"source": "https://github.com/nullivex/lib-array2xml/tree/master"
},
"time": "2019-03-29T20:06:56+00:00"
},
{
"name": "phar-io/manifest",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-phar": "*",
"ext-xmlwriter": "*",
"phar-io/version": "^3.0.1",
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
"support": {
"issues": "https://github.com/phar-io/manifest/issues",
"source": "https://github.com/phar-io/manifest/tree/2.0.3"
},
"time": "2021-07-20T11:28:43+00:00"
},
{
"name": "phar-io/version",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/phar-io/version.git",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Library for handling version information and constraints",
"support": {
"issues": "https://github.com/phar-io/version/issues",
"source": "https://github.com/phar-io/version/tree/3.2.1"
},
"time": "2022-02-21T01:04:05+00:00"
},
{
"name": "php-mock/php-mock",
"version": "2.3.1",
"source": {
"type": "git",
"url": "https://github.com/php-mock/php-mock.git",
"reference": "9a55bd8ba40e6da2e97a866121d2c69dedd4952b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-mock/php-mock/zipball/9a55bd8ba40e6da2e97a866121d2c69dedd4952b",
"reference": "9a55bd8ba40e6da2e97a866121d2c69dedd4952b",
"shasum": ""
},
"require": {
"php": "^5.6 || ^7.0 || ^8.0",
"phpunit/php-text-template": "^1 || ^2"
},
"replace": {
"malkusch/php-mock": "*"
},
"require-dev": {
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.0 || ^9.0",
"squizlabs/php_codesniffer": "^3.5"
},
"suggest": {
"php-mock/php-mock-phpunit": "Allows integration into PHPUnit testcase with the trait PHPMock."
},
"type": "library",
"autoload": {
"files": [
"autoload.php"
],
"psr-4": {
"phpmock\\": [
"classes/",
"tests/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"WTFPL"
],
"authors": [
{
"name": "Markus Malkusch",
"email": "markus@malkusch.de",
"homepage": "http://markus.malkusch.de",
"role": "Developer"
}
],
"description": "PHP-Mock can mock built-in PHP functions (e.g. time()). PHP-Mock relies on PHP's namespace fallback policy. No further extension is needed.",
"homepage": "https://github.com/php-mock/php-mock",
"keywords": [
"BDD",
"TDD",
"function",
"mock",
"stub",
"test",
"test double"
],
"support": {
"issues": "https://github.com/php-mock/php-mock/issues",
"source": "https://github.com/php-mock/php-mock/tree/2.3.1"
},
"funding": [
{
"url": "https://github.com/michalbundyra",
"type": "github"
}
],
"time": "2022-02-07T18:57:52+00:00"
},
{
"name": "php-mock/php-mock-integration",
"version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-mock/php-mock-integration.git",
"reference": "003d585841e435958a02e9b986953907b8b7609b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-mock/php-mock-integration/zipball/003d585841e435958a02e9b986953907b8b7609b",
"reference": "003d585841e435958a02e9b986953907b8b7609b",
"shasum": ""
},
"require": {
"php": ">=5.6",
"php-mock/php-mock": "^2.2",
"phpunit/php-text-template": "^1 || ^2"
},
"require-dev": {
"phpunit/phpunit": "^5.7.27 || ^6 || ^7 || ^8 || ^9"
},
"type": "library",
"autoload": {
"psr-4": {
"phpmock\\integration\\": "classes/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"WTFPL"
],
"authors": [
{
"name": "Markus Malkusch",
"email": "markus@malkusch.de",
"homepage": "http://markus.malkusch.de",
"role": "Developer"
}
],
"description": "Integration package for PHP-Mock",
"homepage": "https://github.com/php-mock/php-mock-integration",
"keywords": [
"BDD",
"TDD",
"function",
"mock",
"stub",
"test",
"test double"
],
"support": {
"issues": "https://github.com/php-mock/php-mock-integration/issues",
"source": "https://github.com/php-mock/php-mock-integration/tree/2.1.0"
},
"time": "2020-02-08T14:40:25+00:00"
},
{
"name": "php-mock/php-mock-phpunit",
"version": "2.6.1",
"source": {
"type": "git",
"url": "https://github.com/php-mock/php-mock-phpunit.git",
"reference": "b9ba2db21e7e1c7deba98bc86dcfc6425fb4647d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-mock/php-mock-phpunit/zipball/b9ba2db21e7e1c7deba98bc86dcfc6425fb4647d",
"reference": "b9ba2db21e7e1c7deba98bc86dcfc6425fb4647d",
"shasum": ""
},
"require": {
"php": ">=7",
"php-mock/php-mock-integration": "^2.1",
"phpunit/phpunit": "^6 || ^7 || ^8 || ^9"
},
"require-dev": {
"phpspec/prophecy": "^1.10.3"
},
"type": "library",
"autoload": {
"files": [
"autoload.php"
],
"psr-4": {
"phpmock\\phpunit\\": "classes/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"WTFPL"
],
"authors": [
{
"name": "Markus Malkusch",
"email": "markus@malkusch.de",
"homepage": "http://markus.malkusch.de",
"role": "Developer"
}
],
"description": "Mock built-in PHP functions (e.g. time()) with PHPUnit. This package relies on PHP's namespace fallback policy. No further extension is needed.",
"homepage": "https://github.com/php-mock/php-mock-phpunit",
"keywords": [
"BDD",
"TDD",
"function",
"mock",
"phpunit",
"stub",
"test",
"test double"
],
"support": {
"issues": "https://github.com/php-mock/php-mock-phpunit/issues",
"source": "https://github.com/php-mock/php-mock-phpunit/tree/2.6.1"
},
"funding": [
{
"url": "https://github.com/michalbundyra",
"type": "github"
}
],
"time": "2022-09-07T20:40:07+00:00"
},
{
"name": "phpdocumentor/reflection-common",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-2.x": "2.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jaap van Otterdijk",
"email": "opensource@ijaap.nl"
}
],
"description": "Common reflection classes used by phpdocumentor to reflect the code structure",
"homepage": "http://www.phpdoc.org",
"keywords": [
"FQSEN",
"phpDocumentor",
"phpdoc",
"reflection",
"static analysis"
],
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
"source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x"
},
"time": "2020-06-27T09:03:43+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "5.3.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "622548b623e81ca6d78b721c5e029f4ce664f170"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170",
"reference": "622548b623e81ca6d78b721c5e029f4ce664f170",
"shasum": ""
},
"require": {
"ext-filter": "*",
"php": "^7.2 || ^8.0",
"phpdocumentor/reflection-common": "^2.2",
"phpdocumentor/type-resolver": "^1.3",
"webmozart/assert": "^1.9.1"
},
"require-dev": {
"mockery/mockery": "~1.3.2",
"psalm/phar": "^4.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
},
{
"name": "Jaap van Otterdijk",
"email": "account@ijaap.nl"
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0"
},
"time": "2021-10-19T17:43:47+00:00"
},
{
"name": "phpdocumentor/type-resolver",
"version": "1.6.2",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/48f445a408c131e38cab1c235aa6d2bb7a0bb20d",
"reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0",
"phpdocumentor/reflection-common": "^2.0"
},
"require-dev": {
"ext-tokenizer": "*",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpunit/phpunit": "^9.5",
"rector/rector": "^0.13.9",
"vimeo/psalm": "^4.25"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-1.x": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
}
],
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"support": {
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.2"
},
"time": "2022-10-14T12:47:21+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "981cc368a216c988e862a75e526b6076987d1b50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/981cc368a216c988e862a75e526b6076987d1b50",
"reference": "981cc368a216c988e862a75e526b6076987d1b50",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.5.1"
},
"time": "2022-05-05T11:32:40+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.17",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
"nikic/php-parser": "^4.14",
"php": ">=7.3",
"phpunit/php-file-iterator": "^3.0.3",
"phpunit/php-text-template": "^2.0.2",
"sebastian/code-unit-reverse-lookup": "^2.0.2",
"sebastian/complexity": "^2.0",
"sebastian/environment": "^5.1.2",
"sebastian/lines-of-code": "^1.0.3",
"sebastian/version": "^3.0.1",
"theseer/tokenizer": "^1.2.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcov": "*",
"ext-xdebug": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-08-30T12:24:04+00:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "3.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2021-12-02T12:48:52+00:00"
},
{
"name": "phpunit/php-invoker",
"version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-invoker.git",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"ext-pcntl": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcntl": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Invoke callables with a timeout",
"homepage": "https://github.com/sebastianbergmann/php-invoker/",
"keywords": [
"process"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-invoker/issues",
"source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:58:55+00:00"
},
{
"name": "phpunit/php-text-template",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
"source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T05:33:50+00:00"
},
{
"name": "phpunit/php-timer",
"version": "5.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-timer/issues",
"source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:16:10+00:00"
},
{
"name": "phpunit/phpunit",
"version": "9.5.25",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
"reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.3.1",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
"myclabs/deep-copy": "^1.10.1",
"phar-io/manifest": "^2.0.3",
"phar-io/version": "^3.0.2",
"php": ">=7.3",
"phpunit/php-code-coverage": "^9.2.13",
"phpunit/php-file-iterator": "^3.0.5",
"phpunit/php-invoker": "^3.1.1",
"phpunit/php-text-template": "^2.0.3",
"phpunit/php-timer": "^5.0.2",
"sebastian/cli-parser": "^1.0.1",
"sebastian/code-unit": "^1.0.6",
"sebastian/comparator": "^4.0.8",
"sebastian/diff": "^4.0.3",
"sebastian/environment": "^5.1.3",
"sebastian/exporter": "^4.0.5",
"sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3",
"sebastian/type": "^3.2",
"sebastian/version": "^3.0.2"
},
"suggest": {
"ext-soap": "*",
"ext-xdebug": "*"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.5-dev"
}
},
"autoload": {
"files": [
"src/Framework/Assert/Functions.php"
],
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.25"
},
"funding": [
{
"url": "https://phpunit.de/sponsors.html",
"type": "custom"
},
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
"type": "tidelift"
}
],
"time": "2022-09-25T03:44:45+00:00"
},
{
"name": "psalm/plugin-phpunit",
"version": "0.17.0",
"source": {
"type": "git",
"url": "https://github.com/psalm/psalm-plugin-phpunit.git",
"reference": "45951541beef07e93e3ad197daf01da88e85c31d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/psalm/psalm-plugin-phpunit/zipball/45951541beef07e93e3ad197daf01da88e85c31d",
"reference": "45951541beef07e93e3ad197daf01da88e85c31d",
"shasum": ""
},
"require": {
"composer/package-versions-deprecated": "^1.10",
"composer/semver": "^1.4 || ^2.0 || ^3.0",
"ext-simplexml": "*",
"php": "^7.1 || ^8.0",
"vimeo/psalm": "dev-master || dev-4.x || ^4.5"
},
"conflict": {
"phpunit/phpunit": "<7.5"
},
"require-dev": {
"codeception/codeception": "^4.0.3",
"php": "^7.3 || ^8.0",
"phpunit/phpunit": "^7.5 || ^8.0 || ^9.0",
"squizlabs/php_codesniffer": "^3.3.1",
"weirdan/codeception-psalm-module": "^0.11.0",
"weirdan/prophecy-shim": "^1.0 || ^2.0"
},
"type": "psalm-plugin",
"extra": {
"psalm": {
"pluginClass": "Psalm\\PhpUnitPlugin\\Plugin"
}
},
"autoload": {
"psr-4": {
"Psalm\\PhpUnitPlugin\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Matt Brown",
"email": "github@muglug.com"
}
],
"description": "Psalm plugin for PHPUnit",
"support": {
"issues": "https://github.com/psalm/psalm-plugin-phpunit/issues",
"source": "https://github.com/psalm/psalm-plugin-phpunit/tree/0.17.0"
},
"time": "2022-06-14T17:05:57+00:00"
},
{
"name": "psr/container",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
"shasum": ""
},
"require": {
"php": ">=7.4.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
"homepage": "https://github.com/php-fig/container",
"keywords": [
"PSR-11",
"container",
"container-interface",
"container-interop",
"psr"
],
"support": {
"issues": "https://github.com/php-fig/container/issues",
"source": "https://github.com/php-fig/container/tree/1.1.2"
},
"time": "2021-11-05T16:50:12+00:00"
},
{
"name": "psr/log",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"support": {
"source": "https://github.com/php-fig/log/tree/3.0.0"
},
"time": "2021-07-14T16:46:02+00:00"
},
{
"name": "sebastian/cli-parser",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for parsing CLI options",
"homepage": "https://github.com/sebastianbergmann/cli-parser",
"support": {
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
"source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:08:49+00:00"
},
{
"name": "sebastian/code-unit",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit.git",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the PHP code units",
"homepage": "https://github.com/sebastianbergmann/code-unit",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit/issues",
"source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:08:54+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
"source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:30:19+00:00"
},
{
"name": "sebastian/comparator",
"version": "4.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/diff": "^4.0",
"sebastian/exporter": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "https://github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
"source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T12:41:17+00:00"
},
{
"name": "sebastian/complexity",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.7",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for calculating the complexity of PHP code units",
"homepage": "https://github.com/sebastianbergmann/complexity",
"support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues",
"source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T15:52:27+00:00"
},
{
"name": "sebastian/diff",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3",
"symfony/process": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
}
],
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
"diff",
"udiff",
"unidiff",
"unified diff"
],
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:10:38+00:00"
},
{
"name": "sebastian/environment",
"version": "5.1.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-posix": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"support": {
"issues": "https://github.com/sebastianbergmann/environment/issues",
"source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-04-03T09:37:03+00:00"
},
{
"name": "sebastian/exporter",
"version": "4.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-mbstring": "*",
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "https://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T06:03:37+00:00"
},
{
"name": "sebastian/global-state",
"version": "5.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-dom": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-uopz": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-02-14T08:28:10+00:00"
},
{
"name": "sebastian/lines-of-code",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.6",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for counting the lines of code in PHP source code",
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
"support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-11-28T06:42:11+00:00"
},
{
"name": "sebastian/object-enumerator",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
"source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:12:34+00:00"
},
{
"name": "sebastian/object-reflector",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Allows reflection of object attributes, including inherited and non-public ones",
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-reflector/issues",
"source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:14:26+00:00"
},
{
"name": "sebastian/recursion-context",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
"source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:17:30+00:00"
},
{
"name": "sebastian/resource-operations",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"support": {
"issues": "https://github.com/sebastianbergmann/resource-operations/issues",
"source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:45:17+00:00"
},
{
"name": "sebastian/type",
"version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the types of the PHP type system",
"homepage": "https://github.com/sebastianbergmann/type",
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
"source": "https://github.com/sebastianbergmann/type/tree/3.2.0"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-12T14:47:03+00:00"
},
{
"name": "sebastian/version",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "c6c1022351a901512170118436c764e473f6de8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
"reference": "c6c1022351a901512170118436c764e473f6de8c",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"support": {
"issues": "https://github.com/sebastianbergmann/version/issues",
"source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:39:44+00:00"
},
{
"name": "slevomat/coding-standard",
"version": "7.2.1",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
"php": "^7.2 || ^8.0",
"phpstan/phpdoc-parser": "^1.5.1",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phing/phing": "2.17.3",
"php-parallel-lint/php-parallel-lint": "1.3.2",
"phpstan/phpstan": "1.4.10|1.7.1",
"phpstan/phpstan-deprecation-rules": "1.0.0",
"phpstan/phpstan-phpunit": "1.0.0|1.1.1",
"phpstan/phpstan-strict-rules": "1.2.3",
"phpunit/phpunit": "7.5.20|8.5.21|9.5.20"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "7.x-dev"
}
},
"autoload": {
"psr-4": {
"SlevomatCodingStandard\\": "SlevomatCodingStandard"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
"source": "https://github.com/slevomat/coding-standard/tree/7.2.1"
},
"funding": [
{
"url": "https://github.com/kukulich",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
"type": "tidelift"
}
],
"time": "2022-05-25T10:58:12+00:00"
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.7.1",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"bin/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2022-06-18T07:21:10+00:00"
},
{
"name": "symfony/console",
"version": "v6.0.14",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "1f89cab8d52c84424f798495b3f10342a7b1a070"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/1f89cab8d52c84424f798495b3f10342a7b1a070",
"reference": "1f89cab8d52c84424f798495b3f10342a7b1a070",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^1.1|^2|^3",
"symfony/string": "^5.4|^6.0"
},
"conflict": {
"symfony/dependency-injection": "<5.4",
"symfony/dotenv": "<5.4",
"symfony/event-dispatcher": "<5.4",
"symfony/lock": "<5.4",
"symfony/process": "<5.4"
},
"provide": {
"psr/log-implementation": "1.0|2.0|3.0"
},
"require-dev": {
"psr/log": "^1|^2|^3",
"symfony/config": "^5.4|^6.0",
"symfony/dependency-injection": "^5.4|^6.0",
"symfony/event-dispatcher": "^5.4|^6.0",
"symfony/lock": "^5.4|^6.0",
"symfony/process": "^5.4|^6.0",
"symfony/var-dumper": "^5.4|^6.0"
},
"suggest": {
"psr/log": "For using the console logger",
"symfony/event-dispatcher": "",
"symfony/lock": "",
"symfony/process": ""
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Eases the creation of beautiful and testable command line interfaces",
"homepage": "https://symfony.com",
"keywords": [
"cli",
"command line",
"console",
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v6.0.14"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-10-07T08:02:12+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.0.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c",
"reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c",
"shasum": ""
},
"require": {
"php": ">=8.0.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.0-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-01-02T09:55:41+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-ctype": "*"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "433d05519ce6990bf3530fba6957499d327395c2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
"reference": "433d05519ce6990bf3530fba6957499d327395c2",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Grapheme\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's grapheme_* functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"grapheme",
"intl",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's Normalizer class and related functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"intl",
"normalizer",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-mbstring": "*"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php80\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ion Bazan",
"email": "ion.bazan@gmail.com"
},
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-10T07:21:04+00:00"
},
{
"name": "symfony/service-contracts",
"version": "v2.5.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
"reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1",
"symfony/deprecation-contracts": "^2.1|^3"
},
"conflict": {
"ext-psr": "<1.1|>=2"
},
"suggest": {
"symfony/service-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\Service\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to writing services",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v2.5.2"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-30T19:17:29+00:00"
},
{
"name": "symfony/string",
"version": "v6.0.14",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "3db7da820a6e4a584b714b3933c34c6a7db4d86c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/3db7da820a6e4a584b714b3933c34c6a7db4d86c",
"reference": "3db7da820a6e4a584b714b3933c34c6a7db4d86c",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
"symfony/translation-contracts": "<2.0"
},
"require-dev": {
"symfony/error-handler": "^5.4|^6.0",
"symfony/http-client": "^5.4|^6.0",
"symfony/translation-contracts": "^2.0|^3.0",
"symfony/var-exporter": "^5.4|^6.0"
},
"type": "library",
"autoload": {
"files": [
"Resources/functions.php"
],
"psr-4": {
"Symfony\\Component\\String\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
"homepage": "https://symfony.com",
"keywords": [
"grapheme",
"i18n",
"string",
"unicode",
"utf-8",
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v6.0.14"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-10-10T09:34:08+00:00"
},
{
"name": "theseer/tokenizer",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
}
],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/1.2.1"
},
"funding": [
{
"url": "https://github.com/theseer",
"type": "github"
}
],
"time": "2021-07-28T10:34:58+00:00"
},
{
"name": "vimeo/psalm",
"version": "4.29.0",
"source": {
"type": "git",
"url": "https://github.com/vimeo/psalm.git",
"reference": "7ec5ffbd5f68ae03782d7fd33fff0c45a69f95b3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/vimeo/psalm/zipball/7ec5ffbd5f68ae03782d7fd33fff0c45a69f95b3",
"reference": "7ec5ffbd5f68ae03782d7fd33fff0c45a69f95b3",
"shasum": ""
},
"require": {
"amphp/amp": "^2.4.2",
"amphp/byte-stream": "^1.5",
"composer/package-versions-deprecated": "^1.8.0",
"composer/semver": "^1.4 || ^2.0 || ^3.0",
"composer/xdebug-handler": "^1.1 || ^2.0 || ^3.0",
"dnoegel/php-xdg-base-dir": "^0.1.1",
"ext-ctype": "*",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-simplexml": "*",
"ext-tokenizer": "*",
"felixfbecker/advanced-json-rpc": "^3.0.3",
"felixfbecker/language-server-protocol": "^1.5",
"netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0",
"nikic/php-parser": "^4.13",
"openlss/lib-array2xml": "^1.0",
"php": "^7.1|^8",
"sebastian/diff": "^3.0 || ^4.0",
"symfony/console": "^3.4.17 || ^4.1.6 || ^5.0 || ^6.0",
"symfony/polyfill-php80": "^1.25",
"webmozart/path-util": "^2.3"
},
"provide": {
"psalm/psalm": "self.version"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.2",
"brianium/paratest": "^4.0||^6.0",
"ext-curl": "*",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpdocumentor/reflection-docblock": "^5",
"phpmyadmin/sql-parser": "5.1.0||dev-master",
"phpspec/prophecy": ">=1.9.0",
"phpstan/phpdoc-parser": "1.2.* || 1.6.4",
"phpunit/phpunit": "^9.0",
"psalm/plugin-phpunit": "^0.16",
"slevomat/coding-standard": "^7.0",
"squizlabs/php_codesniffer": "^3.5",
"symfony/process": "^4.3 || ^5.0 || ^6.0",
"weirdan/prophecy-shim": "^1.0 || ^2.0"
},
"suggest": {
"ext-curl": "In order to send data to shepherd",
"ext-igbinary": "^2.0.5 is required, used to serialize caching data"
},
"bin": [
"psalm",
"psalm-language-server",
"psalm-plugin",
"psalm-refactor",
"psalter"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.x-dev",
"dev-3.x": "3.x-dev",
"dev-2.x": "2.x-dev",
"dev-1.x": "1.x-dev"
}
},
"autoload": {
"files": [
"src/functions.php",
"src/spl_object_id.php"
],
"psr-4": {
"Psalm\\": "src/Psalm/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Matthew Brown"
}
],
"description": "A static analysis tool for finding errors in PHP applications",
"keywords": [
"code",
"inspection",
"php"
],
"support": {
"issues": "https://github.com/vimeo/psalm/issues",
"source": "https://github.com/vimeo/psalm/tree/4.29.0"
},
"time": "2022-10-11T17:09:17+00:00"
},
{
"name": "webimpress/coding-standard",
"version": "1.2.4",
"source": {
"type": "git",
"url": "https://github.com/webimpress/coding-standard.git",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webimpress/coding-standard/zipball/cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"shasum": ""
},
"require": {
"php": "^7.3 || ^8.0",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phpunit/phpunit": "^9.5.13"
},
"type": "phpcodesniffer-standard",
"extra": {
"dev-master": "1.2.x-dev",
"dev-develop": "1.3.x-dev"
},
"autoload": {
"psr-4": {
"WebimpressCodingStandard\\": "src/WebimpressCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-2-Clause"
],
"description": "Webimpress Coding Standard",
"keywords": [
"Coding Standard",
"PSR-2",
"phpcs",
"psr-12",
"webimpress"
],
"support": {
"issues": "https://github.com/webimpress/coding-standard/issues",
"source": "https://github.com/webimpress/coding-standard/tree/1.2.4"
},
"funding": [
{
"url": "https://github.com/michalbundyra",
"type": "github"
}
],
"time": "2022-02-15T19:52:12+00:00"
},
{
"name": "webmozart/assert",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/webmozarts/assert.git",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"php": "^7.2 || ^8.0"
},
"conflict": {
"phpstan/phpstan": "<0.12.20",
"vimeo/psalm": "<4.6.1 || 4.6.2"
},
"require-dev": {
"phpunit/phpunit": "^8.5.13"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.10-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\Assert\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Assertions to validate method input/output with nice error messages.",
"keywords": [
"assert",
"check",
"validate"
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.11.0"
},
"time": "2022-06-03T18:03:27+00:00"
},
{
"name": "webmozart/path-util",
"version": "2.3.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/path-util.git",
"reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
"reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"webmozart/assert": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.6",
"sebastian/version": "^1.0.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.3-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\PathUtil\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.",
"support": {
"issues": "https://github.com/webmozart/path-util/issues",
"source": "https://github.com/webmozart/path-util/tree/2.3.0"
},
"abandoned": "symfony/filesystem",
"time": "2015-12-17T08:42:14+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"ext-ldap": "*"
},
"platform-dev": [],
"platform-overrides": {
"php": "8.0.99"
},
"plugin-api-version": "2.2.0"
}
laminas-ldap/LICENSE.md 0000644 00000002732 15240152654 0010522 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of Laminas Foundation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
laminas-ldap/renovate.json 0000644 00000000205 15240152654 0011625 0 ustar 00 {
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"local>laminas/.github:renovate-config"
]
}
laminas-mail/src/Message.php 0000644 00000036751 15240152654 0012014 0 ustar 00 <?php
namespace Laminas\Mail;
use ArrayIterator;
use Laminas\Mail\Header\Bcc;
use Laminas\Mail\Header\Cc;
use Laminas\Mail\Header\ContentType;
use Laminas\Mail\Header\From;
use Laminas\Mail\Header\MimeVersion;
use Laminas\Mail\Header\ReplyTo;
use Laminas\Mail\Header\Sender;
use Laminas\Mail\Header\To;
use Laminas\Mime;
use Traversable;
use function array_shift;
use function count;
use function date;
use function gettype;
use function is_array;
use function is_object;
use function is_string;
use function method_exists;
use function sprintf;
class Message
{
/**
* Content of the message
*
* @var string|object|Mime\Message
*/
protected $body;
/** @var Headers */
protected $headers;
/**
* Message encoding
*
* Used to determine whether or not to encode headers; defaults to ASCII.
*
* @var string
*/
protected $encoding = 'ASCII';
/**
* Is the message valid?
*
* If we don't any From addresses, we're invalid, according to RFC2822.
*
* @return bool
*/
public function isValid()
{
$from = $this->getFrom();
if (! $from instanceof AddressList) {
return false;
}
return (bool) count($from);
}
/**
* Set the message encoding
*
* @param string $encoding
* @return Message
*/
public function setEncoding($encoding)
{
$this->encoding = $encoding;
$this->getHeaders()->setEncoding($encoding);
return $this;
}
/**
* Get the message encoding
*
* @return string
*/
public function getEncoding()
{
return $this->encoding;
}
/**
* Compose headers
*
* @return Message
*/
public function setHeaders(Headers $headers)
{
$this->headers = $headers;
$headers->setEncoding($this->getEncoding());
return $this;
}
/**
* Access headers collection
*
* Lazy-loads if not already attached.
*
* @return Headers
*/
public function getHeaders()
{
if (null === $this->headers) {
$this->setHeaders(new Headers());
$date = Header\Date::fromString('Date: ' . date('r'));
$this->headers->addHeader($date);
}
return $this->headers;
}
/**
* Set (overwrite) From addresses
*
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList
* @param string|null $name
* @return Message
*/
public function setFrom($emailOrAddressList, $name = null)
{
$this->clearHeaderByName('from');
return $this->addFrom($emailOrAddressList, $name);
}
/**
* Add a "From" address
*
* @param string|Address|array|AddressList|Traversable $emailOrAddressOrList
* @param string|null $name
* @return Message
*/
public function addFrom($emailOrAddressOrList, $name = null)
{
$addressList = $this->getFrom();
$this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__);
return $this;
}
/**
* Retrieve list of From senders
*
* @return AddressList
*/
public function getFrom()
{
return $this->getAddressListFromHeader('from', From::class);
}
/**
* Overwrite the address list in the To recipients
*
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList
* @param null|string $name
* @return Message
*/
public function setTo($emailOrAddressList, $name = null)
{
$this->clearHeaderByName('to');
return $this->addTo($emailOrAddressList, $name);
}
/**
* Add one or more addresses to the To recipients
*
* Appends to the list.
*
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressOrList
* @param null|string $name
* @return Message
*/
public function addTo($emailOrAddressOrList, $name = null)
{
$addressList = $this->getTo();
$this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__);
return $this;
}
/**
* Access the address list of the To header
*
* @return AddressList
*/
public function getTo()
{
return $this->getAddressListFromHeader('to', To::class);
}
/**
* Set (overwrite) CC addresses
*
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList
* @param string|null $name
* @return Message
*/
public function setCc($emailOrAddressList, $name = null)
{
$this->clearHeaderByName('cc');
return $this->addCc($emailOrAddressList, $name);
}
/**
* Add a "Cc" address
*
* @param string|Address|array|AddressList|Traversable $emailOrAddressOrList
* @param string|null $name
* @return Message
*/
public function addCc($emailOrAddressOrList, $name = null)
{
$addressList = $this->getCc();
$this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__);
return $this;
}
/**
* Retrieve list of CC recipients
*
* @return AddressList
*/
public function getCc()
{
return $this->getAddressListFromHeader('cc', Cc::class);
}
/**
* Set (overwrite) BCC addresses
*
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList
* @param string|null $name
* @return Message
*/
public function setBcc($emailOrAddressList, $name = null)
{
$this->clearHeaderByName('bcc');
return $this->addBcc($emailOrAddressList, $name);
}
/**
* Add a "Bcc" address
*
* @param string|Address|array|AddressList|Traversable $emailOrAddressOrList
* @param string|null $name
* @return Message
*/
public function addBcc($emailOrAddressOrList, $name = null)
{
$addressList = $this->getBcc();
$this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__);
return $this;
}
/**
* Retrieve list of BCC recipients
*
* @return AddressList
*/
public function getBcc()
{
return $this->getAddressListFromHeader('bcc', Bcc::class);
}
/**
* Overwrite the address list in the Reply-To recipients
*
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList
* @param null|string $name
* @return Message
*/
public function setReplyTo($emailOrAddressList, $name = null)
{
$this->clearHeaderByName('reply-to');
return $this->addReplyTo($emailOrAddressList, $name);
}
/**
* Add one or more addresses to the Reply-To recipients
*
* Appends to the list.
*
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressOrList
* @param null|string $name
* @return Message
*/
public function addReplyTo($emailOrAddressOrList, $name = null)
{
$addressList = $this->getReplyTo();
$this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__);
return $this;
}
/**
* Access the address list of the Reply-To header
*
* @return AddressList
*/
public function getReplyTo()
{
return $this->getAddressListFromHeader('reply-to', ReplyTo::class);
}
/**
* setSender
*
* @return Message
*/
public function setSender(mixed $emailOrAddress, mixed $name = null)
{
/** @var Sender $header */
$header = $this->getHeaderByName('sender', Sender::class);
$header->setAddress($emailOrAddress, $name);
return $this;
}
/**
* Retrieve the sender address, if any
*
* @return null|Address\AddressInterface
*/
public function getSender()
{
$headers = $this->getHeaders();
if (! $headers->has('sender')) {
return null;
}
/** @var Sender $header */
$header = $this->getHeaderByName('sender', Sender::class);
return $header->getAddress();
}
/**
* Set the message subject header value
*
* @param string $subject
* @return Message
*/
public function setSubject($subject)
{
$headers = $this->getHeaders();
if (! $headers->has('subject')) {
$header = new Header\Subject();
$headers->addHeader($header);
} else {
$header = $headers->get('subject');
}
$header->setSubject($subject);
$header->setEncoding($this->getEncoding());
return $this;
}
/**
* Get the message subject header value
*
* @return null|string
*/
public function getSubject()
{
$headers = $this->getHeaders();
if (! $headers->has('subject')) {
return;
}
$header = $headers->get('subject');
return $header->getFieldValue();
}
/**
* Set the message body
*
* @param null|string|\Laminas\Mime\Message|object $body
* @throws Exception\InvalidArgumentException
* @return Message
*/
public function setBody($body)
{
if (! is_string($body) && $body !== null) {
if (! is_object($body)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a string or object argument; received "%s"',
__METHOD__,
gettype($body)
));
}
if (! $body instanceof Mime\Message) {
if (! method_exists($body, '__toString')) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects object arguments of type %s or implementing __toString();'
. ' object of type "%s" received',
__METHOD__,
Mime\Message::class,
$body::class
));
}
}
}
$this->body = $body;
if (! $this->body instanceof Mime\Message) {
return $this;
}
// Get headers, and set Mime-Version header
$headers = $this->getHeaders();
$this->getHeaderByName('mime-version', MimeVersion::class);
// Multipart content headers
if ($this->body->isMultiPart()) {
$mime = $this->body->getMime();
/** @var ContentType $header */
$header = $this->getHeaderByName('content-type', ContentType::class);
$header->setType('multipart/mixed');
$header->addParameter('boundary', $mime->boundary());
return $this;
}
// MIME single part headers
$parts = $this->body->getParts();
if (! empty($parts)) {
$part = array_shift($parts);
$headers->addHeaders($part->getHeadersArray("\r\n"));
}
return $this;
}
/**
* Return the currently set message body
*
* @return object|string|Mime\Message
*/
public function getBody()
{
return $this->body;
}
/**
* Get the string-serialized message body text
*
* @return string
*/
public function getBodyText()
{
if ($this->body instanceof Mime\Message) {
return $this->body->generateMessage(Headers::EOL);
}
return (string) $this->body;
}
/**
* Retrieve a header by name
*
* If not found, instantiates one based on $headerClass.
*
* @param string $headerName
* @param string $headerClass
* @return Header\HeaderInterface|ArrayIterator header instance or collection of headers
*/
protected function getHeaderByName($headerName, $headerClass)
{
$headers = $this->getHeaders();
if ($headers->has($headerName)) {
$header = $headers->get($headerName);
} else {
$header = new $headerClass();
$headers->addHeader($header);
}
return $header;
}
/**
* Clear a header by name
*
* @param string $headerName
*/
protected function clearHeaderByName($headerName)
{
$this->getHeaders()->removeHeader($headerName);
}
/**
* Retrieve the AddressList from a named header
*
* Used with To, From, Cc, Bcc, and ReplyTo headers. If the header does not
* exist, instantiates it.
*
* @param string $headerName
* @param string $headerClass
* @throws Exception\DomainException
* @return AddressList
*/
protected function getAddressListFromHeader($headerName, $headerClass)
{
$header = $this->getHeaderByName($headerName, $headerClass);
if (! $header instanceof Header\AbstractAddressList) {
throw new Exception\DomainException(sprintf(
'Cannot grab address list from header of type "%s"; not an AbstractAddressList implementation',
$header::class
));
}
return $header->getAddressList();
}
/**
* Update an address list
*
* Proxied to this from addFrom, addTo, addCc, addBcc, and addReplyTo.
*
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressOrList
* @param null|string $name
* @param string $callingMethod
* @throws Exception\InvalidArgumentException
*/
protected function updateAddressList(AddressList $addressList, $emailOrAddressOrList, $name, $callingMethod)
{
if ($emailOrAddressOrList instanceof Traversable) {
foreach ($emailOrAddressOrList as $address) {
$addressList->add($address);
}
return;
}
if (is_array($emailOrAddressOrList)) {
$addressList->addMany($emailOrAddressOrList);
return;
}
if (! is_string($emailOrAddressOrList) && ! $emailOrAddressOrList instanceof Address\AddressInterface) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a string, AddressInterface, array, AddressList, or Traversable as its first argument;'
. ' received "%s"',
$callingMethod,
is_object($emailOrAddressOrList) ? $emailOrAddressOrList::class : gettype($emailOrAddressOrList)
));
}
if (is_string($emailOrAddressOrList) && $name === null) {
$addressList->addFromString($emailOrAddressOrList);
return;
}
$addressList->add($emailOrAddressOrList, $name);
}
/**
* Serialize to string
*
* @return string
*/
public function toString()
{
$headers = $this->getHeaders();
return $headers->toString()
. Headers::EOL
. $this->getBodyText();
}
/**
* Instantiate from raw message string
*
* @todo Restore body to Mime\Message
* @param string $rawMessage
* @return Message
*/
public static function fromString($rawMessage)
{
$message = new static();
/** @var Headers $headers */
$headers = null;
$content = null;
Mime\Decode::splitMessage($rawMessage, $headers, $content, Headers::EOL);
// if ($headers->has('mime-version')) {
// todo - restore body to mime\message
// }
$message->setHeaders($headers);
$message->setBody($content);
return $message;
}
}
laminas-mail/src/Protocol/Imap.php 0000644 00000065154 15240152655 0013117 0 ustar 00 <?php
namespace Laminas\Mail\Protocol;
use Laminas\Mail\Protocol\Exception\ExceptionInterface;
use function array_merge;
use function array_pop;
use function array_push;
use function array_search;
use function array_shift;
use function count;
use function current;
use function explode;
use function fclose;
use function fgets;
use function func_get_args;
use function func_num_args;
use function fwrite;
use function implode;
use function is_array;
use function is_numeric;
use function key;
use function next;
use function preg_match;
use function rtrim;
use function str_contains;
use function str_replace;
use function str_starts_with;
use function stream_socket_enable_crypto;
use function strlen;
use function strpos;
use function strtolower;
use function substr;
use function trim;
use const INF;
class Imap
{
use ProtocolTrait;
/**
* Default timeout in seconds for initiating session
*/
public const TIMEOUT_CONNECTION = 30;
/** @var null|resource */
protected $socket;
/**
* counter for request tag
*
* @var int
*/
protected $tagCount = 0;
/**
* Public constructor
*
* @param string $host hostname or IP address of IMAP server, if given connect() is called
* @param int|null $port port of IMAP server, null for default (143 or 993 for ssl)
* @param string|bool $ssl use ssl? 'SSL', 'TLS' or false
* @param bool $novalidatecert set to true to skip SSL certificate validation
* @throws ExceptionInterface
*/
public function __construct($host = '', $port = null, $ssl = false, $novalidatecert = false)
{
$this->setNoValidateCert($novalidatecert);
if ($host) {
$this->connect($host, $port, $ssl);
}
}
/**
* Public destructor
*/
public function __destruct()
{
$this->logout();
}
/**
* Open connection to IMAP server
*
* @param string $host hostname or IP address of IMAP server
* @param int|null $port of IMAP server, default is 143 (993 for ssl)
* @param string|bool $ssl use 'SSL', 'TLS' or false
* @throws Exception\RuntimeException
* @return void
*/
public function connect($host, $port = null, $ssl = false)
{
$transport = 'tcp';
$isTls = false;
if ($ssl) {
$ssl = strtolower($ssl);
}
switch ($ssl) {
case 'ssl':
$transport = 'ssl';
if (! $port) {
$port = 993;
}
break;
case 'tls':
$isTls = true;
// break intentionally omitted
default:
if (! $port) {
$port = 143;
}
}
$this->socket = $this->setupSocket($transport, $host, $port, self::TIMEOUT_CONNECTION);
if (! $this->assumedNextLine('* OK')) {
throw new Exception\RuntimeException('host doesn\'t allow connection');
}
if ($isTls) {
$result = $this->requestAndResponse('STARTTLS');
$result = $result && stream_socket_enable_crypto($this->socket, true, $this->getCryptoMethod());
if (! $result) {
throw new Exception\RuntimeException('cannot enable TLS');
}
}
}
/**
* get the next line from socket with error checking, but nothing else
*
* @throws Exception\RuntimeException
* @return string next line
*/
protected function nextLine()
{
$line = fgets($this->socket);
if ($line === false) {
throw new Exception\RuntimeException('cannot read - connection closed?');
}
return $line;
}
/**
* get next line and assume it starts with $start. some requests give a simple
* feedback so we can quickly check if we can go on.
*
* @param string $start the first bytes we assume to be in the next line
* @return bool line starts with $start
*/
protected function assumedNextLine($start)
{
$line = $this->nextLine();
return str_starts_with($line, $start);
}
/**
* get next line and split the tag. that's the normal case for a response line
*
* @param string $tag tag of line is returned by reference
* @return string next line
*/
protected function nextTaggedLine(&$tag)
{
$line = $this->nextLine();
// separate tag from line
[$tag, $line] = explode(' ', $line, 2);
return $line;
}
/**
* split a given line in tokens. a token is literal of any form or a list
*
* @param string $line line to decode
* @return array tokens, literals are returned as string, lists as array
*/
protected function decodeLine($line)
{
$tokens = [];
$stack = [];
/*
We start to decode the response here. The understood tokens are:
literal
"literal" or also "lit\\er\"al"
{bytes}<NL>literal
(literals*)
All tokens are returned in an array. Literals in braces (the last understood
token in the list) are returned as an array of tokens. I.e. the following response:
"foo" baz {3}<NL>bar ("f\\\"oo" bar)
would be returned as:
array('foo', 'baz', 'bar', array('f\\\"oo', 'bar'));
// TODO: add handling of '[' and ']' to parser for easier handling of response text
*/
// replace any trailing <NL> including spaces with a single space
$line = rtrim($line) . ' ';
while (($pos = strpos($line, ' ')) !== false) {
$token = substr($line, 0, $pos);
if (! strlen($token)) {
continue;
}
while ($token[0] == '(') {
array_push($stack, $tokens);
$tokens = [];
$token = substr($token, 1);
}
if ($token[0] == '"') {
if (preg_match('%^\(*"((.|\\\\|\\")*?)" *%', $line, $matches)) {
$tokens[] = $matches[1];
$line = substr($line, strlen($matches[0]));
continue;
}
}
if ($token[0] == '{') {
$endPos = strpos($token, '}');
$chars = substr($token, 1, $endPos - 1);
if (is_numeric($chars)) {
$token = '';
while (strlen($token) < $chars) {
$token .= $this->nextLine();
}
$line = '';
if (strlen($token) > $chars) {
$line = substr($token, $chars);
$token = substr($token, 0, $chars);
} else {
$line .= $this->nextLine();
}
$tokens[] = $token;
$line = trim($line) . ' ';
continue;
}
}
if ($stack && $token[strlen($token) - 1] == ')') {
// closing braces are not separated by spaces, so we need to count them
$braces = strlen($token);
$token = rtrim($token, ')');
// only count braces if more than one
$braces -= strlen($token) + 1;
// only add if token had more than just closing braces
if (rtrim($token) != '') {
$tokens[] = rtrim($token);
}
$token = $tokens;
$tokens = array_pop($stack);
// special handline if more than one closing brace
while ($braces-- > 0) {
$tokens[] = $token;
$token = $tokens;
$tokens = array_pop($stack);
}
}
$tokens[] = $token;
$line = substr($line, $pos + 1);
}
// maybe the server forgot to send some closing braces
while ($stack) {
$child = $tokens;
$tokens = array_pop($stack);
$tokens[] = $child;
}
return $tokens;
}
/**
* read a response "line" (could also be more than one real line if response has {..}<NL>)
* and do a simple decode
*
* @param array|string $tokens decoded tokens are returned by reference, if $dontParse
* is true the unparsed line is returned here
* @param string $wantedTag check for this tag for response code. Default '*' is
* continuation tag.
* @param bool $dontParse if true only the unparsed line is returned $tokens
* @return bool if returned tag matches wanted tag
*/
public function readLine(&$tokens = [], $wantedTag = '*', $dontParse = false)
{
$tag = null; // define $tag variable before first use
$line = $this->nextTaggedLine($tag); // get next tag
if (! $dontParse) {
$tokens = $this->decodeLine($line);
} else {
$tokens = $line;
}
// if tag is wanted tag we might be at the end of a multiline response
return $tag == $wantedTag;
}
/**
* read all lines of response until given tag is found (last line of response)
*
* @param string $tag the tag of your request
* @param bool $dontParse if true every line is returned unparsed instead of
* the decoded tokens
* @return null|bool|array tokens if success, false if error, null if bad request
*/
public function readResponse($tag, $dontParse = false)
{
$lines = [];
$tokens = null; // define $tokens variable before first use
while (! $this->readLine($tokens, $tag, $dontParse)) {
$lines[] = $tokens;
}
if ($dontParse) {
// last to chars are still needed for response code
$tokens = [substr($tokens, 0, 2)];
}
// last line has response code
if ($tokens[0] == 'OK') {
return $lines ?: true;
} elseif ($tokens[0] == 'NO') {
return false;
}
}
/**
* send a request
*
* @param string $command your request command
* @param array $tokens additional parameters to command, use escapeString() to prepare
* @param string $tag provide a tag otherwise an autogenerated is returned
* @throws Exception\RuntimeException
*/
public function sendRequest($command, $tokens = [], &$tag = null)
{
if (! $tag) {
++$this->tagCount;
$tag = 'TAG' . $this->tagCount;
}
$line = $tag . ' ' . $command;
foreach ($tokens as $token) {
if (is_array($token)) {
if (fwrite($this->socket, $line . ' ' . $token[0] . "\r\n") === false) {
throw new Exception\RuntimeException('cannot write - connection closed?');
}
if (! $this->assumedNextLine('+ ')) {
throw new Exception\RuntimeException('cannot send literal string');
}
$line = $token[1];
} else {
$line .= ' ' . $token;
}
}
if (fwrite($this->socket, $line . "\r\n") === false) {
throw new Exception\RuntimeException('cannot write - connection closed?');
}
}
/**
* send a request and get response at once
*
* @param string $command command as in sendRequest()
* @param array $tokens parameters as in sendRequest()
* @param bool $dontParse if true unparsed lines are returned instead of tokens
* @return mixed response as in readResponse()
*/
public function requestAndResponse($command, $tokens = [], $dontParse = false)
{
$tag = null; // define $tag variable before first use
$this->sendRequest($command, $tokens, $tag);
return $this->readResponse($tag, $dontParse);
}
/**
* escape one or more literals i.e. for sendRequest
*
* @param string|array $string the literal/-s
* @return string|array escape literals, literals with newline ar returned
* as array('{size}', 'string');
*/
public function escapeString($string)
{
if (func_num_args() < 2) {
if (str_contains($string, "\n")) {
return ['{' . strlen($string) . '}', $string];
}
return '"' . str_replace(['\\', '"'], ['\\\\', '\\"'], $string) . '"';
}
$result = [];
foreach (func_get_args() as $string) {
$result[] = $this->escapeString($string);
}
return $result;
}
/**
* escape a list with literals or lists
*
* @param array $list list with literals or lists as PHP array
* @return string escaped list for imap
*/
public function escapeList($list)
{
$result = [];
foreach ($list as $v) {
if (! is_array($v)) {
$result[] = $v;
continue;
}
$result[] = $this->escapeList($v);
}
return '(' . implode(' ', $result) . ')';
}
/**
* Login to IMAP server.
*
* @param string $user username
* @param string $password password
* @return bool success
*/
public function login($user, $password)
{
return $this->requestAndResponse('LOGIN', $this->escapeString($user, $password), true);
}
/**
* logout of imap server
*
* @return bool success
*/
public function logout()
{
$result = false;
if ($this->socket) {
try {
$result = $this->requestAndResponse('LOGOUT', [], true);
} catch (Exception\ExceptionInterface) {
// ignoring exception
}
fclose($this->socket);
$this->socket = null;
}
return $result;
}
/**
* Get capabilities from IMAP server
*
* @return array list of capabilities
* @throws ExceptionInterface
*/
public function capability()
{
$response = $this->requestAndResponse('CAPABILITY');
if (! $response) {
return [];
}
$capabilities = [];
foreach ($response as $line) {
$capabilities = array_merge($capabilities, $line);
}
return $capabilities;
}
/**
* Examine and select have the same response. The common code for both
* is in this method
*
* @param string $command can be 'EXAMINE' or 'SELECT' and this is used as command
* @param string $box which folder to change to or examine
* @return bool|array false if error, array with returned information
* otherwise (flags, exists, recent, uidvalidity)
* @throws ExceptionInterface
*/
public function examineOrSelect($command = 'EXAMINE', $box = 'INBOX')
{
$tag = null; // define $tag variable before first use
$this->sendRequest($command, [$this->escapeString($box)], $tag);
$result = [];
$tokens = null; // define $tokens variable before first use
while (! $this->readLine($tokens, $tag)) {
if ($tokens[0] == 'FLAGS') {
array_shift($tokens);
$result['flags'] = $tokens;
continue;
}
switch ($tokens[1]) {
case 'EXISTS':
case 'RECENT':
$result[strtolower($tokens[1])] = $tokens[0];
break;
case '[UIDVALIDITY':
$result['uidvalidity'] = (int) $tokens[2];
break;
default:
// ignore
}
}
if ($tokens[0] != 'OK') {
return false;
}
return $result;
}
/**
* change folder
*
* @param string $box change to this folder
* @return bool|array see examineOrselect()
* @throws ExceptionInterface
*/
public function select($box = 'INBOX')
{
return $this->examineOrSelect('SELECT', $box);
}
/**
* examine folder
*
* @param string $box examine this folder
* @return bool|array see examineOrselect()
* @throws ExceptionInterface
*/
public function examine($box = 'INBOX')
{
return $this->examineOrSelect('EXAMINE', $box);
}
/**
* fetch one or more items of one or more messages
*
* @param string|array $items items to fetch from message(s) as string (if only one item)
* or array of strings
* @param int|array $from message for items or start message if $to !== null
* @param int|null $to if null only one message ($from) is fetched, else it's the
* last message, INF means last message available
* @param bool $uid set to true if passing a unique id
* @throws Exception\RuntimeException
* @return string|array if only one item of one message is fetched it's returned as string
* if items of one message are fetched it's returned as (name => value)
* if one items of messages are fetched it's returned as (msgno => value)
* if items of messages are fetched it's returned as (msgno => (name => value))
*/
public function fetch($items, $from, $to = null, $uid = false)
{
if (is_array($from)) {
$set = implode(',', $from);
} elseif ($to === null) {
$set = (int) $from;
} elseif ($to === INF) {
$set = (int) $from . ':*';
} else {
$set = (int) $from . ':' . (int) $to;
}
$items = (array) $items;
$itemList = $this->escapeList($items);
$tag = null; // define $tag variable before first use
$this->sendRequest(($uid ? 'UID ' : '') . 'FETCH', [$set, $itemList], $tag);
$result = [];
$tokens = null; // define $tokens variable before first use
while (! $this->readLine($tokens, $tag)) {
// ignore other responses
if ($tokens[1] != 'FETCH') {
continue;
}
// find array key of UID value; try the last elements, or search for it
if ($uid) {
$count = count($tokens[2]);
if ($tokens[2][$count - 2] == 'UID') {
$uidKey = $count - 1;
} else {
$uidKey = array_search('UID', $tokens[2]) + 1;
}
}
// ignore other messages
if ($to === null && ! is_array($from) && ($uid ? $tokens[2][$uidKey] != $from : $tokens[0] != $from)) {
continue;
}
// if we only want one item we return that one directly
if (count($items) == 1) {
if ($tokens[2][0] == $items[0]) {
$data = $tokens[2][1];
} elseif ($uid && $tokens[2][2] == $items[0]) {
$data = $tokens[2][3];
} else {
// maybe the server send an other field we didn't wanted
$count = count($tokens[2]);
// we start with 2, because 0 was already checked
for ($i = 2; $i < $count; $i += 2) {
if ($tokens[2][$i] != $items[0]) {
continue;
}
$data = $tokens[2][$i + 1];
break;
}
}
} else {
$data = [];
while (key($tokens[2]) !== null) {
$data[current($tokens[2])] = next($tokens[2]);
next($tokens[2]);
}
}
// if we want only one message we can ignore everything else and just return
if ($to === null && ! is_array($from) && ($uid ? $tokens[2][$uidKey] == $from : $tokens[0] == $from)) {
// we still need to read all lines
// phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedWhile
while (! $this->readLine($tokens, $tag)) {
}
return $data;
}
$result[$tokens[0]] = $data;
}
if ($to === null && ! is_array($from)) {
throw new Exception\RuntimeException('the single id was not found in response');
}
return $result;
}
/**
* get mailbox list
*
* this method can't be named after the IMAP command 'LIST', as list is a reserved keyword
*
* @param string $reference mailbox reference for list
* @param string $mailbox mailbox name match with wildcards
* @return array mailboxes that matched $mailbox as array(globalName => array('delim' => .., 'flags' => ..))
* @throws ExceptionInterface
*/
public function listMailbox($reference = '', $mailbox = '*')
{
$result = [];
$list = $this->requestAndResponse('LIST', $this->escapeString($reference, $mailbox));
if (! $list || $list === true) {
return $result;
}
foreach ($list as $item) {
if (count($item) != 4 || $item[0] != 'LIST') {
continue;
}
$result[$item[3]] = ['delim' => $item[2], 'flags' => $item[1]];
}
return $result;
}
/**
* set flags
*
* @param array $flags flags to set, add or remove - see $mode
* @param int $from message for items or start message if $to !== null
* @param int|null $to if null only one message ($from) is fetched, else it's the
* last message, INF means last message available
* @param string|null $mode '+' to add flags, '-' to remove flags, everything else sets the flags as given
* @param bool $silent if false the return values are the new flags for the wanted messages
* @return bool|array new flags if $silent is false, else true or false depending on success
* @throws ExceptionInterface
*/
public function store(array $flags, $from, $to = null, $mode = null, $silent = true)
{
$item = 'FLAGS';
if ($mode == '+' || $mode == '-') {
$item = $mode . $item;
}
if ($silent) {
$item .= '.SILENT';
}
$flags = $this->escapeList($flags);
$set = (int) $from;
if ($to !== null) {
$set .= ':' . ($to == INF ? '*' : (int) $to);
}
$result = $this->requestAndResponse('STORE', [$set, $item, $flags], $silent);
if ($silent) {
return (bool) $result;
}
$tokens = $result;
$result = [];
foreach ($tokens as $token) {
if ($token[1] != 'FETCH' || $token[2][0] != 'FLAGS') {
continue;
}
$result[$token[0]] = $token[2][1];
}
return $result;
}
/**
* append a new message to given folder
*
* @param string $folder name of target folder
* @param string $message full message content
* @param array $flags flags for new message
* @param string $date date for new message
* @return bool success
* @throws ExceptionInterface
*/
public function append($folder, $message, $flags = null, $date = null)
{
$tokens = [];
$tokens[] = $this->escapeString($folder);
if ($flags !== null) {
$tokens[] = $this->escapeList($flags);
}
if ($date !== null) {
$tokens[] = $this->escapeString($date);
}
$tokens[] = $this->escapeString($message);
return $this->requestAndResponse('APPEND', $tokens, true);
}
/**
* copy message set from current folder to other folder
*
* @param string $folder destination folder
* @param int $from
* @param int|null $to if null only one message ($from) is fetched, else it's the
* last message, INF means last message available
* @return bool success
*/
public function copy($folder, $from, $to = null)
{
$set = (string) $from;
if ($to !== null) {
$set .= ':' . ($to == INF ? '*' : (int) $to);
}
return $this->requestAndResponse('COPY', [$set, $this->escapeString($folder)], true);
}
/**
* create a new folder (and parent folders if needed)
*
* @param string $folder folder name
* @return bool success
*/
public function create($folder)
{
return $this->requestAndResponse('CREATE', [$this->escapeString($folder)], true);
}
/**
* rename an existing folder
*
* @param string $old old name
* @param string $new new name
* @return bool success
*/
public function rename($old, $new)
{
return $this->requestAndResponse('RENAME', $this->escapeString($old, $new), true);
}
/**
* remove a folder
*
* @param string $folder folder name
* @return bool success
*/
public function delete($folder)
{
return $this->requestAndResponse('DELETE', [$this->escapeString($folder)], true);
}
/**
* subscribe to a folder
*
* @param string $folder folder name
* @return bool success
*/
public function subscribe($folder)
{
return $this->requestAndResponse('SUBSCRIBE', [$this->escapeString($folder)], true);
}
/**
* permanently remove messages
*
* @return bool success
*/
public function expunge()
{
// TODO: parse response?
return $this->requestAndResponse('EXPUNGE');
}
/**
* send noop
*
* @return bool success
*/
public function noop()
{
// TODO: parse response
return $this->requestAndResponse('NOOP');
}
/**
* do a search request
*
* This method is currently marked as internal as the API might change and is not
* safe if you don't take precautions.
*
* @param array $params
* @return array message ids
*/
public function search(array $params)
{
$response = $this->requestAndResponse('SEARCH', $params);
if (! $response) {
return $response;
}
foreach ($response as $ids) {
if ($ids[0] == 'SEARCH') {
array_shift($ids);
return $ids;
}
}
return [];
}
}
laminas-mail/src/Protocol/ProtocolTrait.php 0000644 00000006464 15240152655 0015035 0 ustar 00 <?php
namespace Laminas\Mail\Protocol;
use Laminas\Stdlib\ErrorHandler;
use function defined;
use function sprintf;
use function stream_context_create;
use function stream_set_timeout;
use function stream_socket_client;
use const STREAM_CLIENT_CONNECT;
use const STREAM_CRYPTO_METHOD_TLS_CLIENT;
use const STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
use const STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
/**
* https://bugs.php.net/bug.php?id=69195
*/
trait ProtocolTrait
{
/**
* If set to true, do not validate the SSL certificate
*
* @var null|bool
*/
protected $novalidatecert;
public function getCryptoMethod(): int
{
// Allow the best TLS version(s) we can
$cryptoMethod = STREAM_CRYPTO_METHOD_TLS_CLIENT;
// PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT
// so add them back in manually if we can
if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
$cryptoMethod |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
$cryptoMethod |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
}
return $cryptoMethod;
}
/**
* Do not validate SSL certificate
*
* @todo Update to return self when minimum supported PHP version is 7.4+
* @param bool $novalidatecert Set to true to disable certificate validation
* @return $this
*/
public function setNoValidateCert(bool $novalidatecert)
{
$this->novalidatecert = $novalidatecert;
return $this;
}
/**
* Should we validate SSL certificate?
*/
public function validateCert(): bool
{
return ! $this->novalidatecert;
}
/**
* Prepare socket options
*
* @return array
*/
private function prepareSocketOptions(): array
{
return $this->novalidatecert
? [
'ssl' => [
'verify_peer_name' => false,
'verify_peer' => false,
],
]
: [];
}
/**
* Setup connection socket
*
* @param string $host hostname or IP address of IMAP server
* @param int|null $port of IMAP server, default is 143 (993 for ssl)
* @param int $timeout timeout in seconds for initiating session
* @return resource The socket created.
* @throws Exception\RuntimeException If unable to connect to host.
*/
protected function setupSocket(
string $transport,
string $host,
?int $port,
int $timeout
) {
ErrorHandler::start();
$socket = stream_socket_client(
sprintf('%s://%s:%d', $transport, $host, $port),
$errno,
$errstr,
$timeout,
STREAM_CLIENT_CONNECT,
stream_context_create($this->prepareSocketOptions())
);
$error = ErrorHandler::stop();
if (! $socket) {
throw new Exception\RuntimeException(sprintf(
'cannot connect to host%s',
$error ? sprintf('; error = %s (errno = %d )', $error->getMessage(), $error->getCode()) : ''
), 0, $error);
}
if (false === stream_set_timeout($socket, $timeout)) {
throw new Exception\RuntimeException('Could not set stream timeout');
}
return $socket;
}
}
laminas-mail/src/Protocol/Pop3.php 0000644 00000025770 15240152655 0013052 0 ustar 00 <?php
namespace Laminas\Mail\Protocol;
use Laminas\Mail\Protocol\Pop3\Response;
use Laminas\Stdlib\ErrorHandler;
use function explode;
use function fclose;
use function fgets;
use function fwrite;
use function is_string;
use function md5;
use function rtrim;
use function stream_socket_enable_crypto;
use function strpos;
use function strtok;
use function strtolower;
use function substr;
use function trim;
class Pop3
{
use ProtocolTrait;
/**
* Default timeout in seconds for initiating session
*/
public const TIMEOUT_CONNECTION = 30;
/**
* saves if server supports top
*
* @var null|bool
*/
public $hasTop;
/** @var null|resource */
protected $socket;
/**
* greeting timestamp for apop
*
* @var null|string
*/
protected $timestamp;
/**
* Public constructor
*
* @param string $host hostname or IP address of POP3 server, if given connect() is called
* @param int|null $port port of POP3 server, null for default (110 or 995 for ssl)
* @param bool|string $ssl use ssl? 'SSL', 'TLS' or false
* @param bool $novalidatecert set to true to skip SSL certificate validation
*/
public function __construct($host = '', $port = null, $ssl = false, $novalidatecert = false)
{
$this->setNoValidateCert($novalidatecert);
if ($host) {
$this->connect($host, $port, $ssl);
}
}
/**
* Public destructor
*/
public function __destruct()
{
$this->logout();
}
/**
* Open connection to POP3 server
*
* @param string $host hostname or IP address of POP3 server
* @param int|null $port of POP3 server, default is 110 (995 for ssl)
* @param string|bool $ssl use 'SSL', 'TLS' or false
* @throws Exception\RuntimeException
* @return string welcome message
*/
public function connect($host, $port = null, $ssl = false)
{
$transport = 'tcp';
$isTls = false;
if ($ssl) {
$ssl = strtolower($ssl);
}
switch ($ssl) {
case 'ssl':
$transport = 'ssl';
if (! $port) {
$port = 995;
}
break;
case 'tls':
$isTls = true;
// break intentionally omitted
default:
if (! $port) {
$port = 110;
}
}
$this->socket = $this->setupSocket($transport, $host, $port, self::TIMEOUT_CONNECTION);
$welcome = $this->readResponse();
strtok($welcome, '<');
$this->timestamp = strtok('>');
if (! strpos($this->timestamp, '@')) {
$this->timestamp = null;
} else {
$this->timestamp = '<' . $this->timestamp . '>';
}
if ($isTls) {
$this->request('STLS');
$result = stream_socket_enable_crypto($this->socket, true, $this->getCryptoMethod());
if (! $result) {
throw new Exception\RuntimeException('cannot enable TLS');
}
}
return $welcome;
}
/**
* Send a request
*
* @param string $request your request without newline
* @throws Exception\RuntimeException
*/
public function sendRequest($request)
{
ErrorHandler::start();
$result = fwrite($this->socket, $request . "\r\n");
$error = ErrorHandler::stop();
if (! $result) {
throw new Exception\RuntimeException('send failed - connection closed?', 0, $error);
}
}
/**
* read a response
*
* @param bool $multiline response has multiple lines and should be read until "<nl>.<nl>"
* @throws Exception\RuntimeException
* @return string response
*/
public function readResponse($multiline = false)
{
$response = $this->readRemoteResponse();
if ($response->status() != '+OK') {
throw new Exception\RuntimeException('last request failed');
}
$message = $response->message();
if ($multiline) {
$message = '';
$line = fgets($this->socket);
while ($line && rtrim($line, "\r\n") != '.') {
if ($line[0] == '.') {
$line = substr($line, 1);
}
$message .= $line;
$line = fgets($this->socket);
}
}
return $message;
}
/**
* read a response
* return extracted status / message from response
* @throws Exception\RuntimeException
*/
protected function readRemoteResponse(): Response
{
ErrorHandler::start();
$result = fgets($this->socket);
$error = ErrorHandler::stop();
if (! is_string($result)) {
throw new Exception\RuntimeException('read failed - connection closed?', 0, $error);
}
$result = trim($result);
if (strpos($result, ' ')) {
[$status, $message] = explode(' ', $result, 2);
} else {
$status = $result;
$message = '';
}
return new Response($status, $message);
}
/**
* Send request and get response
*
* @see sendRequest()
* @see readResponse()
*
* @param string $request request
* @param bool $multiline multiline response?
* @return string result from readResponse()
*/
public function request($request, $multiline = false)
{
$this->sendRequest($request);
return $this->readResponse($multiline);
}
/**
* End communication with POP3 server (also closes socket)
*/
public function logout()
{
if ($this->socket) {
try {
$this->request('QUIT');
} catch (Exception\ExceptionInterface) {
// ignore error - we're closing the socket anyway
}
fclose($this->socket);
$this->socket = null;
}
}
/**
* Get capabilities from POP3 server
*
* @return array list of capabilities
*/
public function capa()
{
$result = $this->request('CAPA', true);
return explode("\n", $result);
}
/**
* Login to POP3 server. Can use APOP
*
* @param string $user username
* @param string $password password
* @param bool $tryApop should APOP be tried?
*/
public function login($user, $password, $tryApop = true)
{
if ($tryApop && $this->timestamp) {
try {
$this->request("APOP $user " . md5($this->timestamp . $password));
return;
} catch (Exception\ExceptionInterface) {
// ignore
}
}
$this->request("USER $user");
$this->request("PASS $password");
}
/**
* Make STAT call for message count and size sum
*
* @param int $messages out parameter with count of messages
* @param int $octets out parameter with size in octets of messages
*/
public function status(&$messages, &$octets)
{
$messages = 0;
$octets = 0;
$result = $this->request('STAT');
[$messages, $octets] = explode(' ', $result);
}
/**
* Make LIST call for size of message(s)
*
* @param int|null $msgno number of message, null for all
* @return int|array size of given message or list with array(num => size)
*/
public function getList($msgno = null)
{
if ($msgno !== null) {
$result = $this->request("LIST $msgno");
[, $result] = explode(' ', $result);
return (int) $result;
}
$result = $this->request('LIST', true);
$messages = [];
$line = strtok($result, "\n");
while ($line) {
[$no, $size] = explode(' ', trim($line));
$messages[(int) $no] = (int) $size;
$line = strtok("\n");
}
return $messages;
}
/**
* Make UIDL call for getting a uniqueid
*
* @param int|null $msgno number of message, null for all
* @return string|array uniqueid of message or list with array(num => uniqueid)
*/
public function uniqueid($msgno = null)
{
if ($msgno !== null) {
$result = $this->request("UIDL $msgno");
[, $result] = explode(' ', $result);
return $result;
}
$result = $this->request('UIDL', true);
$result = explode("\n", $result);
$messages = [];
foreach ($result as $line) {
if (! $line) {
continue;
}
[$no, $id] = explode(' ', trim($line), 2);
$messages[(int) $no] = $id;
}
return $messages;
}
/**
* Make TOP call for getting headers and maybe some body lines
* This method also sets hasTop - before it it's not known if top is supported
*
* The fallback makes normal RETR call, which retrieves the whole message. Additional
* lines are not removed.
*
* @param int $msgno number of message
* @param int $lines number of wanted body lines (empty line is inserted after header lines)
* @param bool $fallback fallback with full retrieve if top is not supported
* @throws Exception\RuntimeException
* @throws Exception\ExceptionInterface
* @return string message headers with wanted body lines
*/
public function top($msgno, $lines = 0, $fallback = false)
{
if ($this->hasTop === false) {
if ($fallback) {
return $this->retrieve($msgno);
}
throw new Exception\RuntimeException('top not supported and no fallback wanted');
}
$this->hasTop = true;
$lines = ! $lines || $lines < 1 ? 0 : (int) $lines;
try {
$result = $this->request("TOP $msgno $lines", true);
} catch (Exception\ExceptionInterface $e) {
$this->hasTop = false;
if ($fallback) {
$result = $this->retrieve($msgno);
} else {
throw $e;
}
}
return $result;
}
/**
* Make a RETR call for retrieving a full message with headers and body
*
* @param int $msgno message number
* @return string message
*/
public function retrieve($msgno)
{
return $this->request("RETR $msgno", true);
}
/**
* Make a NOOP call, maybe needed for keeping the server happy
*/
public function noop()
{
$this->request('NOOP');
}
/**
* Make a DELE count to remove a message
*
* @param int $msgno
*/
public function delete($msgno)
{
$this->request("DELE $msgno");
}
/**
* Make RSET call, which rollbacks delete requests
*/
public function undelete()
{
$this->request('RSET');
}
}
laminas-mail/src/Protocol/AbstractProtocol.php 0000644 00000022427 15240152655 0015512 0 ustar 00 <?php
namespace Laminas\Mail\Protocol;
use Laminas\Validator;
use Laminas\Validator\ValidatorChain;
use function array_shift;
use function count;
use function fclose;
use function fgets;
use function fwrite;
use function implode;
use function in_array;
use function is_array;
use function is_resource;
use function preg_split;
use function restore_error_handler;
use function set_error_handler;
use function sprintf;
use function str_starts_with;
use function stream_get_meta_data;
use function stream_set_timeout;
use function stream_socket_client;
use const E_WARNING;
use const PREG_SPLIT_DELIM_CAPTURE;
/**
* Provides low-level methods for concrete adapters to communicate with a
* remote mail server and track requests and responses.
*
* @todo Implement proxy settings
*/
abstract class AbstractProtocol
{
/**
* Mail default EOL string
*/
public const EOL = "\r\n";
/**
* Default timeout in seconds for initiating session
*/
public const TIMEOUT_CONNECTION = 30;
/**
* Maximum of the transaction log
*
* @var int
*/
protected $maximumLog = 64;
/**
* Hostname or IP address of remote server
*
* @var string
*/
protected $host;
/**
* Instance of Laminas\Validator\ValidatorChain to check hostnames
*
* @var ValidatorChain
*/
protected $validHost;
/**
* Socket connection resource
*
* @var null|resource
*/
protected $socket;
/**
* Last request sent to server
*
* @var string
*/
protected $request;
/**
* Array of server responses to last request
*
* @var array
*/
protected $response;
/**
* Log of mail requests and server responses for a session
*/
private array $log = [];
/**
* @param string $host OPTIONAL Hostname of remote connection (default: 127.0.0.1)
* @param int $port OPTIONAL Port number (default: null)
* @throws Exception\RuntimeException
*/
public function __construct($host = '127.0.0.1', protected $port = null)
{
$this->validHost = new Validator\ValidatorChain();
$this->validHost->attach(new Validator\Hostname(Validator\Hostname::ALLOW_ALL));
if (! $this->validHost->isValid($host)) {
throw new Exception\RuntimeException(implode(', ', $this->validHost->getMessages()));
}
$this->host = $host;
}
/**
* Class destructor to cleanup open resources
*/
public function __destruct()
{
$this->_disconnect();
}
/**
* Set the maximum log size
*
* @param int $maximumLog Maximum log size
*/
public function setMaximumLog($maximumLog)
{
$this->maximumLog = (int) $maximumLog;
}
/**
* Get the maximum log size
*
* @return int the maximum log size
*/
public function getMaximumLog()
{
return $this->maximumLog;
}
/**
* Create a connection to the remote host
*
* Concrete adapters for this class will implement their own unique connect
* scripts, using the _connect() method to create the socket resource.
*/
abstract public function connect();
/**
* Retrieve the last client request
*
* @return string
*/
public function getRequest()
{
return $this->request;
}
/**
* Retrieve the last server response
*
* @return array
*/
public function getResponse()
{
return $this->response;
}
/**
* Retrieve the transaction log
*
* @return string
*/
public function getLog()
{
return implode('', $this->log);
}
/**
* Reset the transaction log
*/
public function resetLog()
{
$this->log = [];
}
/**
* Add the transaction log
*
* @param string $value new transaction
*/
// @codingStandardsIgnoreLine PSR2.Methods.MethodDeclaration.Underscore
protected function _addLog($value)
{
if ($this->maximumLog >= 0 && count($this->log) >= $this->maximumLog) {
array_shift($this->log);
}
$this->log[] = $value;
}
/**
* Connect to the server using the supplied transport and target
*
* An example $remote string may be 'tcp://mail.example.com:25' or 'ssh://hostname.com:2222'
*
* @deprecated Since 1.12.0. Implementations should use the ProtocolTrait::setupSocket() method instead.
*
* @todo Remove for 3.0.0.
* @param string $remote Remote
* @throws Exception\RuntimeException
* @return bool
*/
// @codingStandardsIgnoreLine PSR2.Methods.MethodDeclaration.Underscore
protected function _connect($remote)
{
$errorNum = 0;
$errorStr = '';
// open connection
set_error_handler(
static function ($error, $message = '') {
throw new Exception\RuntimeException(sprintf('Could not open socket: %s', $message), $error);
},
E_WARNING
);
$this->socket = stream_socket_client($remote, $errorNum, $errorStr, self::TIMEOUT_CONNECTION);
restore_error_handler();
if ($this->socket === false) {
if ($errorNum == 0) {
$errorStr = 'Could not open socket';
}
throw new Exception\RuntimeException($errorStr);
}
if (($result = stream_set_timeout($this->socket, self::TIMEOUT_CONNECTION)) === false) {
throw new Exception\RuntimeException('Could not set stream timeout');
}
return $result;
}
/**
* Disconnect from remote host and free resource
*/
// @codingStandardsIgnoreLine PSR2.Methods.MethodDeclaration.Underscore
protected function _disconnect()
{
if (is_resource($this->socket)) {
fclose($this->socket);
}
}
/**
* Send the given request followed by a LINEEND to the server.
*
* @param string $request
* @throws Exception\RuntimeException
* @return int|bool Number of bytes written to remote host
*/
// @codingStandardsIgnoreLine PSR2.Methods.MethodDeclaration.Underscore
protected function _send($request)
{
if (! is_resource($this->socket)) {
throw new Exception\RuntimeException('No connection has been established to ' . $this->host);
}
$this->request = $request;
$result = fwrite($this->socket, $request . self::EOL);
// Save request to internal log
$this->_addLog($request . self::EOL);
if ($result === false) {
throw new Exception\RuntimeException('Could not send request to ' . $this->host);
}
return $result;
}
/**
* Get a line from the stream.
*
* @param int $timeout Per-request timeout value if applicable
* @throws Exception\RuntimeException
* @return string
*/
// @codingStandardsIgnoreLine PSR2.Methods.MethodDeclaration.Underscore
protected function _receive($timeout = null)
{
if (! is_resource($this->socket)) {
throw new Exception\RuntimeException('No connection has been established to ' . $this->host);
}
// Adapters may wish to supply per-commend timeouts according to appropriate RFC
if ($timeout !== null) {
stream_set_timeout($this->socket, $timeout);
}
// Retrieve response
$response = fgets($this->socket, 1024);
// Save request to internal log
$this->_addLog($response);
// Check meta data to ensure connection is still valid
$info = stream_get_meta_data($this->socket);
if ($info['timed_out']) {
throw new Exception\RuntimeException($this->host . ' has timed out');
}
if ($response === false) {
throw new Exception\RuntimeException('Could not read from ' . $this->host);
}
return $response;
}
/**
* Parse server response for successful codes
*
* Read the response from the stream and check for expected return code.
* Throws a Laminas\Mail\Protocol\Exception\ExceptionInterface if an unexpected code is returned.
*
* @param string|array $code One or more codes that indicate a successful response
* @param int $timeout Per-request timeout value if applicable
* @throws Exception\RuntimeException
* @return string Last line of response string
*/
// @codingStandardsIgnoreLine PSR2.Methods.MethodDeclaration.Underscore
protected function _expect($code, $timeout = null)
{
$this->response = [];
$errMsg = '';
if (! is_array($code)) {
$code = [$code];
}
do {
$this->response[] = $result = $this->_receive($timeout);
[$cmd, $more, $msg] = preg_split('/([\s-]+)/', $result, 2, PREG_SPLIT_DELIM_CAPTURE);
if ($errMsg !== '') {
$errMsg .= ' ' . $msg;
} elseif ($cmd === null || ! in_array($cmd, $code)) {
$errMsg = $msg;
}
// The '-' message prefix indicates an information string instead of a response string.
} while (str_starts_with($more, '-'));
if ($errMsg !== '') {
throw new Exception\RuntimeException($errMsg);
}
return $msg;
}
}
laminas-mail/src/Protocol/SmtpPluginManager.php 0000644 00000007306 15240152655 0015621 0 ustar 00 <?php
namespace Laminas\Mail\Protocol;
use Laminas\ServiceManager\AbstractPluginManager;
use Laminas\ServiceManager\ConfigInterface;
use Laminas\ServiceManager\Exception\InvalidServiceException;
use Laminas\ServiceManager\Factory\InvokableFactory;
use function gettype;
use function is_object;
use function sprintf;
/**
* Plugin manager implementation for SMTP extensions.
*
* Enforces that SMTP extensions retrieved are instances of Smtp. Additionally,
* it registers a number of default extensions available.
*
* @link ConfigInterface
*
* @psalm-import-type FactoriesConfigurationType from ConfigInterface
*
* @extends AbstractPluginManager<Smtp>
* @final
*/
class SmtpPluginManager extends AbstractPluginManager
{
/**
* Service aliases
*
* @var array<array-key, class-string>
*/
protected $aliases = [
'crammd5' => Smtp\Auth\Crammd5::class,
'cramMd5' => Smtp\Auth\Crammd5::class,
'CramMd5' => Smtp\Auth\Crammd5::class,
'cramMD5' => Smtp\Auth\Crammd5::class,
'CramMD5' => Smtp\Auth\Crammd5::class,
'login' => Smtp\Auth\Login::class,
'Login' => Smtp\Auth\Login::class,
'plain' => Smtp\Auth\Plain::class,
'Plain' => Smtp\Auth\Plain::class,
'smtp' => Smtp::class,
'Smtp' => Smtp::class,
'SMTP' => Smtp::class,
// Legacy Zend Framework aliases
'Zend\Mail\Protocol\Smtp\Auth\Crammd5' => Smtp\Auth\Crammd5::class,
'Zend\Mail\Protocol\Smtp\Auth\Login' => Smtp\Auth\Login::class,
'Zend\Mail\Protocol\Smtp\Auth\Plain' => Smtp\Auth\Plain::class,
'Zend\Mail\Protocol\Smtp' => Smtp::class,
// v2 normalized FQCNs
'zendmailprotocolsmtpauthcrammd5' => Smtp\Auth\Crammd5::class,
'zendmailprotocolsmtpauthlogin' => Smtp\Auth\Login::class,
'zendmailprotocolsmtpauthplain' => Smtp\Auth\Plain::class,
'zendmailprotocolsmtp' => Smtp::class,
'laminasmailprotocolsmtpauthcrammd5' => Smtp\Auth\Crammd5::class,
'laminasmailprotocolsmtpauthlogin' => Smtp\Auth\Login::class,
'laminasmailprotocolsmtpauthplain' => Smtp\Auth\Plain::class,
'laminasmailprotocolsmtp' => Smtp::class,
];
/**
* Service factories
*
* @var FactoriesConfigurationType
*/
protected $factories = [
Smtp\Auth\Crammd5::class => InvokableFactory::class,
Smtp\Auth\Login::class => InvokableFactory::class,
Smtp\Auth\Plain::class => InvokableFactory::class,
Smtp::class => InvokableFactory::class,
];
/**
* Plugins must be an instance of the Smtp class
*
* @var class-string<Smtp>
*/
protected $instanceOf = Smtp::class;
/**
* Validate a retrieved plugin instance (v3).
*
* {@inheritDoc}
*/
public function validate(mixed $instance)
{
if (! $instance instanceof $this->instanceOf) {
throw new InvalidServiceException(sprintf(
'Plugin of type %s is invalid; must extend %s',
is_object($instance) ? $instance::class : gettype($instance),
$this->instanceOf
));
}
}
/**
* Validate a retrieved plugin instance (v2).
*
* @deprecated
*
* @param object $plugin
* @throws Exception\InvalidArgumentException
*/
public function validatePlugin(mixed $plugin)
{
try {
$this->validate($plugin);
} catch (InvalidServiceException $e) {
throw new Exception\InvalidArgumentException(
$e->getMessage(),
$e->getCode(),
$e
);
}
}
}
laminas-mail/src/Protocol/SmtpPluginManagerFactory.php 0000644 00000002771 15240152655 0017152 0 ustar 00 <?php
namespace Laminas\Mail\Protocol;
// phpcs:ignore WebimpressCodingStandard.PHP.CorrectClassNameCase.Invalid
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\FactoryInterface;
use Laminas\ServiceManager\ServiceLocatorInterface;
use Laminas\ServiceManager\ServiceManager;
/**
* @link ServiceManager
*
* @psalm-import-type ServiceManagerConfiguration from ServiceManager
*/
class SmtpPluginManagerFactory implements FactoryInterface
{
/**
* laminas-servicemanager v2 support for invocation options.
*
* @var array
* @psalm-var ServiceManagerConfiguration
*/
protected $creationOptions;
/**
* {@inheritDoc}
*
* @psalm-param ServiceManagerConfiguration $options
* @return SmtpPluginManager
*/
public function __invoke(ContainerInterface $container, $name, ?array $options = null)
{
return new SmtpPluginManager($container, $options ?: []);
}
/**
* {@inheritDoc}
*
* @return SmtpPluginManager
*/
public function createService(ServiceLocatorInterface $container, $name = null, $requestedName = null)
{
return $this($container, $requestedName ?: SmtpPluginManager::class, $this->creationOptions);
}
/**
* laminas-servicemanager v2 support for invocation options.
*
* @psalm-param ServiceManagerConfiguration $options
* @return void
*/
public function setCreationOptions(array $options)
{
$this->creationOptions = $options;
}
}
laminas-mail/src/Protocol/Exception/InvalidArgumentException.php 0000644 00000000355 15240152655 0021127 0 ustar 00 <?php
namespace Laminas\Mail\Protocol\Exception;
use Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface
{
}
laminas-mail/src/Protocol/Exception/ExceptionInterface.php 0000644 00000000253 15240152655 0017733 0 ustar 00 <?php
namespace Laminas\Mail\Protocol\Exception;
use Laminas\Mail\Exception\ExceptionInterface as MailException;
interface ExceptionInterface extends MailException
{
}
laminas-mail/src/Protocol/Exception/RuntimeException.php 0000644 00000000335 15240152655 0017457 0 ustar 00 <?php
namespace Laminas\Mail\Protocol\Exception;
use Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class RuntimeException extends Exception\RuntimeException implements ExceptionInterface
{
}
laminas-mail/src/Protocol/Smtp.php 0000644 00000034546 15240152655 0013155 0 ustar 00 <?php
namespace Laminas\Mail\Protocol;
use Generator;
use Laminas\Mail\Headers;
use function array_key_exists;
use function array_replace_recursive;
use function chunk_split;
use function fclose;
use function fgets;
use function fopen;
use function fwrite;
use function implode;
use function ini_get;
use function is_array;
use function rewind;
use function rtrim;
use function stream_socket_enable_crypto;
use function strlen;
use function strtolower;
use function substr;
/**
* SMTP implementation of Laminas\Mail\Protocol\AbstractProtocol
*
* Minimum implementation according to RFC2821: EHLO, MAIL FROM, RCPT TO, DATA,
* RSET, NOOP, QUIT
*/
class Smtp extends AbstractProtocol
{
use ProtocolTrait;
/**
* RFC 5322 section-2.2.3 specifies maximum of 998 bytes per line.
* This may not be exceeded.
*
* @see https://tools.ietf.org/html/rfc5322#section-2.2.3
*/
public const SMTP_LINE_LIMIT = 998;
/**
* The transport method for the socket
*
* @var string
*/
protected $transport = 'tcp';
/**
* Indicates that a session is requested to be secure
*
* @var string
*/
protected $secure;
/**
* Indicates an smtp session has been started by the HELO command
*
* @var bool
*/
protected $sess = false;
/**
* Indicates an smtp AUTH has been issued and authenticated
*
* @var bool
*/
protected $auth = false;
/**
* Indicates a MAIL command has been issued
*
* @var bool
*/
protected $mail = false;
/**
* Indicates one or more RCTP commands have been issued
*
* @var bool
*/
protected $rcpt = false;
/**
* Indicates that DATA has been issued and sent
*
* @var bool
*/
protected $data;
/**
* Whether or not send QUIT command
*
* @var bool
*/
protected $useCompleteQuit = true;
/**
* The first argument may be an array of all options. If so, it must include
* the 'host' and 'port' keys in order to ensure that all required values
* are present.
*
* @param string|array $host
* @param null|int $port
* @param null|array $config
* @throws Exception\InvalidArgumentException
*/
public function __construct($host = '127.0.0.1', $port = null, ?array $config = null)
{
// Did we receive a configuration array?
if (is_array($host)) {
// Merge config array with principal array, if provided
if (is_array($config)) {
$config = array_replace_recursive($host, $config);
} else {
$config = $host;
}
// Look for a host key; if none found, use default value
if (isset($config['host'])) {
$host = $config['host'];
} else {
$host = '127.0.0.1';
}
// Look for a port key; if none found, use default value
if (isset($config['port'])) {
$port = $config['port'];
} else {
$port = null;
}
}
// If we don't have a config array, initialize it
if (null === $config) {
$config = [];
}
if (isset($config['ssl'])) {
switch (strtolower($config['ssl'])) {
case 'tls':
$this->secure = 'tls';
break;
case 'ssl':
$this->transport = 'ssl';
$this->secure = 'ssl';
if ($port === null) {
$port = 465;
}
break;
case '':
// fall-through
case 'none':
break;
default:
throw new Exception\InvalidArgumentException($config['ssl'] . ' is unsupported SSL type');
}
}
if (array_key_exists('use_complete_quit', $config)) {
$this->setUseCompleteQuit($config['use_complete_quit']);
}
// If no port has been specified then check the master PHP ini file. Defaults to 25 if the ini setting is null.
if ($port === null) {
if (($port = ini_get('smtp_port')) == '') {
$port = 25;
}
}
if (array_key_exists('novalidatecert', $config)) {
$this->setNoValidateCert($config['novalidatecert']);
}
parent::__construct($host, $port);
}
/**
* Set whether or not send QUIT command
*
* @param bool $useCompleteQuit use complete quit
* @return bool
*/
public function setUseCompleteQuit($useCompleteQuit)
{
return $this->useCompleteQuit = (bool) $useCompleteQuit;
}
/**
* Read $data as lines terminated by "\n"
*
* @return Generator|string[]
*/
private static function chunkedReader(string $data, int $chunkSize = 4096): Generator
{
if (($fp = fopen("php://temp", "r+")) === false) {
throw new Exception\RuntimeException('cannot fopen');
}
if (fwrite($fp, $data) === false) {
throw new Exception\RuntimeException('cannot fwrite');
}
rewind($fp);
$line = null;
while (($buffer = fgets($fp, $chunkSize)) !== false) {
$line .= $buffer;
// This is optimization to avoid calling length() in a loop.
// We need to match a condition that is when:
// 1. maximum was read from fgets, which is $chunkSize-1
// 2. last byte of the buffer is not \n
//
// to access last byte of buffer, we can do
// - $buffer[strlen($buffer)-1]
// and when maximum is read from fgets, then:
// - strlen($buffer) === $chunkSize-1
// - strlen($buffer)-1 === $chunkSize-2
// which means this is also true:
// - $buffer[strlen($buffer)-1] === $buffer[$chunkSize-2]
//
// the null coalesce works, as string offset can never be null
$lastByte = $buffer[$chunkSize - 2] ?? null;
// partial read, continue loop to read again to complete the line
// compare \n first as that's usually false
if ($lastByte !== "\n" && $lastByte !== null) {
continue;
}
yield $line;
$line = null;
}
if ($line !== null) {
yield $line;
}
fclose($fp);
}
/**
* Whether or not send QUIT command
*
* @return bool
*/
public function useCompleteQuit()
{
return $this->useCompleteQuit;
}
/**
* Connect to the server with the parameters given in the constructor.
*
* @return bool
*/
public function connect()
{
$this->socket = $this->setupSocket(
$this->transport,
$this->host,
$this->port,
self::TIMEOUT_CONNECTION
);
return true;
}
/**
* Initiate HELO/EHLO sequence and set flag to indicate valid smtp session
*
* @param string $host The client hostname or IP address (default: 127.0.0.1)
* @throws Exception\RuntimeException
*/
public function helo($host = '127.0.0.1')
{
// Respect RFC 2821 and disallow HELO attempts if session is already initiated.
if ($this->sess === true) {
throw new Exception\RuntimeException('Cannot issue HELO to existing session');
}
// Validate client hostname
if (! $this->validHost->isValid($host)) {
throw new Exception\RuntimeException(implode(', ', $this->validHost->getMessages()));
}
// Initiate helo sequence
$this->_expect(220, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
$this->ehlo($host);
// If a TLS session is required, commence negotiation
if ($this->secure == 'tls') {
$this->_send('STARTTLS');
$this->_expect(220, 180);
if (! stream_socket_enable_crypto($this->socket, true, $this->getCryptoMethod())) {
throw new Exception\RuntimeException('Unable to connect via TLS');
}
$this->ehlo($host);
}
$this->startSession();
$this->auth();
}
/**
* Returns the perceived session status
*
* @return bool
*/
public function hasSession()
{
return $this->sess;
}
/**
* Send EHLO or HELO depending on capabilities of smtp host
*
* @param string $host The client hostname or IP address (default: 127.0.0.1)
* @throws Exception\ExceptionInterface
*/
protected function ehlo($host)
{
// Support for older, less-compliant remote servers. Tries multiple attempts of EHLO or HELO.
try {
$this->_send('EHLO ' . $host);
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
} catch (Exception\ExceptionInterface) {
$this->_send('HELO ' . $host);
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
}
}
/**
* Issues MAIL command
*
* @param string $from Sender mailbox
* @throws Exception\RuntimeException
*/
public function mail($from)
{
if ($this->sess !== true) {
throw new Exception\RuntimeException('A valid session has not been started');
}
$this->_send('MAIL FROM:<' . $from . '>');
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
// Set mail to true, clear recipients and any existing data flags as per 4.1.1.2 of RFC 2821
$this->mail = true;
$this->rcpt = false;
$this->data = false;
}
/**
* Issues RCPT command
*
* @param string $to Receiver(s) mailbox
* @throws Exception\RuntimeException
*/
public function rcpt($to)
{
if ($this->mail !== true) {
throw new Exception\RuntimeException('No sender reverse path has been supplied');
}
// Set rcpt to true, as per 4.1.1.3 of RFC 2821
$this->_send('RCPT TO:<' . $to . '>');
$this->_expect([250, 251], 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
$this->rcpt = true;
}
/**
* Issues DATA command
*
* @param string $data
* @throws Exception\RuntimeException
*/
public function data($data)
{
// Ensure recipients have been set
if ($this->rcpt !== true) { // Per RFC 2821 3.3 (page 18)
throw new Exception\RuntimeException('No recipient forward path has been supplied');
}
$this->_send('DATA');
$this->_expect(354, 120); // Timeout set for 2 minutes as per RFC 2821 4.5.3.2
$reader = self::chunkedReader($data);
foreach ($reader as $line) {
$line = rtrim($line, "\r\n");
if (isset($line[0]) && $line[0] === '.') {
// Escape lines prefixed with a '.'
$line = '.' . $line;
}
if (strlen($line) > self::SMTP_LINE_LIMIT) {
// Long lines are "folded" by inserting "<CR><LF><SPACE>"
// https://tools.ietf.org/html/rfc5322#section-2.2.3
// Add "-1" to stay within limits,
// because Headers::FOLDING includes a byte for space character after \r\n
$chunks = chunk_split($line, self::SMTP_LINE_LIMIT - 1, Headers::FOLDING);
$line = substr($chunks, 0, -strlen(Headers::FOLDING));
}
$this->_send($line);
}
$this->_send('.');
$this->_expect(250, 600); // Timeout set for 10 minutes as per RFC 2821 4.5.3.2
$this->data = true;
}
/**
* Issues the RSET command end validates answer
*
* Can be used to restore a clean smtp communication state when a
* transaction has been cancelled or commencing a new transaction.
*/
public function rset()
{
$this->_send('RSET');
// MS ESMTP doesn't follow RFC, see https://zendframework.com/issues/browse/ZF-1377
$this->_expect([250, 220]);
$this->mail = false;
$this->rcpt = false;
$this->data = false;
}
/**
* Issues the NOOP command end validates answer
*
* Not used by Laminas\Mail, could be used to keep a connection alive or check if it is still open.
*/
public function noop()
{
$this->_send('NOOP');
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
}
/**
* Issues the VRFY command end validates answer
*
* Not used by Laminas\Mail.
*
* @param string $user User Name or eMail to verify
*/
public function vrfy($user)
{
$this->_send('VRFY ' . $user);
$this->_expect([250, 251, 252], 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
}
/**
* Issues the QUIT command and clears the current session
*/
public function quit()
{
if ($this->sess) {
$this->auth = false;
if ($this->useCompleteQuit()) {
$this->_send('QUIT');
$this->_expect(221, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
}
$this->stopSession();
}
}
/**
* Default authentication method
*
* This default method is implemented by AUTH adapters to properly authenticate to a remote host.
*
* @throws Exception\RuntimeException
*/
public function auth()
{
if ($this->auth === true) {
throw new Exception\RuntimeException('Already authenticated for this session');
}
}
/**
* Closes connection
*/
public function disconnect()
{
$this->_disconnect();
}
/**
* Disconnect from remote host and free resource
*/
// @codingStandardsIgnoreLine PSR2.Methods.MethodDeclaration.Underscore
protected function _disconnect()
{
// Make sure the session gets closed
$this->quit();
parent::_disconnect();
}
/**
* Start mail session
*/
protected function startSession()
{
$this->sess = true;
}
/**
* Stop mail session
*/
protected function stopSession()
{
$this->sess = false;
}
}
laminas-mail/src/Protocol/Xoauth2/Xoauth2.php 0000644 00000001227 15240152655 0015104 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Mail\Protocol\Xoauth2;
use function base64_encode;
use function chr;
use function sprintf;
/**
* @internal
*/
final class Xoauth2
{
/**
* encodes accessToken and target mailbox to Xoauth2 SASL base64 encoded string
*/
public static function encodeXoauth2Sasl(string $targetMailbox, string $accessToken): string
{
return base64_encode(
sprintf(
"user=%s%sauth=Bearer %s%s%s",
$targetMailbox,
chr(0x01),
$accessToken,
chr(0x01),
chr(0x01)
)
);
}
}
laminas-mail/src/Protocol/Pop3/Response.php 0000644 00000001067 15240152655 0014641 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Mail\Protocol\Pop3;
/**
* POP3 response value object
*
* @internal
*/
final class Response
{
/** @var string $status */
private $status;
/** @var string $message */
private $message;
public function __construct(string $status, string $message)
{
$this->status = $status;
$this->message = $message;
}
public function status(): string
{
return $this->status;
}
public function message(): string
{
return $this->message;
}
}
laminas-mail/src/Protocol/Pop3/Xoauth2/Microsoft.php 0000644 00000001663 15240152656 0016345 0 ustar 00 <?php
namespace Laminas\Mail\Protocol\Pop3\Xoauth2;
use Laminas\Mail\Protocol\Exception\RuntimeException;
use Laminas\Mail\Protocol\Pop3;
use Laminas\Mail\Protocol\Xoauth2\Xoauth2;
/**
* @final
*/
class Microsoft extends Pop3
{
protected const AUTH_INITIALIZE_REQUEST = 'AUTH XOAUTH2';
protected const AUTH_RESPONSE_INITIALIZED_OK = '+';
/**
* @param string $user the target mailbox to access
* @param string $password OAUTH2 accessToken
* @param bool $tryApop obsolete parameter not used here
*/
public function login($user, $password, $tryApop = true): void
{
$this->sendRequest(self::AUTH_INITIALIZE_REQUEST);
$response = $this->readRemoteResponse();
if ($response->status() != self::AUTH_RESPONSE_INITIALIZED_OK) {
throw new RuntimeException($response->message());
}
$this->request(Xoauth2::encodeXoauth2Sasl($user, $password));
}
}
laminas-mail/src/Protocol/Smtp/Auth/Crammd5.php 0000644 00000006170 15240152656 0015337 0 ustar 00 <?php
namespace Laminas\Mail\Protocol\Smtp\Auth;
use Laminas\Crypt\Hmac;
use Laminas\Mail\Protocol\Smtp;
use function array_replace_recursive;
use function base64_decode;
use function base64_encode;
use function is_array;
/**
* Performs CRAM-MD5 authentication
*/
class Crammd5 extends Smtp
{
/** @var string */
protected $username;
/** @var string */
protected $password;
/**
* All parameters may be passed as an array to the first argument of the
* constructor. If so,
*
* @param string|array $host (Default: 127.0.0.1)
* @param null|int $port (Default: null)
* @param null|array $config Auth-specific parameters
*/
public function __construct($host = '127.0.0.1', $port = null, $config = null)
{
// Did we receive a configuration array?
$origConfig = $config;
if (is_array($host)) {
// Merge config array with principal array, if provided
if (is_array($config)) {
$config = array_replace_recursive($host, $config);
} else {
$config = $host;
}
}
if (is_array($config)) {
if (isset($config['username'])) {
$this->setUsername($config['username']);
}
if (isset($config['password'])) {
$this->setPassword($config['password']);
}
}
// Call parent with original arguments
parent::__construct($host, $port, $origConfig);
}
/**
* Performs CRAM-MD5 authentication with supplied credentials
*/
public function auth()
{
// Ensure AUTH has not already been initiated.
parent::auth();
$this->_send('AUTH CRAM-MD5');
$challenge = $this->_expect(334);
$challenge = base64_decode($challenge);
$digest = $this->hmacMd5($this->getPassword(), $challenge);
$this->_send(base64_encode($this->getUsername() . ' ' . $digest));
$this->_expect(235);
$this->auth = true;
}
/**
* Set value for username
*
* @param string $username
* @return Crammd5
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* @return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Set value for password
*
* @param string $password
* @return Crammd5
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* @return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Prepare CRAM-MD5 response to server's ticket
*
* @param string $key Challenge key (usually password)
* @param string $data Challenge data
* @param int $block Length of blocks (deprecated; unused)
* @return string
*/
protected function hmacMd5($key, $data, $block = 64)
{
return Hmac::compute($key, 'md5', $data);
}
}
laminas-mail/src/Protocol/Smtp/Auth/Login.php 0000644 00000005103 15240152656 0015112 0 ustar 00 <?php
namespace Laminas\Mail\Protocol\Smtp\Auth;
use Laminas\Mail\Protocol\Smtp;
use function array_replace_recursive;
use function base64_encode;
use function is_array;
/**
* Performs LOGIN authentication
*/
class Login extends Smtp
{
/**
* LOGIN username
*
* @var string
*/
protected $username;
/**
* LOGIN password
*
* @var string
*/
protected $password;
/**
* @param string $host (Default: 127.0.0.1)
* @param int $port (Default: null)
* @param array $config Auth-specific parameters
*/
public function __construct($host = '127.0.0.1', $port = null, $config = null)
{
// Did we receive a configuration array?
$origConfig = $config;
if (is_array($host)) {
// Merge config array with principal array, if provided
if (is_array($config)) {
$config = array_replace_recursive($host, $config);
} else {
$config = $host;
}
}
if (is_array($config)) {
if (isset($config['username'])) {
$this->setUsername($config['username']);
}
if (isset($config['password'])) {
$this->setPassword($config['password']);
}
}
// Call parent with original arguments
parent::__construct($host, $port, $origConfig);
}
/**
* Perform LOGIN authentication with supplied credentials
*/
public function auth()
{
// Ensure AUTH has not already been initiated.
parent::auth();
$this->_send('AUTH LOGIN');
$this->_expect(334);
$this->_send(base64_encode($this->getUsername()));
$this->_expect(334);
$this->_send(base64_encode($this->getPassword()));
$this->_expect(235);
$this->auth = true;
}
/**
* Set value for username
*
* @param string $username
* @return Login
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* @return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Set value for password
*
* @param string $password
* @return Login
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* @return string
*/
public function getPassword()
{
return $this->password;
}
}
laminas-mail/src/Protocol/Smtp/Auth/Plain.php 0000644 00000005020 15240152656 0015103 0 ustar 00 <?php
namespace Laminas\Mail\Protocol\Smtp\Auth;
use Laminas\Mail\Protocol\Smtp;
use function array_replace_recursive;
use function base64_encode;
use function is_array;
/**
* Performs PLAIN authentication
*/
class Plain extends Smtp
{
/**
* PLAIN username
*
* @var string
*/
protected $username;
/**
* PLAIN password
*
* @var string
*/
protected $password;
/**
* @param string $host (Default: 127.0.0.1)
* @param int $port (Default: null)
* @param array $config Auth-specific parameters
*/
public function __construct($host = '127.0.0.1', $port = null, $config = null)
{
// Did we receive a configuration array?
$origConfig = $config;
if (is_array($host)) {
// Merge config array with principal array, if provided
if (is_array($config)) {
$config = array_replace_recursive($host, $config);
} else {
$config = $host;
}
}
if (is_array($config)) {
if (isset($config['username'])) {
$this->setUsername($config['username']);
}
if (isset($config['password'])) {
$this->setPassword($config['password']);
}
}
// Call parent with original arguments
parent::__construct($host, $port, $origConfig);
}
/**
* Perform PLAIN authentication with supplied credentials
*/
public function auth()
{
// Ensure AUTH has not already been initiated.
parent::auth();
$this->_send('AUTH PLAIN');
$this->_expect(334);
$this->_send(base64_encode("\0" . $this->getUsername() . "\0" . $this->getPassword()));
$this->_expect(235);
$this->auth = true;
}
/**
* Set value for username
*
* @param string $username
* @return Plain
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* @return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Set value for password
*
* @param string $password
* @return Plain
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* @return string
*/
public function getPassword()
{
return $this->password;
}
}
laminas-mail/src/Transport/SmtpOptions.php 0000644 00000010662 15240152656 0014716 0 ustar 00 <?php
namespace Laminas\Mail\Transport;
use Laminas\Mail\Exception;
use Laminas\Mail\Exception\InvalidArgumentException;
use Laminas\Stdlib\AbstractOptions;
use function gettype;
use function is_object;
use function is_string;
use function sprintf;
class SmtpOptions extends AbstractOptions
{
/** @var string Local client hostname */
protected $name = 'localhost';
/** @var string */
protected $connectionClass = 'smtp';
/**
* Connection configuration (passed to the underlying Protocol class)
*
* @var array
*/
protected $connectionConfig = [];
/** @var string Remote SMTP hostname or IP */
protected $host = '127.0.0.1';
/** @var int */
protected $port = 25;
/**
* The timeout in seconds for the SMTP connection
* (Use null to disable it)
*
* @var int|null
*/
protected $connectionTimeLimit;
/**
* Return the local client hostname
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set the local client hostname or IP
*
* @todo hostname/IP validation
* @param string $name
* @throws InvalidArgumentException
* @return SmtpOptions
*/
public function setName($name)
{
if (! is_string($name) && $name !== null) {
throw new Exception\InvalidArgumentException(sprintf(
'Name must be a string or null; argument of type "%s" provided',
is_object($name) ? $name::class : gettype($name)
));
}
$this->name = $name;
return $this;
}
/**
* Get connection class
*
* This should be either the class Laminas\Mail\Protocol\Smtp or a class
* extending it -- typically a class in the Laminas\Mail\Protocol\Smtp\Auth
* namespace.
*
* @return string
*/
public function getConnectionClass()
{
return $this->connectionClass;
}
/**
* Set connection class
*
* @param string $connectionClass the value to be set
* @throws InvalidArgumentException
* @return SmtpOptions
*/
public function setConnectionClass($connectionClass)
{
if (! is_string($connectionClass) && $connectionClass !== null) {
throw new Exception\InvalidArgumentException(sprintf(
'Connection class must be a string or null; argument of type "%s" provided',
is_object($connectionClass) ? $connectionClass::class : gettype($connectionClass)
));
}
$this->connectionClass = $connectionClass;
return $this;
}
/**
* Get connection configuration array
*
* @return array
*/
public function getConnectionConfig()
{
return $this->connectionConfig;
}
/**
* Set connection configuration array
*
* @return SmtpOptions
*/
public function setConnectionConfig(array $connectionConfig)
{
$this->connectionConfig = $connectionConfig;
return $this;
}
/**
* Get the host name
*
* @return string
*/
public function getHost()
{
return $this->host;
}
/**
* Set the SMTP host
*
* @todo hostname/IP validation
* @param string $host
* @return SmtpOptions
*/
public function setHost($host)
{
$this->host = (string) $host;
return $this;
}
/**
* Get the port the SMTP server runs on
*
* @return int
*/
public function getPort()
{
return $this->port;
}
/**
* Set the port the SMTP server runs on
*
* @param int $port
* @throws InvalidArgumentException
* @return SmtpOptions
*/
public function setPort($port)
{
$port = (int) $port;
if ($port < 1) {
throw new Exception\InvalidArgumentException(sprintf(
'Port must be greater than 1; received "%d"',
$port
));
}
$this->port = $port;
return $this;
}
/**
* @return int|null
*/
public function getConnectionTimeLimit()
{
return $this->connectionTimeLimit;
}
/**
* @param int|null $seconds
* @return self
*/
public function setConnectionTimeLimit($seconds)
{
$this->connectionTimeLimit = $seconds === null
? null
: (int) $seconds;
return $this;
}
}
laminas-mail/src/Transport/File.php 0000644 00000003540 15240152657 0013274 0 ustar 00 <?php
namespace Laminas\Mail\Transport;
use Laminas\Mail\Message;
use function file_put_contents;
use function sprintf;
use const DIRECTORY_SEPARATOR;
/**
* File transport
*
* Class for saving outgoing emails in filesystem
*/
class File implements TransportInterface
{
/** @var FileOptions */
protected $options;
/**
* Last file written to
*
* @var string
*/
protected $lastFile;
/**
* Constructor
*
* @param null|FileOptions $options OPTIONAL (Default: null)
*/
public function __construct(?FileOptions $options = null)
{
if (! $options instanceof FileOptions) {
$options = new FileOptions();
}
$this->setOptions($options);
}
/**
* @return FileOptions
*/
public function getOptions()
{
return $this->options;
}
/**
* Sets options
*/
public function setOptions(FileOptions $options)
{
$this->options = $options;
}
/**
* Saves e-mail message to a file
*
* @throws Exception\RuntimeException On not writable target directory or on file_put_contents() failure.
*/
public function send(Message $message)
{
$options = $this->options;
$filename = $options->getCallback()($this);
$file = $options->getPath() . DIRECTORY_SEPARATOR . $filename;
$email = $message->toString();
if (false === file_put_contents($file, $email)) {
throw new Exception\RuntimeException(sprintf(
'Unable to write mail to file (directory "%s")',
$options->getPath()
));
}
$this->lastFile = $file;
}
/**
* Get the name of the last file written to
*
* @return string
*/
public function getLastFile()
{
return $this->lastFile;
}
}
laminas-mail/src/Transport/Factory.php 0000644 00000004650 15240152657 0014027 0 ustar 00 <?php
namespace Laminas\Mail\Transport;
use Laminas\Stdlib\ArrayUtils;
use Traversable;
use function class_exists;
use function gettype;
use function is_array;
use function is_object;
use function sprintf;
use function strtolower;
// phpcs:ignore WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix
abstract class Factory
{
/** @var array Known transport types */
protected static $classMap = [
'file' => File::class,
'inmemory' => InMemory::class,
'memory' => InMemory::class,
'null' => InMemory::class,
'sendmail' => Sendmail::class,
'smtp' => Smtp::class,
];
/**
* @param array $spec
* @return TransportInterface
* @throws Exception\InvalidArgumentException
* @throws Exception\DomainException
*/
public static function create($spec = [])
{
if ($spec instanceof Traversable) {
$spec = ArrayUtils::iteratorToArray($spec);
}
if (! is_array($spec)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects an array or Traversable argument; received "%s"',
__METHOD__,
is_object($spec) ? $spec::class : gettype($spec)
));
}
$type = $spec['type'] ?? 'sendmail';
$normalizedType = strtolower($type);
if (isset(static::$classMap[$normalizedType])) {
$type = static::$classMap[$normalizedType];
}
if (! class_exists($type)) {
throw new Exception\DomainException(sprintf(
'%s expects the "type" attribute to resolve to an existing class; received "%s"',
__METHOD__,
$type
));
}
$transport = new $type();
if (! $transport instanceof TransportInterface) {
throw new Exception\DomainException(sprintf(
'%s expects the "type" attribute to resolve to a valid %s instance; received "%s"',
__METHOD__,
TransportInterface::class,
$type
));
}
if ($transport instanceof Smtp && isset($spec['options'])) {
$transport->setOptions(new SmtpOptions($spec['options']));
}
if ($transport instanceof File && isset($spec['options'])) {
$transport->setOptions(new FileOptions($spec['options']));
}
return $transport;
}
}
laminas-mail/src/Transport/FileOptions.php 0000644 00000004362 15240152657 0014653 0 ustar 00 <?php
namespace Laminas\Mail\Transport;
use Laminas\Mail\Exception;
use Laminas\Mail\Exception\InvalidArgumentException;
use Laminas\Stdlib\AbstractOptions;
use function gettype;
use function is_callable;
use function is_dir;
use function is_object;
use function is_writable;
use function mt_rand;
use function sprintf;
use function sys_get_temp_dir;
use function time;
class FileOptions extends AbstractOptions
{
/** @var string Path to stored mail files */
protected $path;
/** @var callable */
protected $callback;
/**
* Set path to stored mail files
*
* @param string $path
* @throws InvalidArgumentException
* @return FileOptions
*/
public function setPath($path)
{
if (! is_dir($path) || ! is_writable($path)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a valid path in which to write mail files; received "%s"',
__METHOD__,
(string) $path
));
}
$this->path = $path;
return $this;
}
/**
* Get path
*
* If none is set, uses value from sys_get_temp_dir()
*
* @return string
*/
public function getPath()
{
if (null === $this->path) {
$this->setPath(sys_get_temp_dir());
}
return $this->path;
}
/**
* Set callback used to generate a file name
*
* @param callable $callback
* @throws InvalidArgumentException
* @return FileOptions
*/
public function setCallback($callback)
{
if (! is_callable($callback)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a valid callback; received "%s"',
__METHOD__,
is_object($callback) ? $callback::class : gettype($callback)
));
}
$this->callback = $callback;
return $this;
}
/**
* Get callback used to generate a file name
*
* @return callable
*/
public function getCallback()
{
if (null === $this->callback) {
$this->setCallback(static fn() => 'LaminasMail_' . time() . '_' . mt_rand() . '.eml');
}
return $this->callback;
}
}
laminas-mail/src/Transport/TransportInterface.php 0000644 00000000376 15240152657 0016236 0 ustar 00 <?php
namespace Laminas\Mail\Transport;
use Laminas\Mail;
/**
* Interface for mail transports
*/
interface TransportInterface
{
/**
* Send a mail message
*
* @return void
*/
public function send(Mail\Message $message);
}
laminas-mail/src/Transport/Envelope.php 0000644 00000001423 15240152657 0014170 0 ustar 00 <?php
namespace Laminas\Mail\Transport;
use Laminas\Stdlib\AbstractOptions;
class Envelope extends AbstractOptions
{
/** @var string|null */
protected $from;
/** @var string|null */
protected $to;
/**
* Get MAIL FROM
*
* @return string
*/
public function getFrom()
{
return $this->from;
}
/**
* Set MAIL FROM
*
* @param string $from
*/
public function setFrom($from)
{
$this->from = (string) $from;
}
/**
* Get RCPT TO
*
* @return string|null
*/
public function getTo()
{
return $this->to;
}
/**
* Set RCPT TO
*
* @param string $to
*/
public function setTo($to)
{
$this->to = $to;
}
}
laminas-mail/src/Transport/Exception/InvalidArgumentException.php 0000644 00000000356 15240152657 0021325 0 ustar 00 <?php
namespace Laminas\Mail\Transport\Exception;
use Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface
{
}
laminas-mail/src/Transport/Exception/ExceptionInterface.php 0000644 00000000254 15240152660 0020123 0 ustar 00 <?php
namespace Laminas\Mail\Transport\Exception;
use Laminas\Mail\Exception\ExceptionInterface as MailException;
interface ExceptionInterface extends MailException
{
}
laminas-mail/src/Transport/Exception/DomainException.php 0000644 00000000346 15240152660 0017434 0 ustar 00 <?php
namespace Laminas\Mail\Transport\Exception;
use Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail\Transport component.
*/
class DomainException extends Exception\DomainException implements ExceptionInterface
{
}
laminas-mail/src/Transport/Exception/RuntimeException.php 0000644 00000000336 15240152660 0017647 0 ustar 00 <?php
namespace Laminas\Mail\Transport\Exception;
use Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class RuntimeException extends Exception\RuntimeException implements ExceptionInterface
{
}
laminas-mail/src/Transport/Smtp.php 0000644 00000022552 15240152660 0013336 0 ustar 00 <?php
namespace Laminas\Mail\Transport;
use Laminas\Mail\Address;
use Laminas\Mail\Headers;
use Laminas\Mail\Message;
use Laminas\Mail\Protocol;
use Laminas\Mail\Protocol\Exception as ProtocolException;
use Laminas\ServiceManager\ServiceManager;
use function array_unique;
use function count;
use function sprintf;
use function time;
/**
* SMTP connection object
*
* Loads an instance of Laminas\Mail\Protocol\Smtp and forwards smtp transactions
*/
class Smtp implements TransportInterface
{
/** @var SmtpOptions */
protected $options;
/** @var Envelope|null */
protected $envelope;
/** @var null|Protocol\Smtp */
protected $connection;
/** @var bool */
protected $autoDisconnect = true;
/** @var Protocol\SmtpPluginManager */
protected $plugins;
/**
* When did we connect to the server?
*
* @var int|null
*/
protected $connectedTime;
/**
* @param SmtpOptions $options Optional
*/
public function __construct(?SmtpOptions $options = null)
{
if (! $options instanceof SmtpOptions) {
$options = new SmtpOptions();
}
$this->setOptions($options);
}
/**
* Set options
*
* @return Smtp
*/
public function setOptions(SmtpOptions $options)
{
$this->options = $options;
return $this;
}
/**
* Get options
*
* @return SmtpOptions
*/
public function getOptions()
{
return $this->options;
}
/**
* Set options
*/
public function setEnvelope(Envelope $envelope)
{
$this->envelope = $envelope;
}
/**
* Get envelope
*
* @return Envelope|null
*/
public function getEnvelope()
{
return $this->envelope;
}
/**
* Set plugin manager for obtaining SMTP protocol connection
*
* @throws Exception\InvalidArgumentException
* @return Smtp
*/
public function setPluginManager(Protocol\SmtpPluginManager $plugins)
{
$this->plugins = $plugins;
return $this;
}
/**
* Get plugin manager for loading SMTP protocol connection
*
* @return Protocol\SmtpPluginManager
*/
public function getPluginManager()
{
if (null === $this->plugins) {
$this->setPluginManager(new Protocol\SmtpPluginManager(new ServiceManager()));
}
return $this->plugins;
}
/**
* Set the automatic disconnection when destruct
*
* @param bool $flag
* @return Smtp
*/
public function setAutoDisconnect($flag)
{
$this->autoDisconnect = (bool) $flag;
return $this;
}
/**
* Get the automatic disconnection value
*
* @return bool
*/
public function getAutoDisconnect()
{
return $this->autoDisconnect;
}
/**
* Return an SMTP connection
*
* @param string $name
* @return Protocol\Smtp
*/
public function plugin($name, ?array $options = null)
{
return $this->getPluginManager()->get($name, $options);
}
/**
* Class destructor to ensure all open connections are closed
*/
public function __destruct()
{
$connection = $this->getConnection();
if (! $connection instanceof Protocol\Smtp) {
return;
}
try {
$connection->quit();
} catch (ProtocolException\ExceptionInterface) {
// ignore
}
if ($this->autoDisconnect) {
$connection->disconnect();
}
}
/**
* Sets the connection protocol instance
*/
public function setConnection(Protocol\AbstractProtocol $connection)
{
$this->connection = $connection;
if (
$connection instanceof Protocol\Smtp
&& ($this->getOptions()->getConnectionTimeLimit() !== null)
) {
$connection->setUseCompleteQuit(false);
}
}
/**
* Gets the connection protocol instance
*
* @return null|Protocol\Smtp
*/
public function getConnection()
{
$timeLimit = $this->getOptions()->getConnectionTimeLimit();
if (
$timeLimit !== null
&& $this->connectedTime !== null
&& ((time() - $this->connectedTime) > $timeLimit)
) {
$this->connection = null;
}
return $this->connection;
}
/**
* Disconnect the connection protocol instance
*
* @return void
*/
public function disconnect()
{
$connection = $this->getConnection();
if ($connection instanceof Protocol\Smtp) {
$connection->disconnect();
$this->connectedTime = null;
}
}
/**
* Send an email via the SMTP connection protocol
*
* The connection via the protocol adapter is made just-in-time to allow a
* developer to add a custom adapter if required before mail is sent.
*
* @throws Exception\RuntimeException
*/
public function send(Message $message)
{
// If sending multiple messages per session use existing adapter
$connection = $this->getConnection();
if (! $connection instanceof Protocol\Smtp || ! $connection->hasSession()) {
$connection = $this->connect();
} else {
// Reset connection to ensure reliable transaction
$connection->rset();
}
// Prepare message
$from = $this->prepareFromAddress($message);
$recipients = $this->prepareRecipients($message);
$headers = $this->prepareHeaders($message);
$body = $this->prepareBody($message);
if ((count($recipients) == 0) && (! empty($headers) || ! empty($body))) {
// Per RFC 2821 3.3 (page 18)
throw new Exception\RuntimeException(
sprintf(
'%s transport expects at least one recipient if the message has at least one header or body',
self::class
)
);
}
// Set sender email address
$connection->mail($from);
// Set recipient forward paths
foreach ($recipients as $recipient) {
$connection->rcpt($recipient);
}
// Issue DATA command to client
$connection->data($headers . Headers::EOL . $body);
}
/**
* Retrieve email address for envelope FROM
*
* @throws Exception\RuntimeException
* @return string
*/
protected function prepareFromAddress(Message $message)
{
if ($this->getEnvelope() && $this->getEnvelope()->getFrom()) {
return $this->getEnvelope()->getFrom();
}
$sender = $message->getSender();
if ($sender instanceof Address\AddressInterface) {
return $sender->getEmail();
}
$from = $message->getFrom();
if (! count($from)) {
// Per RFC 2822 3.6
throw new Exception\RuntimeException(sprintf(
'%s transport expects either a Sender or at least one From address in the Message; none provided',
self::class
));
}
$from->rewind();
$sender = $from->current();
return $sender->getEmail();
}
/**
* Prepare array of email address recipients
*
* @return array
*/
protected function prepareRecipients(Message $message)
{
if ($this->getEnvelope() && $this->getEnvelope()->getTo()) {
return (array) $this->getEnvelope()->getTo();
}
$recipients = [];
foreach ($message->getTo() as $address) {
$recipients[] = $address->getEmail();
}
foreach ($message->getCc() as $address) {
$recipients[] = $address->getEmail();
}
foreach ($message->getBcc() as $address) {
$recipients[] = $address->getEmail();
}
$recipients = array_unique($recipients);
return $recipients;
}
/**
* Prepare header string from message
*
* @return string
*/
protected function prepareHeaders(Message $message)
{
$headers = clone $message->getHeaders();
$headers->removeHeader('Bcc');
return $headers->toString();
}
/**
* Prepare body string from message
*
* @return string
*/
protected function prepareBody(Message $message)
{
return $message->getBodyText();
}
/**
* Lazy load the connection
*
* @return Protocol\Smtp
*/
protected function lazyLoadConnection()
{
// Check if authentication is required and determine required class
$options = $this->getOptions();
$config = $options->getConnectionConfig();
$config['host'] = $options->getHost();
$config['port'] = $options->getPort();
$this->setConnection($this->plugin($options->getConnectionClass(), $config));
return $this->connect();
}
/**
* Connect the connection, and pass it helo
*
* @return Protocol\Smtp
*/
protected function connect()
{
if (! $this->connection instanceof Protocol\Smtp) {
return $this->lazyLoadConnection();
}
$this->connection->connect();
$this->connectedTime = time();
$this->connection->helo($this->getOptions()->getName());
return $this->connection;
}
}
laminas-mail/src/Transport/InMemory.php 0000644 00000001276 15240152660 0014152 0 ustar 00 <?php
namespace Laminas\Mail\Transport;
use Laminas\Mail\Message;
/**
* InMemory transport
*
* This transport will just store the message in memory. It is helpful
* when unit testing, or to prevent sending email when in development or
* testing.
*/
class InMemory implements TransportInterface
{
/** @var null|Message */
protected $lastMessage;
/**
* Takes the last message and saves it for testing.
*/
public function send(Message $message)
{
$this->lastMessage = $message;
}
/**
* Get the last message sent.
*
* @return null|Message
*/
public function getLastMessage()
{
return $this->lastMessage;
}
}
laminas-mail/src/Transport/Sendmail.php 0000644 00000022521 15240152660 0014143 0 ustar 00 <?php
namespace Laminas\Mail\Transport;
use Laminas\Mail;
use Laminas\Mail\Address\AddressInterface;
use Laminas\Mail\Header\HeaderInterface;
use Laminas\Mail\Transport\Exception\InvalidArgumentException;
use Laminas\Mail\Transport\Exception\RuntimeException;
use Traversable;
use function count;
use function escapeshellarg;
use function gettype;
use function implode;
use function is_array;
use function is_callable;
use function is_object;
use function is_string;
use function mail;
use function preg_match;
use function restore_error_handler;
use function set_error_handler;
use function sprintf;
use function str_contains;
use function str_replace;
use function strtoupper;
use function substr;
use function trim;
use const PHP_OS;
use const PHP_VERSION_ID;
/**
* Class for sending email via the PHP internal mail() function
*/
class Sendmail implements TransportInterface
{
/**
* Config options for sendmail parameters
*
* @var string
*/
protected $parameters;
/**
* Callback to use when sending mail; typically, {@link mailHandler()}
*
* @var callable
*/
protected $callable;
/**
* error information
*
* @var string
*/
protected $errstr;
/** @var string */
protected $operatingSystem;
/**
* @param null|string|array|Traversable $parameters OPTIONAL (Default: null)
*/
public function __construct($parameters = null)
{
if ($parameters !== null) {
$this->setParameters($parameters);
}
$this->callable = [$this, 'mailHandler'];
}
/**
* Set sendmail parameters
*
* Used to populate the additional_parameters argument to mail()
*
* @param null|string|array|Traversable $parameters
* @throws InvalidArgumentException
* @return Sendmail
*/
public function setParameters($parameters)
{
if ($parameters === null || is_string($parameters)) {
$this->parameters = $parameters;
return $this;
}
if (! is_array($parameters) && ! $parameters instanceof Traversable) {
throw new InvalidArgumentException(sprintf(
'%s expects a string, array, or Traversable object of parameters; received "%s"',
__METHOD__,
is_object($parameters) ? $parameters::class : gettype($parameters)
));
}
$string = '';
foreach ($parameters as $param) {
$string .= ' ' . $param;
}
$this->parameters = trim($string);
return $this;
}
/**
* Set callback to use for mail
*
* Primarily for testing purposes, but could be used to curry arguments.
*
* @param callable $callable
* @throws InvalidArgumentException
* @return Sendmail
*/
public function setCallable($callable)
{
if (! is_callable($callable)) {
throw new InvalidArgumentException(sprintf(
'%s expects a callable argument; received "%s"',
__METHOD__,
is_object($callable) ? $callable::class : gettype($callable)
));
}
$this->callable = $callable;
return $this;
}
/**
* Send a message
*/
public function send(Mail\Message $message)
{
$to = $this->prepareRecipients($message);
$subject = $this->prepareSubject($message);
$body = $this->prepareBody($message);
$headers = $this->prepareHeaders($message);
$params = $this->prepareParameters($message);
// On *nix platforms, we need to replace \r\n with \n
// sendmail is not an SMTP server, it is a unix command - it expects LF
if (PHP_VERSION_ID < 80000 && ! $this->isWindowsOs()) {
$to = str_replace("\r\n", "\n", $to);
$subject = str_replace("\r\n", "\n", $subject);
$body = str_replace("\r\n", "\n", $body);
$headers = str_replace("\r\n", "\n", $headers);
}
($this->callable)($to, $subject, $body, $headers, $params);
}
/**
* Prepare recipients list
*
* @throws RuntimeException
* @return string
*/
protected function prepareRecipients(Mail\Message $message)
{
$headers = $message->getHeaders();
$hasTo = $headers->has('to');
if (! $hasTo && ! $headers->has('cc') && ! $headers->has('bcc')) {
throw new RuntimeException(
'Invalid email; contains no at least one of "To", "Cc", and "Bcc" header'
);
}
if (! $hasTo) {
return '';
}
/** @var Mail\Header\To $to */
$to = $headers->get('to');
$list = $to->getAddressList();
if (0 == count($list)) {
throw new RuntimeException('Invalid "To" header; contains no addresses');
}
// If not on Windows, return normal string
if (! $this->isWindowsOs()) {
return $to->getFieldValue(HeaderInterface::FORMAT_ENCODED);
}
// Otherwise, return list of emails
$addresses = [];
foreach ($list as $address) {
$addresses[] = $address->getEmail();
}
$addresses = implode(', ', $addresses);
return $addresses;
}
/**
* Prepare the subject line string
*
* @return string
*/
protected function prepareSubject(Mail\Message $message)
{
$headers = $message->getHeaders();
if (! $headers->has('subject')) {
return;
}
$header = $headers->get('subject');
return $header->getFieldValue(HeaderInterface::FORMAT_ENCODED);
}
/**
* Prepare the body string
*
* @return string
*/
protected function prepareBody(Mail\Message $message)
{
if (! $this->isWindowsOs()) {
// *nix platforms can simply return the body text
return $message->getBodyText();
}
// On windows, lines beginning with a full stop need to be fixed
$text = $message->getBodyText();
$text = str_replace("\n.", "\n..", $text);
return $text;
}
/**
* Prepare the textual representation of headers
*
* @return string
*/
protected function prepareHeaders(Mail\Message $message)
{
// Strip the "to" and "subject" headers
$headers = clone $message->getHeaders();
$headers->removeHeader('To');
$headers->removeHeader('Subject');
/** @var Mail\Header\From $from Sanitize the From header*/
$from = $headers->get('From');
if ($from) {
foreach ($from->getAddressList() as $address) {
if (str_contains($address->getEmail(), '\\"')) {
throw new RuntimeException('Potential code injection in From header');
}
}
}
return $headers->toString();
}
/**
* Prepare additional_parameters argument
*
* Basically, overrides the MAIL FROM envelope with either the Sender or
* From address.
*
* @return string
*/
protected function prepareParameters(Mail\Message $message)
{
if ($this->isWindowsOs()) {
return;
}
$parameters = (string) $this->parameters;
if (preg_match('/(^| )\-f.+/', $parameters)) {
return $parameters;
}
$sender = $message->getSender();
if ($sender instanceof AddressInterface) {
return $parameters . ' -f' . escapeshellarg($sender->getEmail());
}
$from = $message->getFrom();
if (count($from)) {
$from->rewind();
$sender = $from->current();
return $parameters . ' -f' . escapeshellarg($sender->getEmail());
}
return $parameters;
}
/**
* Send mail using PHP native mail()
*
* @param string $to
* @param string $subject
* @param string $message
* @param string $headers
* @param null|string $parameters
* @throws RuntimeException
*/
public function mailHandler($to, $subject, $message, $headers, $parameters)
{
set_error_handler([$this, 'handleMailErrors']);
if ($parameters === null) {
$result = mail($to, $subject, $message, $headers);
} else {
$result = mail($to, $subject, $message, $headers, $parameters);
}
restore_error_handler();
if ($this->errstr !== null || ! $result) {
$errstr = $this->errstr;
if (empty($errstr)) {
$errstr = 'Unknown error';
}
throw new RuntimeException('Unable to send mail: ' . $errstr);
}
}
/**
* Temporary error handler for PHP native mail().
*
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param string $errline
* @param array $errcontext
* @return bool always true
*/
public function handleMailErrors($errno, $errstr, $errfile = null, $errline = null, ?array $errcontext = null)
{
$this->errstr = $errstr;
return true;
}
/**
* Is this a windows OS?
*
* @return bool
*/
protected function isWindowsOs()
{
if (! $this->operatingSystem) {
$this->operatingSystem = strtoupper(substr(PHP_OS, 0, 3));
}
return $this->operatingSystem == 'WIN';
}
}
laminas-mail/src/ConfigProvider.php 0000644 00000001436 15240152660 0013335 0 ustar 00 <?php
namespace Laminas\Mail;
class ConfigProvider
{
/**
* Retrieve configuration for laminas-mail package.
*
* @return array
*/
public function __invoke()
{
return [
'dependencies' => $this->getDependencyConfig(),
];
}
/**
* Retrieve dependency settings for laminas-mail package.
*
* @return array
*/
public function getDependencyConfig()
{
return [
// Legacy Zend Framework aliases
'aliases' => [
'Zend\Mail\Protocol\SmtpPluginManager' => Protocol\SmtpPluginManager::class,
],
'factories' => [
Protocol\SmtpPluginManager::class => Protocol\SmtpPluginManagerFactory::class,
],
];
}
}
laminas-mail/src/Exception/InvalidArgumentException.php 0000644 00000000302 15240152660 0017312 0 ustar 00 <?php
namespace Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class InvalidArgumentException extends \InvalidArgumentException implements
ExceptionInterface
{
}
laminas-mail/src/Exception/ExceptionInterface.php 0000644 00000000155 15240152660 0016127 0 ustar 00 <?php
namespace Laminas\Mail\Exception;
use Throwable;
interface ExceptionInterface extends Throwable
{
}
laminas-mail/src/Exception/DomainException.php 0000644 00000000254 15240152660 0015436 0 ustar 00 <?php
namespace Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class DomainException extends \DomainException implements ExceptionInterface
{
}
laminas-mail/src/Exception/BadMethodCallException.php 0000644 00000000276 15240152660 0016656 0 ustar 00 <?php
namespace Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class BadMethodCallException extends \BadMethodCallException implements
ExceptionInterface
{
}
laminas-mail/src/Exception/OutOfBoundsException.php 0000644 00000000266 15240152660 0016441 0 ustar 00 <?php
namespace Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface
{
}
laminas-mail/src/Exception/RuntimeException.php 0000644 00000000256 15240152660 0015654 0 ustar 00 <?php
namespace Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
laminas-mail/src/Module.php 0000644 00000000536 15240152660 0011642 0 ustar 00 <?php
namespace Laminas\Mail;
class Module
{
/**
* Retrieve laminas-mail package configuration for laminas-mvc context.
*
* @return array
*/
public function getConfig()
{
$provider = new ConfigProvider();
return [
'service_manager' => $provider->getDependencyConfig(),
];
}
}
laminas-mail/src/MessageFactory.php 0000644 00000003056 15240152660 0013331 0 ustar 00 <?php
namespace Laminas\Mail;
use Traversable;
use function gettype;
use function is_array;
use function is_object;
use function method_exists;
use function sprintf;
use function str_replace;
use function strtr;
use function ucwords;
class MessageFactory
{
/**
* @param array|Traversable $options
* @return Message
*/
public static function getInstance($options = [])
{
if (! is_array($options) && ! $options instanceof Traversable) {
throw new Exception\InvalidArgumentException(sprintf(
'"%s" expects an array or Traversable; received "%s"',
__METHOD__,
is_object($options) ? $options::class : gettype($options)
));
}
$message = new Message();
foreach ($options as $key => $value) {
$setter = self::getSetterMethod($key);
if (method_exists($message, $setter)) {
$message->{$setter}($value);
}
}
return $message;
}
/**
* Generate a setter method name based on a provided key.
*
* @param string $key
* @return string
*/
private static function getSetterMethod($key)
{
return 'set'
. str_replace(
' ',
'',
ucwords(
strtr(
$key,
[
'-' => ' ',
'_' => ' ',
]
)
)
);
}
}
laminas-mail/src/Storage.php 0000644 00000001035 15240152660 0012014 0 ustar 00 <?php
namespace Laminas\Mail;
class Storage
{
// maildir and IMAP flags, using IMAP names, where possible to be able to distinguish between IMAP
// system flags and other flags
public const FLAG_PASSED = 'Passed';
public const FLAG_SEEN = '\Seen';
public const FLAG_UNSEEN = '\Unseen';
public const FLAG_ANSWERED = '\Answered';
public const FLAG_FLAGGED = '\Flagged';
public const FLAG_DELETED = '\Deleted';
public const FLAG_DRAFT = '\Draft';
public const FLAG_RECENT = '\Recent';
}
laminas-mail/src/Address/AddressInterface.php 0000644 00000000617 15240152660 0015210 0 ustar 00 <?php
namespace Laminas\Mail\Address;
interface AddressInterface
{
/**
* Retrieve email
*
* @return string
*/
public function getEmail();
/**
* Retrieve name, if any
*
* @return null|string
*/
public function getName();
/**
* String representation of address
*
* @return string
*/
public function toString();
}
laminas-mail/src/Header/References.php 0000644 00000000334 15240152660 0013662 0 ustar 00 <?php
namespace Laminas\Mail\Header;
class References extends IdentificationField
{
/** @var string */
protected $fieldName = 'References';
/** @var string */
protected static $type = 'references';
}
laminas-mail/src/Header/Date.php 0000644 00000003316 15240152660 0012461 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use function strtolower;
/**
* @todo Add accessors for setting date from DateTime, Laminas\Date, or a string
*/
class Date implements HeaderInterface
{
/** @var string */
protected $value;
/**
* @param string $headerLine
* @return static
*/
public static function fromString($headerLine)
{
[$name, $value] = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'date') {
throw new Exception\InvalidArgumentException('Invalid header line for Date string');
}
return new static($value);
}
/**
* @param string $value
*/
public function __construct($value)
{
if (! HeaderValue::isValid($value)) {
throw new Exception\InvalidArgumentException('Invalid Date header value detected');
}
$this->value = $value;
}
/**
* @return string
*/
public function getFieldName()
{
return 'Date';
}
/**
* @inheritDoc
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
return $this->value;
}
/**
* @param string $encoding
* @return self
*/
public function setEncoding($encoding)
{
// This header must be always in US-ASCII
return $this;
}
/**
* @return string
*/
public function getEncoding()
{
return 'ASCII';
}
/**
* @return string
*/
public function toString()
{
return 'Date: ' . $this->getFieldValue();
}
}
laminas-mail/src/Header/ContentDisposition.php 0000644 00000022361 15240152660 0015444 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use Laminas\Mail\Headers;
use Laminas\Mime\Mime;
use function count;
use function explode;
use function gettype;
use function is_numeric;
use function mb_strlen;
use function mb_substr;
use function sprintf;
use function str_replace;
use function strlen;
use function strpos;
use function strtolower;
use function trim;
use function var_export;
class ContentDisposition implements UnstructuredInterface
{
/**
* 78 chars (RFC 2822) - (semicolon + space (Header::FOLDING))
*
* @var int
*/
public const MAX_PARAMETER_LENGTH = 76;
/** @var string */
protected $disposition = 'inline';
/**
* Header encoding
*
* @var string
*/
protected $encoding = 'ASCII';
/** @var array */
protected $parameters = [];
/**
* @inheritDoc
*/
public static function fromString($headerLine)
{
[$name, $value] = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'content-disposition') {
throw new Exception\InvalidArgumentException('Invalid header line for Content-Disposition string');
}
$value = str_replace(Headers::FOLDING, ' ', $value);
$parts = explode(';', $value, 2);
$header = new static();
$header->setDisposition($parts[0]);
if (isset($parts[1])) {
$values = ListParser::parse(trim($parts[1]), [';', '=']);
$length = count($values);
$continuedValues = [];
for ($i = 0; $i < $length; $i += 2) {
$value = $values[$i + 1];
$value = trim($value, "'\" \t\n\r\0\x0B");
$name = trim($values[$i], "'\" \t\n\r\0\x0B");
if (strpos($name, '*')) {
[$name, $count] = explode('*', $name);
// allow optional count:
// Content-Disposition: attachment; filename*=UTF-8''%64%61%61%6D%69%2D%6D%C3%B5%72%76%2E%6A%70%67
if ($count === "") {
$count = 0;
}
if (! is_numeric($count)) {
$type = gettype($count);
$value = var_export($count, true);
throw new Exception\InvalidArgumentException(sprintf(
"Invalid header line for Content-Disposition string"
. " - count expected to be numeric, got %s with value %s",
$type,
$value
));
}
if (! isset($continuedValues[$name])) {
$continuedValues[$name] = [];
}
$continuedValues[$name][$count] = $value;
} else {
$header->setParameter($name, $value);
}
}
foreach ($continuedValues as $name => $values) {
$value = '';
for ($i = 0, $iMax = count($values); $i < $iMax; $i++) {
if (! isset($values[$i])) {
throw new Exception\InvalidArgumentException(
'Invalid header line for Content-Disposition string - incomplete continuation'
. '; HeaderLine: ' . $headerLine
);
}
$value .= $values[$i];
}
$header->setParameter($name, $value);
}
}
return $header;
}
/**
* @inheritDoc
*/
public function getFieldName()
{
return 'Content-Disposition';
}
/**
* @inheritDoc
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
$result = $this->disposition;
if (empty($this->parameters)) {
return $result;
}
foreach ($this->parameters as $attribute => $value) {
$valueIsEncoded = false;
if (HeaderInterface::FORMAT_ENCODED === $format && ! Mime::isPrintable($value)) {
$value = $this->getEncodedValue($value);
$valueIsEncoded = true;
}
$line = sprintf('%s="%s"', $attribute, $value);
if (strlen($line) < self::MAX_PARAMETER_LENGTH) {
$lines = explode(Headers::FOLDING, $result);
if (count($lines) === 1) {
$existingLineLength = strlen('Content-Disposition: ' . $result);
} else {
$existingLineLength = 1 + strlen($lines[count($lines) - 1]);
}
if ((2 + $existingLineLength + strlen($line)) <= self::MAX_PARAMETER_LENGTH) {
$result .= '; ' . $line;
} else {
$result .= ';' . Headers::FOLDING . $line;
}
} else {
// Use 'continuation' per RFC 2231
if ($valueIsEncoded) {
$value = HeaderWrap::mimeDecodeValue($value);
}
$i = 0;
$fullLength = mb_strlen($value, 'UTF-8');
while ($fullLength > 0) {
$attributePart = $attribute . '*' . $i++ . '="';
$attLen = mb_strlen($attributePart, 'UTF-8');
$subPos = 1;
$valuePart = '';
while ($subPos <= $fullLength) {
$sub = mb_substr($value, 0, $subPos, 'UTF-8');
if ($valueIsEncoded) {
$sub = $this->getEncodedValue($sub);
}
if ($attLen + mb_strlen($sub, 'UTF-8') >= self::MAX_PARAMETER_LENGTH) {
$subPos--;
break;
}
$subPos++;
$valuePart = $sub;
}
$value = mb_substr($value, $subPos, null, 'UTF-8');
$fullLength = mb_strlen($value, 'UTF-8');
$result .= ';' . Headers::FOLDING . $attributePart . $valuePart . '"';
}
}
}
return $result;
}
/**
* @param string $value
* @return string
*/
protected function getEncodedValue($value)
{
$configuredEncoding = $this->encoding;
$this->encoding = 'UTF-8';
$value = HeaderWrap::wrap($value, $this);
$this->encoding = $configuredEncoding;
return $value;
}
/**
* @inheritDoc
*/
public function setEncoding($encoding)
{
$this->encoding = $encoding;
return $this;
}
/**
* @inheritDoc
*/
public function getEncoding()
{
return $this->encoding;
}
/**
* @inheritDoc
*/
public function toString()
{
return 'Content-Disposition: ' . $this->getFieldValue(HeaderInterface::FORMAT_ENCODED);
}
/**
* Set the content disposition
* Expected values include 'inline', 'attachment'
*
* @param string $disposition
* @return ContentDisposition
*/
public function setDisposition($disposition)
{
$this->disposition = strtolower($disposition);
return $this;
}
/**
* Retrieve the content disposition
*
* @return string
*/
public function getDisposition()
{
return $this->disposition;
}
/**
* Add a parameter pair
*
* @param string $name
* @param string $value
* @return ContentDisposition
*/
public function setParameter($name, $value)
{
$name = strtolower($name);
if (! HeaderValue::isValid($name)) {
throw new Exception\InvalidArgumentException(
'Invalid content-disposition parameter name detected'
);
}
// '5' here is for the quotes & equal sign in `name="value"`,
// and the space & semicolon for line folding
if ((strlen($name) + 5) >= self::MAX_PARAMETER_LENGTH) {
throw new Exception\InvalidArgumentException(
'Invalid content-disposition parameter name detected (too long)'
);
}
$this->parameters[$name] = $value;
return $this;
}
/**
* Get all parameters
*
* @return array
*/
public function getParameters()
{
return $this->parameters;
}
/**
* Get a parameter by name
*
* @param string $name
* @return null|string
*/
public function getParameter($name)
{
$name = strtolower($name);
if (isset($this->parameters[$name])) {
return $this->parameters[$name];
}
return null;
}
/**
* Remove a named parameter
*
* @param string $name
* @return bool
*/
public function removeParameter($name)
{
$name = strtolower($name);
if (isset($this->parameters[$name])) {
unset($this->parameters[$name]);
return true;
}
return false;
}
}
laminas-mail/src/Header/HeaderLocatorInterface.php 0000644 00000000622 15240152660 0016136 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Mail\Header;
/**
* Interface detailing how to resolve header names to classes.
*/
interface HeaderLocatorInterface
{
public function get(string $name, ?string $default = null): ?string;
public function has(string $name): bool;
public function add(string $name, string $class): void;
public function remove(string $name): void;
}
laminas-mail/src/Header/HeaderWrap.php 0000644 00000014071 15240152660 0013626 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use Laminas\Mail\Headers;
use Laminas\Mime\Mime;
use function array_reduce;
use function explode;
use function extension_loaded;
use function iconv_mime_decode;
use function iconv_mime_encode;
use function implode;
use function str_contains;
use function str_pad;
use function str_starts_with;
use function strlen;
use function strpos;
use function substr;
use function wordwrap;
use const ICONV_MIME_DECODE_CONTINUE_ON_ERROR;
/**
* Utility class used for creating wrapped or MIME-encoded versions of header
* values.
*/
// phpcs:ignore WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix
abstract class HeaderWrap
{
/**
* Wrap a long header line
*
* @param string $value
* @return string
*/
public static function wrap($value, HeaderInterface $header)
{
if ($header instanceof UnstructuredInterface) {
return static::wrapUnstructuredHeader($value, $header);
} elseif ($header instanceof StructuredInterface) {
return static::wrapStructuredHeader($value, $header);
}
return $value;
}
/**
* Wrap an unstructured header line
*
* Wrap at 78 characters or before, based on whitespace.
*
* @param string $value
* @return string
*/
protected static function wrapUnstructuredHeader($value, HeaderInterface $header)
{
$headerNameColonSize = strlen($header->getFieldName() . ': ');
$encoding = $header->getEncoding();
if ($encoding == 'ASCII') {
/*
* Before folding the header line, it is necessary to calculate the length of the
* entire header (including the name and colon). We need to put a stub at the
* beginning of the value so that the folding is performed correctly.
*/
$headerLine = str_pad('0', $headerNameColonSize, '0') . $value;
$foldedHeaderLine = wordwrap($headerLine, 78, Headers::FOLDING);
// Remove the stub and return the header folded value.
return substr($foldedHeaderLine, $headerNameColonSize);
}
return static::mimeEncodeValue($value, $encoding, 78, $headerNameColonSize);
}
/**
* Wrap a structured header line
*
* @param string $value
* @return string
*/
protected static function wrapStructuredHeader($value, StructuredInterface $header)
{
$delimiter = $header->getDelimiter();
$length = strlen($value);
$lines = [];
$temp = '';
for ($i = 0; $i < $length; $i++) {
$temp .= $value[$i];
if ($value[$i] == $delimiter) {
$lines[] = $temp;
$temp = '';
}
}
return implode(Headers::FOLDING, $lines);
}
/**
* MIME-encode a value
*
* Performs quoted-printable encoding on a value, setting maximum
* line-length to 998.
*
* @param string $value
* @param string $encoding
* @param int $lineLength Maximum line-length, by default 998
* @param positive-int|0 $firstLineGapSize When folding a line, it is necessary to calculate
* the length of the entire line (together with the
* header name). Therefore, you can specify the header
* name and colon length in this argument to fold the
* string properly.
* @return string Returns the mime encode value without the last line ending
*/
public static function mimeEncodeValue($value, $encoding, $lineLength = 998, $firstLineGapSize = 0)
{
return Mime::encodeQuotedPrintableHeader($value, $encoding, $lineLength, Headers::EOL, $firstLineGapSize);
}
/**
* MIME-decode a value
*
* Performs quoted-printable decoding on a value.
*
* @param string $value
* @return string Returns the mime encode value without the last line ending
*/
public static function mimeDecodeValue($value)
{
// unfold first, because iconv_mime_decode is discarding "\n" with no apparent reason
// making the resulting value no longer valid.
// see https://tools.ietf.org/html/rfc2822#section-2.2.3 about unfolding
$parts = explode(Headers::FOLDING, $value);
$value = implode(' ', $parts);
$decodedValue = iconv_mime_decode($value, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, 'UTF-8');
// imap (unlike iconv) can handle multibyte headers which are splitted across multiple line
if (self::isNotDecoded($value, $decodedValue) && extension_loaded('imap')) {
return array_reduce(
imap_mime_header_decode(imap_utf8($value)),
static fn($accumulator, $headerPart) => $accumulator . $headerPart->text,
''
);
}
return $decodedValue;
}
private static function isNotDecoded(string $originalValue, string $value): bool
{
return str_starts_with($value, '=?')
&& strlen($value) - 2 === strpos($value, '?=')
&& str_contains($originalValue, $value);
}
/**
* Test if is possible apply MIME-encoding
*
* @param string $value
* @return bool
*/
public static function canBeEncoded($value)
{
// avoid any wrapping by specifying line length long enough
// "test" -> 4
// "x-test: =?ISO-8859-1?B?dGVzdA==?=" -> 33
// 8 +2 +3 +3 -> 16
$charset = 'UTF-8';
$lineLength = strlen($value) * 4 + strlen($charset) + 16;
$preferences = [
'scheme' => 'Q',
'input-charset' => $charset,
'output-charset' => $charset,
'line-length' => $lineLength,
];
$encoded = iconv_mime_encode('x-test', $value, $preferences);
return false !== $encoded;
}
}
laminas-mail/src/Header/UnstructuredInterface.php 0000644 00000000231 15240152660 0016125 0 ustar 00 <?php
namespace Laminas\Mail\Header;
/**
* Marker interface for unstructured headers.
*/
interface UnstructuredInterface extends HeaderInterface
{
}
laminas-mail/src/Header/To.php 0000644 00000000302 15240152660 0012156 0 ustar 00 <?php
namespace Laminas\Mail\Header;
class To extends AbstractAddressList
{
/** @var string */
protected $fieldName = 'To';
/** @var string */
protected static $type = 'to';
}
laminas-mail/src/Header/Exception/InvalidArgumentException.php 0000644 00000000272 15240152660 0020510 0 ustar 00 <?php
namespace Laminas\Mail\Header\Exception;
use Laminas\Mail\Exception;
class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface
{
}
laminas-mail/src/Header/Exception/ExceptionInterface.php 0000644 00000000251 15240152660 0017314 0 ustar 00 <?php
namespace Laminas\Mail\Header\Exception;
use Laminas\Mail\Exception\ExceptionInterface as MailException;
interface ExceptionInterface extends MailException
{
}
laminas-mail/src/Header/Exception/BadMethodCallException.php 0000644 00000000266 15240152660 0020045 0 ustar 00 <?php
namespace Laminas\Mail\Header\Exception;
use Laminas\Mail\Exception;
class BadMethodCallException extends Exception\BadMethodCallException implements ExceptionInterface
{
}
laminas-mail/src/Header/Exception/RuntimeException.php 0000644 00000000252 15240152660 0017040 0 ustar 00 <?php
namespace Laminas\Mail\Header\Exception;
use Laminas\Mail\Exception;
class RuntimeException extends Exception\RuntimeException implements ExceptionInterface
{
}
laminas-mail/src/Header/MultipleHeadersInterface.php 0000644 00000000243 15240152660 0016510 0 ustar 00 <?php
namespace Laminas\Mail\Header;
interface MultipleHeadersInterface extends HeaderInterface
{
public function toStringMultipleHeaders(array $headers);
}
laminas-mail/src/Header/HeaderName.php 0000644 00000003027 15240152660 0013574 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use function ord;
use function strlen;
final class HeaderName
{
/**
* No public constructor.
*/
private function __construct()
{
}
/**
* Filter the header name according to RFC 2822
*
* @see http://www.rfc-base.org/txt/rfc-2822.txt (section 2.2)
*
* @param string $name
* @return string
*/
public static function filter($name)
{
$result = '';
$tot = strlen($name);
for ($i = 0; $i < $tot; $i += 1) {
$ord = ord($name[$i]);
if ($ord > 32 && $ord < 127 && $ord !== 58) {
$result .= $name[$i];
}
}
return $result;
}
/**
* Determine if the header name contains any invalid characters.
*
* @param string $name
* @return bool
*/
public static function isValid($name)
{
$tot = strlen($name);
for ($i = 0; $i < $tot; $i += 1) {
$ord = ord($name[$i]);
if ($ord < 33 || $ord > 126 || $ord === 58) {
return false;
}
}
return true;
}
/**
* Assert that the header name is valid.
*
* Raises an exception if invalid.
*
* @param string $name
* @throws Exception\RuntimeException
* @return void
*/
public static function assertValid($name)
{
if (! self::isValid($name)) {
throw new Exception\RuntimeException('Invalid header name detected');
}
}
}
laminas-mail/src/Header/Received.php 0000644 00000004704 15240152660 0013334 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use Laminas\Mail\Headers;
use function implode;
use function strtolower;
/**
* @todo Allow setting date from DateTime, Laminas\Date, or string
*/
class Received implements HeaderInterface, MultipleHeadersInterface
{
/** @var string */
protected $value;
/**
* @param string $headerLine
* @return static
*/
public static function fromString($headerLine)
{
[$name, $value] = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'received') {
throw new Exception\InvalidArgumentException('Invalid header line for Received string');
}
return new static($value);
}
/**
* @param string $value
*/
public function __construct($value = '')
{
if (! HeaderValue::isValid($value)) {
throw new Exception\InvalidArgumentException('Invalid Received value provided');
}
$this->value = $value;
}
/**
* @return string
*/
public function getFieldName()
{
return 'Received';
}
/**
* @inheritDoc
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
return $this->value;
}
/**
* @param string $encoding
* @return self
*/
public function setEncoding($encoding)
{
// This header must be always in US-ASCII
return $this;
}
/**
* @return string
*/
public function getEncoding()
{
return 'ASCII';
}
/**
* @return string
*/
public function toString()
{
return 'Received: ' . $this->getFieldValue();
}
/**
* Serialize collection of Received headers to string
*
* @param array $headers
* @throws Exception\RuntimeException
* @return string
*/
public function toStringMultipleHeaders(array $headers)
{
$strings = [$this->toString()];
foreach ($headers as $header) {
if (! $header instanceof self) {
throw new Exception\RuntimeException(
'The Received multiple header implementation can only accept an array of Received headers'
);
}
$strings[] = $header->toString();
}
return implode(Headers::EOL, $strings);
}
}
laminas-mail/src/Header/ListParser.php 0000644 00000005501 15240152660 0013672 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use function in_array;
use function strlen;
/**
* @internal
*/
class ListParser
{
public const CHAR_QUOTES = ['\'', '"'];
public const CHAR_DELIMS = [',', ';'];
public const CHAR_ESCAPE = '\\';
/**
* @param string $value
* @param array $delims Delimiters allowed between values; parser will
* split on these, as long as they are not within quotes. Defaults
* to ListParser::CHAR_DELIMS.
* @return array
*/
public static function parse($value, array $delims = self::CHAR_DELIMS)
{
$values = [];
$length = strlen($value);
$currentValue = '';
$inEscape = false;
$inQuote = false;
$currentQuoteDelim = null;
for ($i = 0; $i < $length; $i += 1) {
$char = $value[$i];
// If we are in an escape sequence, append the character and continue.
if ($inEscape) {
$currentValue .= $char;
$inEscape = false;
continue;
}
// If we are not in a quoted string, and have a delimiter, append
// the current value to the list, and reset the current value.
if (in_array($char, $delims, true) && ! $inQuote) {
$values [] = $currentValue;
$currentValue = '';
continue;
}
// Append the character to the current value
$currentValue .= $char;
// Escape sequence discovered.
if (self::CHAR_ESCAPE === $char) {
$inEscape = true;
continue;
}
// If the character is not a quote character, we are done
// processing it.
if (! in_array($char, self::CHAR_QUOTES)) {
continue;
}
// If the character matches a previously matched quote delimiter,
// we reset our quote status and the currently opened quote
// delimiter.
if ($char === $currentQuoteDelim) {
$inQuote = false;
$currentQuoteDelim = null;
continue;
}
// If already in quote and the character does not match the previously
// matched quote delimiter, we're done here.
if ($inQuote) {
continue;
}
// Otherwise, we're starting a quoted string.
$inQuote = true;
$currentQuoteDelim = $char;
}
// If we reached the end of the string and still have a current value,
// append it to the list (no delimiter was reached).
if ('' !== $currentValue) {
$values [] = $currentValue;
}
return $values;
}
}
laminas-mail/src/Header/MimeVersion.php 0000644 00000004305 15240152660 0014040 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use function preg_match;
use function strtolower;
class MimeVersion implements HeaderInterface
{
/** @var string Version string */
protected $version = '1.0';
/**
* @param string $headerLine
* @return static
*/
public static function fromString($headerLine)
{
[$name, $value] = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'mime-version') {
throw new Exception\InvalidArgumentException('Invalid header line for MIME-Version string');
}
// Check for version, and set if found
$header = new static();
if (preg_match('/^(?P<version>\d+\.\d+)$/', $value, $matches)) {
$header->setVersion($matches['version']);
}
return $header;
}
/**
* @return string
*/
public function getFieldName()
{
return 'MIME-Version';
}
/**
* @inheritDoc
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
return $this->version;
}
/**
* @param string $encoding
* @return self
*/
public function setEncoding($encoding)
{
// This header must be always in US-ASCII
return $this;
}
/**
* @return string
*/
public function getEncoding()
{
return 'ASCII';
}
/**
* @return string
*/
public function toString()
{
return 'MIME-Version: ' . $this->getFieldValue();
}
/**
* Set the version string used in this header
*
* @param string $version
* @return MimeVersion
*/
public function setVersion($version)
{
if (! preg_match('/^[1-9]\d*\.\d+$/', $version)) {
throw new Exception\InvalidArgumentException('Invalid MIME-Version value detected');
}
$this->version = $version;
return $this;
}
/**
* Retrieve the version string for this header
*
* @return string
*/
public function getVersion()
{
return $this->version;
}
}
laminas-mail/src/Header/InReplyTo.php 0000644 00000000335 15240152660 0013467 0 ustar 00 <?php
namespace Laminas\Mail\Header;
class InReplyTo extends IdentificationField
{
/** @var string */
protected $fieldName = 'In-Reply-To';
/** @var string */
protected static $type = 'in-reply-to';
}
laminas-mail/src/Header/GenericHeader.php 0000644 00000012356 15240152660 0014275 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use Laminas\Mail\Header\Exception\InvalidArgumentException;
use Laminas\Mime\Mime;
use function count;
use function explode;
use function is_string;
use function ltrim;
use function str_replace;
use function strtoupper;
use function ucwords;
class GenericHeader implements HeaderInterface, UnstructuredInterface
{
/** @var string */
protected $fieldName;
/** @var string */
protected $fieldValue = '';
/**
* Header encoding
*
* @var null|string
*/
protected $encoding;
/**
* @param string $headerLine
* @return GenericHeader
*/
public static function fromString($headerLine)
{
[$name, $value] = self::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
return new static($name, $value);
}
/**
* Splits the header line in `name` and `value` parts.
*
* @param string $headerLine
* @return string[] `name` in the first index and `value` in the second.
* @throws InvalidArgumentException If header does not match with the format ``name:value``.
*/
public static function splitHeaderLine($headerLine)
{
$parts = explode(':', $headerLine, 2);
if (count($parts) !== 2) {
throw new InvalidArgumentException('Header must match with the format "name:value"');
}
if (! HeaderName::isValid($parts[0])) {
throw new InvalidArgumentException('Invalid header name detected');
}
if (! HeaderValue::isValid($parts[1])) {
throw new InvalidArgumentException('Invalid header value detected');
}
$parts[1] = ltrim($parts[1]);
return $parts;
}
/**
* Constructor
*
* @param string $fieldName Optional
* @param null|string $fieldValue Optional
*/
public function __construct($fieldName = null, $fieldValue = null)
{
if (! $fieldName) {
throw new InvalidArgumentException('Header MUST contain a field name');
}
$this->setFieldName($fieldName);
if ($fieldValue !== null) {
$this->setFieldValue($fieldValue);
}
}
/**
* Set header name
*
* @param string $fieldName
* @return GenericHeader
* @throws Exception\InvalidArgumentException;
*/
public function setFieldName($fieldName)
{
if (! is_string($fieldName) || empty($fieldName)) {
throw new InvalidArgumentException('Header name must be a string');
}
// Pre-filter to normalize valid characters, change underscore to dash
$fieldName = str_replace(' ', '-', ucwords(str_replace(['_', '-'], ' ', $fieldName)));
if (! HeaderName::isValid($fieldName)) {
throw new InvalidArgumentException(
'Header name must be composed of printable US-ASCII characters, except colon.'
);
}
$this->fieldName = $fieldName;
return $this;
}
/**
* @return string
*/
public function getFieldName()
{
return $this->fieldName;
}
/**
* Set header value
*
* @param string $fieldValue
* @return GenericHeader
* @throws Exception\InvalidArgumentException;
*/
public function setFieldValue($fieldValue)
{
$fieldValue = (string) $fieldValue;
if (! HeaderWrap::canBeEncoded($fieldValue)) {
throw new InvalidArgumentException(
'Header value must be composed of printable US-ASCII characters and valid folding sequences.'
);
}
$this->fieldValue = $fieldValue;
$this->encoding = null;
return $this;
}
/**
* @inheritDoc
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
if (HeaderInterface::FORMAT_ENCODED === $format) {
return HeaderWrap::wrap($this->fieldValue, $this);
}
return $this->fieldValue;
}
/**
* @param string $encoding
* @return self
*/
public function setEncoding($encoding)
{
if ($encoding === $this->encoding) {
return $this;
}
if ($encoding === null) {
$this->encoding = null;
return $this;
}
$encoding = strtoupper($encoding);
if ($encoding === 'UTF-8') {
$this->encoding = $encoding;
return $this;
}
if ($encoding === 'ASCII' && Mime::isPrintable($this->fieldValue)) {
$this->encoding = $encoding;
return $this;
}
$this->encoding = null;
return $this;
}
/**
* @return string
*/
public function getEncoding()
{
if (! $this->encoding) {
$this->encoding = Mime::isPrintable($this->fieldValue) ? 'ASCII' : 'UTF-8';
}
return $this->encoding;
}
/**
* @return string
*/
public function toString()
{
$name = $this->getFieldName();
if (empty($name)) {
throw new Exception\RuntimeException('Header name is not set, use setFieldName()');
}
$value = $this->getFieldValue(HeaderInterface::FORMAT_ENCODED);
return $name . ': ' . $value;
}
}
laminas-mail/src/Header/HeaderValue.php 0000644 00000005211 15240152660 0013765 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use function in_array;
use function ord;
use function strlen;
final class HeaderValue
{
/**
* No public constructor.
*/
private function __construct()
{
}
/**
* Filter the header value according to RFC 2822
*
* @see http://www.rfc-base.org/txt/rfc-2822.txt (section 2.2)
*
* @param string $value
* @return string
*/
public static function filter($value)
{
$result = '';
$total = strlen($value);
// Filter for CR and LF characters, leaving CRLF + WSP sequences for
// Long Header Fields (section 2.2.3 of RFC 2822)
for ($i = 0; $i < $total; $i += 1) {
$ord = ord($value[$i]);
if ($ord === 10 || $ord > 127) {
continue;
}
if ($ord === 13) {
if ($i + 2 >= $total) {
continue;
}
$lf = ord($value[$i + 1]);
$sp = ord($value[$i + 2]);
if ($lf !== 10 || $sp !== 32) {
continue;
}
$result .= "\r\n ";
$i += 2;
continue;
}
$result .= $value[$i];
}
return $result;
}
/**
* Determine if the header value contains any invalid characters.
*
* @see http://www.rfc-base.org/txt/rfc-2822.txt (section 2.2)
*
* @param string $value
* @return bool
*/
public static function isValid($value)
{
$total = strlen($value);
for ($i = 0; $i < $total; $i += 1) {
$ord = ord($value[$i]);
// bare LF means we aren't valid
if ($ord === 10 || $ord > 127) {
return false;
}
if ($ord === 13) {
if ($i + 2 >= $total) {
return false;
}
$lf = ord($value[$i + 1]);
$sp = ord($value[$i + 2]);
if ($lf !== 10 || ! in_array($sp, [9, 32], true)) {
return false;
}
// skip over the LF following this
$i += 2;
}
}
return true;
}
/**
* Assert that the header value is valid.
*
* Raises an exception if invalid.
*
* @param string $value
* @throws Exception\RuntimeException
* @return void
*/
public static function assertValid($value)
{
if (! self::isValid($value)) {
throw new Exception\RuntimeException('Invalid header value detected');
}
}
}
laminas-mail/src/Header/IdentificationField.php 0000644 00000006050 15240152661 0015500 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use Laminas\Mail\Headers;
use function array_map;
use function explode;
use function implode;
use function preg_match;
use function sprintf;
use function strtolower;
use function trim;
/**
* @see https://tools.ietf.org/html/rfc5322#section-3.6.4
*/
// phpcs:ignore WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix
abstract class IdentificationField implements HeaderInterface
{
/** @var string lower case field name */
protected static $type;
/** @var string[] */
protected $messageIds;
/** @var string */
protected $fieldName;
/**
* @param string $headerLine
* @return static
*/
public static function fromString($headerLine)
{
[$name, $value] = GenericHeader::splitHeaderLine($headerLine);
if (strtolower($name) !== static::$type) {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for "%s" string',
self::class
));
}
$value = HeaderWrap::mimeDecodeValue($value);
$messageIds = array_map(
[self::class, "trimMessageId"],
explode(" ", $value)
);
$header = new static();
$header->setIds($messageIds);
return $header;
}
/**
* @param string $id
* @return string
*/
private static function trimMessageId($id)
{
return trim($id, "\t\n\r\0\x0B<>");
}
/**
* @return string
*/
public function getFieldName()
{
return $this->fieldName;
}
/**
* @inheritDoc
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
return implode(Headers::FOLDING, array_map(static fn($id) => sprintf('<%s>', $id), $this->messageIds));
}
/**
* @param string $encoding Ignored; headers of this type MUST always be in
* ASCII.
* @return static This method is a no-op, and implements a fluent interface.
*/
public function setEncoding($encoding)
{
return $this;
}
/**
* @return string Always returns ASCII
*/
public function getEncoding()
{
return 'ASCII';
}
/**
* @return string
*/
public function toString()
{
return sprintf('%s: %s', $this->getFieldName(), $this->getFieldValue());
}
/**
* Set the message ids
*
* @param string[] $ids
* @return static This method implements a fluent interface.
*/
public function setIds($ids)
{
foreach ($ids as $id) {
if (
! HeaderValue::isValid($id)
|| preg_match("/[\r\n]/", $id)
) {
throw new Exception\InvalidArgumentException('Invalid ID detected');
}
}
$this->messageIds = array_map([self::class, "trimMessageId"], $ids);
return $this;
}
/**
* Retrieve the message ids
*
* @return string[]
*/
public function getIds()
{
return $this->messageIds;
}
}
laminas-mail/src/Header/Subject.php 0000644 00000005701 15240152661 0013204 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use Laminas\Mime\Mime;
use function strtolower;
use function strtoupper;
/**
* Subject header class methods.
*
* @see https://tools.ietf.org/html/rfc2822 RFC 2822
* @see https://tools.ietf.org/html/rfc2047 RFC 2047
*/
class Subject implements UnstructuredInterface
{
/** @var string */
protected $subject = '';
/**
* Header encoding
*
* @var null|string
*/
protected $encoding;
/**
* @param string $headerLine
* @return static
*/
public static function fromString($headerLine)
{
[$name, $value] = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'subject') {
throw new Exception\InvalidArgumentException('Invalid header line for Subject string');
}
$header = new static();
$header->setSubject($value);
return $header;
}
/**
* @return string
*/
public function getFieldName()
{
return 'Subject';
}
/**
* @inheritDoc
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
if (HeaderInterface::FORMAT_ENCODED === $format) {
return HeaderWrap::wrap($this->subject, $this);
}
return $this->subject;
}
/**
* @param string $encoding
* @return self
*/
public function setEncoding($encoding)
{
if ($encoding === $this->encoding) {
return $this;
}
if ($encoding === null) {
$this->encoding = null;
return $this;
}
$encoding = strtoupper($encoding);
if ($encoding === 'UTF-8') {
$this->encoding = $encoding;
return $this;
}
if ($encoding === 'ASCII' && Mime::isPrintable($this->subject)) {
$this->encoding = $encoding;
return $this;
}
$this->encoding = null;
return $this;
}
/**
* @return string
*/
public function getEncoding()
{
if (! $this->encoding) {
$this->encoding = Mime::isPrintable($this->subject) ? 'ASCII' : 'UTF-8';
}
return $this->encoding;
}
/**
* @param string $subject
* @return self
*/
public function setSubject($subject)
{
$subject = (string) $subject;
if (! HeaderWrap::canBeEncoded($subject)) {
throw new Exception\InvalidArgumentException(
'Subject value must be composed of printable US-ASCII or UTF-8 characters.'
);
}
$this->subject = $subject;
$this->encoding = null;
return $this;
}
/**
* @return string
*/
public function toString()
{
return 'Subject: ' . $this->getFieldValue(HeaderInterface::FORMAT_ENCODED);
}
}
laminas-mail/src/Header/Bcc.php 0000644 00000000306 15240152661 0012270 0 ustar 00 <?php
namespace Laminas\Mail\Header;
class Bcc extends AbstractAddressList
{
/** @var string */
protected $fieldName = 'Bcc';
/** @var string */
protected static $type = 'bcc';
}
laminas-mail/src/Header/From.php 0000644 00000000312 15240152661 0012501 0 ustar 00 <?php
namespace Laminas\Mail\Header;
class From extends AbstractAddressList
{
/** @var string */
protected $fieldName = 'From';
/** @var string */
protected static $type = 'from';
}
laminas-mail/src/Header/Sender.php 0000644 00000010656 15240152661 0013032 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use Laminas\Mail;
use Laminas\Mail\Address\AddressInterface;
use Laminas\Mime\Mime;
use function gettype;
use function is_object;
use function is_string;
use function preg_match;
use function sprintf;
use function strtolower;
use function trim;
/**
* Sender header class methods.
*
* @see https://tools.ietf.org/html/rfc2822 RFC 2822
* @see https://tools.ietf.org/html/rfc2047 RFC 2047
*/
class Sender implements HeaderInterface
{
/** @var AddressInterface */
protected $address;
/**
* Header encoding
*
* @var null|string
*/
protected $encoding;
/**
* @param string $headerLine
* @return static
*/
public static function fromString($headerLine)
{
[$name, $value] = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'sender') {
throw new Exception\InvalidArgumentException('Invalid header name for Sender string');
}
$header = new static();
/**
* matches the header value so that the email must be enclosed by < > when a name is present
* 'name' and 'email' capture groups correspond respectively to 'display-name' and 'addr-spec' in the ABNF
*
* @see https://tools.ietf.org/html/rfc5322#section-3.4
*/
$hasMatches = preg_match(
'/^(?:(?P<name>.+)\s)?(?(name)<|<?)(?P<email>[^\s]+?)(?(name)>|>?)$/',
$value,
$matches
);
if ($hasMatches !== 1) {
throw new Exception\InvalidArgumentException('Invalid header value for Sender string');
}
$senderName = trim($matches['name']);
if (empty($senderName)) {
$senderName = null;
}
$header->setAddress($matches['email'], $senderName);
return $header;
}
/**
* @return string
*/
public function getFieldName()
{
return 'Sender';
}
/**
* @inheritDoc
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
if (! $this->address instanceof Mail\Address\AddressInterface) {
return '';
}
$email = sprintf('<%s>', $this->address->getEmail());
$name = $this->address->getName();
if (! empty($name)) {
if ($format == HeaderInterface::FORMAT_ENCODED) {
$encoding = $this->getEncoding();
if ('ASCII' !== $encoding) {
$name = HeaderWrap::mimeEncodeValue($name, $encoding);
}
}
$email = sprintf('%s %s', $name, $email);
}
return $email;
}
/**
* @param string $encoding
* @return self
*/
public function setEncoding($encoding)
{
$this->encoding = $encoding;
return $this;
}
/**
* @return string
*/
public function getEncoding()
{
if (! $this->encoding) {
$this->encoding = Mime::isPrintable($this->getFieldValue(HeaderInterface::FORMAT_RAW))
? 'ASCII'
: 'UTF-8';
}
return $this->encoding;
}
/**
* @return string
*/
public function toString()
{
return 'Sender: ' . $this->getFieldValue(HeaderInterface::FORMAT_ENCODED);
}
/**
* Set the address used in this header
*
* @param string|AddressInterface $emailOrAddress
* @param null|string $name
* @throws Exception\InvalidArgumentException
* @return Sender
*/
public function setAddress($emailOrAddress, $name = null)
{
if (is_string($emailOrAddress)) {
$emailOrAddress = new Mail\Address($emailOrAddress, $name);
} elseif (! $emailOrAddress instanceof Mail\Address\AddressInterface) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a string or AddressInterface object; received "%s"',
__METHOD__,
is_object($emailOrAddress) ? $emailOrAddress::class : gettype($emailOrAddress)
));
}
$this->address = $emailOrAddress;
return $this;
}
/**
* Retrieve the internal address from this header
*
* @return AddressInterface|null
*/
public function getAddress()
{
return $this->address;
}
}
laminas-mail/src/Header/HeaderLoader.php 0000644 00000003403 15240152661 0014121 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use Laminas\Loader\PluginClassLoader;
/**
* Plugin Class Loader implementation for HTTP headers
*/
class HeaderLoader extends PluginClassLoader
{
/** @var array Pre-aliased Header plugins */
protected $plugins = [
'bcc' => Bcc::class,
'cc' => Cc::class,
'contentdisposition' => ContentDisposition::class,
'content_disposition' => ContentDisposition::class,
'content-disposition' => ContentDisposition::class,
'contenttype' => ContentType::class,
'content_type' => ContentType::class,
'content-type' => ContentType::class,
'contenttransferencoding' => ContentTransferEncoding::class,
'content_transfer_encoding' => ContentTransferEncoding::class,
'content-transfer-encoding' => ContentTransferEncoding::class,
'date' => Date::class,
'from' => From::class,
'in-reply-to' => InReplyTo::class,
'message-id' => MessageId::class,
'mimeversion' => MimeVersion::class,
'mime_version' => MimeVersion::class,
'mime-version' => MimeVersion::class,
'received' => Received::class,
'references' => References::class,
'replyto' => ReplyTo::class,
'reply_to' => ReplyTo::class,
'reply-to' => ReplyTo::class,
'sender' => Sender::class,
'subject' => Subject::class,
'to' => To::class,
];
}
laminas-mail/src/Header/AbstractAddressList.php 0000644 00000022034 15240152661 0015510 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use Laminas\Mail\Address;
use Laminas\Mail\AddressList;
use Laminas\Mail\Headers;
use Laminas\Mail\Storage\Exception\RuntimeException;
use function array_filter;
use function array_map;
use function assert;
use function idn_to_ascii;
use function implode;
use function is_array;
use function is_string;
use function preg_match;
use function preg_match_all;
use function preg_replace;
use function sprintf;
use function str_contains;
use function str_replace;
use function strtolower;
use function trim;
use const IDNA_DEFAULT;
use const IDNA_ERROR_BIDI;
use const IDNA_ERROR_CONTEXTJ;
use const IDNA_ERROR_DISALLOWED;
use const IDNA_ERROR_DOMAIN_NAME_TOO_LONG;
use const IDNA_ERROR_EMPTY_LABEL;
use const IDNA_ERROR_HYPHEN_3_4;
use const IDNA_ERROR_INVALID_ACE_LABEL;
use const IDNA_ERROR_LABEL_HAS_DOT;
use const IDNA_ERROR_LABEL_TOO_LONG;
use const IDNA_ERROR_LEADING_COMBINING_MARK;
use const IDNA_ERROR_LEADING_HYPHEN;
use const IDNA_ERROR_PUNYCODE;
use const IDNA_ERROR_TRAILING_HYPHEN;
use const INTL_IDNA_VARIANT_UTS46;
/**
* Base class for headers composing address lists (to, from, cc, bcc, reply-to)
*/
abstract class AbstractAddressList implements HeaderInterface
{
private const IDNA_ERROR_MAP = [
IDNA_ERROR_EMPTY_LABEL => 'empty label',
IDNA_ERROR_LABEL_TOO_LONG => 'label too long',
IDNA_ERROR_DOMAIN_NAME_TOO_LONG => 'domain name too long',
IDNA_ERROR_LEADING_HYPHEN => 'leading hyphen',
IDNA_ERROR_TRAILING_HYPHEN => 'trailing hyphen',
IDNA_ERROR_HYPHEN_3_4 => 'consecutive hyphens',
IDNA_ERROR_LEADING_COMBINING_MARK => 'leading combining mark',
IDNA_ERROR_DISALLOWED => 'disallowed',
IDNA_ERROR_PUNYCODE => 'invalid punycode encoding',
IDNA_ERROR_LABEL_HAS_DOT => 'has dot',
IDNA_ERROR_INVALID_ACE_LABEL => 'label not in ASCII encoding',
IDNA_ERROR_BIDI => 'fails bidirectional criteria',
IDNA_ERROR_CONTEXTJ => 'one or more characters fail CONTEXTJ rule',
];
/** @var AddressList */
protected $addressList;
/** @var string Normalized field name */
protected $fieldName;
/**
* Header encoding
*
* @var string
*/
protected $encoding = 'ASCII';
/** @var string lower case field name */
protected static $type;
/**
* @param string $headerLine
* @return static
*/
public static function fromString($headerLine)
{
[$fieldName, $fieldValue] = GenericHeader::splitHeaderLine($headerLine);
if (strtolower($fieldName) !== static::$type) {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for "%s" string',
self::class
));
}
// split value on ","
$fieldValue = str_replace(Headers::FOLDING, ' ', $fieldValue);
$fieldValue = preg_replace('/[^:]+:([^;]*);/', '$1,', $fieldValue);
$values = ListParser::parse($fieldValue);
$wasEncoded = false;
$addresses = array_map(
static function ($value) use (&$wasEncoded): ?Address {
$decodedValue = HeaderWrap::mimeDecodeValue($value);
$wasEncoded = $wasEncoded || ($decodedValue !== $value);
$value = trim($decodedValue);
$comments = self::getComments($value);
$value = self::stripComments($value);
$value = preg_replace(
[
'#(?<!\\\)"(.*)(?<!\\\)"#', // quoted-text
'#\\\([\x01-\x09\x0b\x0c\x0e-\x7f])#', // quoted-pair
],
[
'\\1',
'\\1',
],
$value
);
return empty($value) ? null : Address::fromString($value, $comments);
},
$values
);
$addresses = array_filter($addresses);
$header = new static();
if ($wasEncoded) {
$header->setEncoding('UTF-8');
}
/** @var AddressList $addressList */
$addressList = $header->getAddressList();
foreach ($addresses as $address) {
$addressList->add($address);
}
return $header;
}
/**
* @return string
*/
public function getFieldName()
{
return $this->fieldName;
}
/**
* Safely convert UTF-8 encoded domain name to ASCII
*
* @param string $domainName the UTF-8 encoded email
*/
protected function idnToAscii($domainName): string
{
/** @psalm-var string|false $ascii */
$ascii = idn_to_ascii($domainName, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46, $conversionInfo);
if (is_string($ascii)) {
return $ascii;
}
$messages = [];
assert(is_array($conversionInfo));
/* @psalm-var array{errors: numeric-string} $conversionInfo */
$errors = (int) $conversionInfo['errors'];
foreach (self::IDNA_ERROR_MAP as $flag => $message) {
if (($flag & $errors) === $flag) {
$messages[] = $message;
}
}
throw new RuntimeException(sprintf(
'Failed encoding domain due to errors: %s',
implode(', ', $messages)
));
}
/**
* @inheritDoc
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
$emails = [];
$encoding = $this->getEncoding();
foreach ($this->getAddressList() as $address) {
$email = $address->getEmail();
$name = $address->getName();
// quote $name if value requires so
if (! empty($name) && (str_contains($name, ',') || str_contains($name, ';'))) {
// FIXME: what if name contains double quote?
$name = sprintf('"%s"', $name);
}
if (
$format === HeaderInterface::FORMAT_ENCODED
&& 'ASCII' !== $encoding
) {
if (! empty($name)) {
$name = HeaderWrap::mimeEncodeValue($name, $encoding);
}
if (preg_match('/^(.+)@([^@]+)$/', $email, $matches)) {
$localPart = $matches[1];
$hostname = $this->idnToAscii($matches[2]);
$email = sprintf('%s@%s', $localPart, $hostname);
}
}
if (empty($name)) {
$emails[] = $email;
} else {
$emails[] = sprintf('%s <%s>', $name, $email);
}
}
// Ensure the values are valid before sending them.
if ($format !== HeaderInterface::FORMAT_RAW) {
foreach ($emails as $email) {
HeaderValue::assertValid($email);
}
}
return implode(',' . Headers::FOLDING, $emails);
}
/**
* @param string $encoding
* @return self
*/
public function setEncoding($encoding)
{
$this->encoding = $encoding;
return $this;
}
/**
* @return string
*/
public function getEncoding()
{
return $this->encoding;
}
/**
* Set address list for this header
*/
public function setAddressList(AddressList $addressList)
{
$this->addressList = $addressList;
}
/**
* Get address list managed by this header
*
* @return AddressList
*/
public function getAddressList()
{
if (null === $this->addressList) {
$this->setAddressList(new AddressList());
}
return $this->addressList;
}
/**
* @return string
*/
public function toString()
{
$name = $this->getFieldName();
$value = $this->getFieldValue(HeaderInterface::FORMAT_ENCODED);
return empty($value) ? '' : sprintf('%s: %s', $name, $value);
}
/**
* Retrieve comments from value, if any.
*
* Supposed to be private, protected as a workaround for PHP bug 68194
*
* @param string $value
* @return string
*/
protected static function getComments($value)
{
$matches = [];
preg_match_all(
'/\\(
(?P<comment>(
\\\\.|
[^\\\\)]
)+)
\\)/x',
$value,
$matches
);
return isset($matches['comment']) ? implode(', ', $matches['comment']) : '';
}
/**
* Strip all comments from value, if any.
*
* Supposed to be private, protected as a workaround for PHP bug 68194
*
* @param string $value
* @return string
*/
protected static function stripComments($value)
{
return preg_replace(
'/\\(
(
\\\\.|
[^\\\\)]
)+
\\)/x',
'',
$value
);
}
}
laminas-mail/src/Header/HeaderLocator.php 0000644 00000004671 15240152661 0014326 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Mail\Header;
use function strtolower;
/**
* Plugin Class Loader implementation for HTTP headers
*/
final class HeaderLocator implements HeaderLocatorInterface
{
/** @var array Pre-aliased Header plugins */
private array $plugins = [
'bcc' => Bcc::class,
'cc' => Cc::class,
'contentdisposition' => ContentDisposition::class,
'content_disposition' => ContentDisposition::class,
'content-disposition' => ContentDisposition::class,
'contenttype' => ContentType::class,
'content_type' => ContentType::class,
'content-type' => ContentType::class,
'contenttransferencoding' => ContentTransferEncoding::class,
'content_transfer_encoding' => ContentTransferEncoding::class,
'content-transfer-encoding' => ContentTransferEncoding::class,
'date' => Date::class,
'from' => From::class,
'in-reply-to' => InReplyTo::class,
'message-id' => MessageId::class,
'mimeversion' => MimeVersion::class,
'mime_version' => MimeVersion::class,
'mime-version' => MimeVersion::class,
'received' => Received::class,
'references' => References::class,
'replyto' => ReplyTo::class,
'reply_to' => ReplyTo::class,
'reply-to' => ReplyTo::class,
'sender' => Sender::class,
'subject' => Subject::class,
'to' => To::class,
];
public function get(string $name, ?string $default = null): ?string
{
$name = $this->normalizeName($name);
return $this->plugins[$name] ?? $default;
}
public function has(string $name): bool
{
return isset($this->plugins[$this->normalizeName($name)]);
}
public function add(string $name, string $class): void
{
$this->plugins[$this->normalizeName($name)] = $class;
}
public function remove(string $name): void
{
unset($this->plugins[$this->normalizeName($name)]);
}
private function normalizeName(string $name): string
{
return strtolower($name);
}
}
laminas-mail/src/Header/HeaderInterface.php 0000644 00000002722 15240152661 0014616 0 ustar 00 <?php
namespace Laminas\Mail\Header;
interface HeaderInterface
{
/**
* Format value in Mime-Encoding (Quoted-Printable). Result is valid US-ASCII string
*
* @var bool
*/
public const FORMAT_ENCODED = true;
/**
* Return value in internal encoding which is usually UTF-8
*
* @var bool
*/
public const FORMAT_RAW = false;
/**
* Factory to generate a header object from a string
*
* @see http://tools.ietf.org/html/rfc2822#section-2.2
*
* @param string $headerLine
* @return static
* @throws Exception\InvalidArgumentException If the header does not match with RFC 2822 definition.
*/
public static function fromString($headerLine);
/**
* Retrieve header name
*
* @return string
*/
public function getFieldName();
/**
* Retrieve header value
*
* @param HeaderInterface::FORMAT_* $format Return the value in Mime::Encoded or in Raw format
* @return string
*/
public function getFieldValue($format = self::FORMAT_RAW);
/**
* Set header encoding
*
* @param string $encoding
* @return $this
*/
public function setEncoding($encoding);
/**
* Get header encoding
*
* @return string
*/
public function getEncoding();
/**
* Cast to string
*
* Returns in form of "NAME: VALUE"
*
* @return string
*/
public function toString();
}
laminas-mail/src/Header/MessageId.php 0000644 00000005521 15240152661 0013446 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use function getmypid;
use function mt_rand;
use function php_uname;
use function preg_match;
use function sha1;
use function sprintf;
use function strtolower;
use function time;
use function trim;
class MessageId implements HeaderInterface
{
/** @var string */
protected $messageId;
/**
* @param string $headerLine
* @return static
*/
public static function fromString($headerLine)
{
[$name, $value] = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'message-id') {
throw new Exception\InvalidArgumentException('Invalid header line for Message-ID string');
}
$header = new static();
$header->setId($value);
return $header;
}
/**
* @return string
*/
public function getFieldName()
{
return 'Message-ID';
}
/**
* @inheritDoc
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
return $this->messageId;
}
/**
* @param string $encoding
* @return self
*/
public function setEncoding($encoding)
{
// This header must be always in US-ASCII
return $this;
}
/**
* @return string
*/
public function getEncoding()
{
return 'ASCII';
}
/**
* @return string
*/
public function toString()
{
return 'Message-ID: ' . $this->getFieldValue();
}
/**
* Set the message id
*
* @param string|null $id
* @return MessageId
*/
public function setId($id = null)
{
if ($id === null) {
$id = $this->createMessageId();
} else {
$id = trim($id, '<>');
}
if (
! HeaderValue::isValid($id)
|| preg_match("/[\r\n]/", $id)
) {
throw new Exception\InvalidArgumentException('Invalid ID detected');
}
$this->messageId = sprintf('<%s>', $id);
return $this;
}
/**
* Retrieve the message id
*
* @return string
*/
public function getId()
{
return $this->messageId;
}
/**
* Creates the Message-ID
*
* @return string
*/
public function createMessageId()
{
$time = time();
if (isset($_SERVER['REMOTE_ADDR'])) {
$user = $_SERVER['REMOTE_ADDR'];
} else {
$user = getmypid();
}
$rand = mt_rand();
if (isset($_SERVER["SERVER_NAME"])) {
$hostName = $_SERVER["SERVER_NAME"];
} else {
$hostName = php_uname('n');
}
return sha1($time . $user . $rand) . '@' . $hostName;
}
}
laminas-mail/src/Header/Cc.php 0000644 00000000304 15240152661 0012124 0 ustar 00 <?php
namespace Laminas\Mail\Header;
class Cc extends AbstractAddressList
{
/** @var string */
protected $fieldName = 'Cc';
/** @var string */
protected static $type = 'cc';
}
laminas-mail/src/Header/StructuredInterface.php 0000644 00000000367 15240152661 0015575 0 ustar 00 <?php
namespace Laminas\Mail\Header;
interface StructuredInterface extends HeaderInterface
{
/**
* Return the delimiter at which a header line should be wrapped
*
* @return string
*/
public function getDelimiter();
}
laminas-mail/src/Header/GenericMultiHeader.php 0000644 00000003270 15240152661 0015304 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use function explode;
use function implode;
use function strpos;
/**
* Generic class for Headers with multiple occurs in the same message
*/
class GenericMultiHeader extends GenericHeader implements MultipleHeadersInterface
{
/**
* @param string $headerLine
* @return array|GenericHeader|GenericMultiHeader|static
*/
public static function fromString($headerLine)
{
[$fieldName, $fieldValue] = GenericHeader::splitHeaderLine($headerLine);
$fieldValue = HeaderWrap::mimeDecodeValue($fieldValue);
if (strpos($fieldValue, ',')) {
$headers = [];
foreach (explode(',', $fieldValue) as $multiValue) {
$headers[] = new static($fieldName, $multiValue);
}
return $headers;
}
return new static($fieldName, $fieldValue);
}
/**
* Cast multiple header objects to a single string header
*
* @param array $headers
* @throws Exception\InvalidArgumentException
* @return string
*/
public function toStringMultipleHeaders(array $headers)
{
$name = $this->getFieldName();
$values = [$this->getFieldValue(HeaderInterface::FORMAT_ENCODED)];
foreach ($headers as $header) {
if (! $header instanceof static) {
throw new Exception\InvalidArgumentException(
'This method toStringMultipleHeaders was expecting an array of headers of the same type'
);
}
$values[] = $header->getFieldValue(HeaderInterface::FORMAT_ENCODED);
}
return $name . ': ' . implode(',', $values);
}
}
laminas-mail/src/Header/ContentTransferEncoding.php 0000644 00000005735 15240152661 0016402 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use function implode;
use function in_array;
use function sprintf;
use function strtolower;
class ContentTransferEncoding implements HeaderInterface
{
/**
* Allowed Content-Transfer-Encoding parameters specified by RFC 1521
* (reduced set)
*
* @var array
*/
protected static $allowedTransferEncodings = [
'7bit',
'8bit',
'quoted-printable',
'base64',
'binary',
/*
* not implemented:
* x-token: 'X-'
*/
];
/** @var string */
protected $transferEncoding;
/** @var array */
protected $parameters = [];
/**
* @param string $headerLine
* @return static
*/
public static function fromString($headerLine)
{
[$name, $value] = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'content-transfer-encoding') {
throw new Exception\InvalidArgumentException('Invalid header line for Content-Transfer-Encoding string');
}
$header = new static();
$header->setTransferEncoding($value);
return $header;
}
/**
* @return string
*/
public function getFieldName()
{
return 'Content-Transfer-Encoding';
}
/**
* @inheritDoc
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
return $this->transferEncoding;
}
/**
* @param string $encoding
* @return self
*/
public function setEncoding($encoding)
{
// Header must be always in US-ASCII
return $this;
}
/**
* @return string
*/
public function getEncoding()
{
return 'ASCII';
}
/**
* @return string
*/
public function toString()
{
return 'Content-Transfer-Encoding: ' . $this->getFieldValue();
}
/**
* Set the content transfer encoding
*
* @param string $transferEncoding
* @throws Exception\InvalidArgumentException
* @return $this
*/
public function setTransferEncoding($transferEncoding)
{
// Per RFC 1521, the value of the header is not case sensitive
$transferEncoding = strtolower($transferEncoding);
if (! in_array($transferEncoding, static::$allowedTransferEncodings)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects one of "' . implode(', ', static::$allowedTransferEncodings) . '"; received "%s"',
__METHOD__,
(string) $transferEncoding
));
}
$this->transferEncoding = $transferEncoding;
return $this;
}
/**
* Retrieve the content transfer encoding
*
* @return string
*/
public function getTransferEncoding()
{
return $this->transferEncoding;
}
}
laminas-mail/src/Header/ReplyTo.php 0000644 00000000325 15240152661 0013200 0 ustar 00 <?php
namespace Laminas\Mail\Header;
class ReplyTo extends AbstractAddressList
{
/** @var string */
protected $fieldName = 'Reply-To';
/** @var string */
protected static $type = 'reply-to';
}
laminas-mail/src/Header/ContentType.php 0000644 00000012354 15240152661 0014063 0 ustar 00 <?php
namespace Laminas\Mail\Header;
use Laminas\Mail\Headers;
use Laminas\Mime\Mime;
use function count;
use function explode;
use function implode;
use function preg_match;
use function sprintf;
use function str_replace;
use function strtolower;
use function trim;
class ContentType implements UnstructuredInterface
{
/** @var string */
protected $type;
/**
* Header encoding
*
* @var string
*/
protected $encoding = 'ASCII';
/** @var array */
protected $parameters = [];
/**
* @param string $headerLine
* @return static
*/
public static function fromString($headerLine)
{
[$name, $value] = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'content-type') {
throw new Exception\InvalidArgumentException('Invalid header line for Content-Type string');
}
$value = str_replace(Headers::FOLDING, ' ', $value);
$parts = explode(';', $value, 2);
$header = new static();
$header->setType($parts[0]);
if (isset($parts[1])) {
$values = ListParser::parse(trim($parts[1]), [';', '=']);
$length = count($values);
for ($i = 0; $i < $length; $i += 2) {
$value = $values[$i + 1];
$value = trim($value, "'\" \t\n\r\0\x0B");
$header->addParameter($values[$i], $value);
}
}
return $header;
}
/**
* @return string
*/
public function getFieldName()
{
return 'Content-Type';
}
/**
* @inheritDoc
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
$prepared = $this->type;
if (empty($this->parameters)) {
return $prepared;
}
$values = [$prepared];
foreach ($this->parameters as $attribute => $value) {
if (HeaderInterface::FORMAT_ENCODED === $format && ! Mime::isPrintable($value)) {
$this->encoding = 'UTF-8';
$value = HeaderWrap::wrap($value, $this);
$this->encoding = 'ASCII';
}
$values[] = sprintf('%s="%s"', $attribute, $value);
}
return implode(';' . Headers::FOLDING, $values);
}
/**
* @param string $encoding
* @return self
*/
public function setEncoding($encoding)
{
$this->encoding = $encoding;
return $this;
}
/**
* @return string
*/
public function getEncoding()
{
return $this->encoding;
}
/**
* @return string
*/
public function toString()
{
return 'Content-Type: ' . $this->getFieldValue(HeaderInterface::FORMAT_ENCODED);
}
/**
* Set the content type
*
* @param string $type
* @throws Exception\InvalidArgumentException
* @return ContentType
*/
public function setType($type)
{
if (! preg_match('/^[a-z-]+\/[a-z0-9.+-]+$/i', $type)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a value in the format "type/subtype"; received "%s"',
__METHOD__,
(string) $type
));
}
$this->type = $type;
return $this;
}
/**
* Retrieve the content type
*
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* Add a parameter pair
*
* @param string $name
* @param string $value
* @return ContentType
* @throws Exception\InvalidArgumentException For parameter names that do not follow RFC 2822.
* @throws Exception\InvalidArgumentException For parameter values that do not follow RFC 2822.
*/
public function addParameter($name, $value)
{
$name = trim(strtolower($name));
$value = (string) $value;
if (! HeaderValue::isValid($name)) {
throw new Exception\InvalidArgumentException('Invalid content-type parameter name detected');
}
if (! HeaderWrap::canBeEncoded($value)) {
throw new Exception\InvalidArgumentException(
'Parameter value must be composed of printable US-ASCII or UTF-8 characters.'
);
}
$this->parameters[$name] = $value;
return $this;
}
/**
* Get all parameters
*
* @return array
*/
public function getParameters()
{
return $this->parameters;
}
/**
* Get a parameter by name
*
* @param string $name
* @return null|string
*/
public function getParameter($name)
{
$name = strtolower($name);
if (isset($this->parameters[$name])) {
return $this->parameters[$name];
}
return null;
}
/**
* Remove a named parameter
*
* @param string $name
* @return bool
*/
public function removeParameter($name)
{
$name = strtolower($name);
if (isset($this->parameters[$name])) {
unset($this->parameters[$name]);
return true;
}
return false;
}
}
laminas-mail/src/Address.php 0000644 00000010645 15240152661 0012005 0 ustar 00 <?php
namespace Laminas\Mail;
use Laminas\Validator\EmailAddress as EmailAddressValidator;
use Laminas\Validator\Hostname;
use function array_shift;
use function is_string;
use function preg_match;
use function sprintf;
use function trim;
class Address implements Address\AddressInterface
{
/** @var null|string */
protected $comment;
/** @var string */
protected $email;
/** @var null|string */
protected $name;
/**
* Create an instance from a string value.
*
* Parses a string representing a single address. If it is a valid format,
* it then creates and returns an instance of itself using the name and
* email it has parsed from the value.
*
* @param string $address
* @param null|string $comment Comment associated with the address, if any.
* @throws Exception\InvalidArgumentException
* @return self
*/
public static function fromString($address, $comment = null)
{
if (! preg_match('/^((?P<name>.*)<(?P<namedEmail>[^>]+)>|(?P<email>.+))$/', $address, $matches)) {
throw new Exception\InvalidArgumentException('Invalid address format');
}
$name = null;
if (isset($matches['name'])) {
$name = trim($matches['name']);
}
if (empty($name)) {
$name = null;
}
if (isset($matches['namedEmail'])) {
$email = $matches['namedEmail'];
}
if (isset($matches['email'])) {
$email = $matches['email'];
}
$email = trim($email);
//trim single quotes, because outlook does add single quotes to emails sometimes which is technically not valid
$email = trim($email, '\'');
return new static($email, $name, $comment);
}
/**
* Constructor
*
* @param string $email
* @param null|string $name
* @param null|string $comment
* @throws Exception\InvalidArgumentException
*/
public function __construct($email, $name = null, $comment = null)
{
$emailAddressValidator = new EmailAddressValidator(Hostname::ALLOW_DNS | Hostname::ALLOW_LOCAL);
if (! is_string($email) || empty($email)) {
throw new Exception\InvalidArgumentException('Email must be a valid email address');
}
if (preg_match("/[\r\n]/", $email)) {
throw new Exception\InvalidArgumentException('CRLF injection detected');
}
if (! $emailAddressValidator->isValid($email)) {
$invalidMessages = $emailAddressValidator->getMessages();
throw new Exception\InvalidArgumentException(array_shift($invalidMessages));
}
if (null !== $name) {
if (! is_string($name)) {
throw new Exception\InvalidArgumentException('Name must be a string');
}
if (preg_match("/[\r\n]/", $name)) {
throw new Exception\InvalidArgumentException('CRLF injection detected');
}
$this->name = $name;
}
$this->email = $email;
if (null !== $comment) {
$this->comment = $comment;
}
}
/**
* Retrieve email
*
* @return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Retrieve name, if any
*
* @return null|string
*/
public function getName()
{
return $this->name;
}
/**
* Retrieve comment, if any
*
* @return null|string
*/
public function getComment()
{
return $this->comment;
}
/**
* String representation of address
*
* @return string
*/
public function toString()
{
$string = sprintf('<%s>', $this->getEmail());
$name = $this->constructName();
if (null === $name) {
return $string;
}
return sprintf('%s %s', $name, $string);
}
/**
* Constructs the name string
*
* If a comment is present, appends the comment (commented using parens) to
* the name before returning it; otherwise, returns just the name.
*
* @return null|string
*/
private function constructName()
{
$name = $this->getName();
$comment = $this->getComment();
if ($comment === null || $comment === '') {
return $name;
}
$string = sprintf('%s (%s)', $name, $comment);
return trim($string);
}
}
laminas-mail/src/AddressList.php 0000644 00000013564 15240152661 0012644 0 ustar 00 <?php
namespace Laminas\Mail;
use Countable;
use Iterator;
use ReturnTypeWillChange;
use function count;
use function current;
use function gettype;
use function is_int;
use function is_numeric;
use function is_object;
use function is_string;
use function key;
use function next;
use function reset;
use function sprintf;
use function strtolower;
use function var_export;
class AddressList implements Countable, Iterator
{
/**
* List of Address objects we're managing
*
* @var array
*/
protected $addresses = [];
/**
* Add an address to the list
*
* @param string|Address\AddressInterface $emailOrAddress
* @param null|string $name
* @throws Exception\InvalidArgumentException
* @return AddressList
*/
public function add($emailOrAddress, $name = null)
{
if (is_string($emailOrAddress)) {
$emailOrAddress = $this->createAddress($emailOrAddress, $name);
}
if (! $emailOrAddress instanceof Address\AddressInterface) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects an email address or %s\Address object as its first argument; received "%s"',
__METHOD__,
__NAMESPACE__,
is_object($emailOrAddress) ? $emailOrAddress::class : gettype($emailOrAddress)
));
}
$email = strtolower($emailOrAddress->getEmail());
if ($this->has($email)) {
return $this;
}
$this->addresses[$email] = $emailOrAddress;
return $this;
}
/**
* Add many addresses at once
*
* If an email key is provided, it will be used as the email, and the value
* as the name. Otherwise, the value is passed as the sole argument to add(),
* and, as such, can be either email strings or Address\AddressInterface objects.
*
* @param array $addresses
* @throws Exception\RuntimeException
* @return AddressList
*/
public function addMany(array $addresses)
{
foreach ($addresses as $key => $value) {
if (is_int($key) || is_numeric($key)) {
$this->add($value);
continue;
}
if (! is_string($key)) {
throw new Exception\RuntimeException(sprintf(
'Invalid key type in provided addresses array ("%s")',
is_object($key) ? $key::class : var_export($key, true)
));
}
$this->add($key, $value);
}
return $this;
}
/**
* Add an address to the list from any valid string format, such as
* - "Laminas Dev" <dev@laminas.com>
* - dev@laminas.com
*
* @param string $address
* @param null|string $comment Comment associated with the address, if any.
* @throws Exception\InvalidArgumentException
* @return AddressList
*/
public function addFromString($address, $comment = null)
{
$this->add(Address::fromString($address, $comment));
return $this;
}
/**
* Merge another address list into this one
*
* @return AddressList
*/
public function merge(self $addressList)
{
foreach ($addressList as $address) {
$this->add($address);
}
return $this;
}
/**
* Does the email exist in this list?
*
* @param string $email
* @return bool
*/
public function has($email)
{
$email = strtolower($email);
return isset($this->addresses[$email]);
}
/**
* Get an address by email
*
* @param string $email
* @return bool|Address\AddressInterface
*/
public function get($email)
{
$email = strtolower($email);
if (! isset($this->addresses[$email])) {
return false;
}
return $this->addresses[$email];
}
/**
* Delete an address from the list
*
* @param string $email
* @return bool
*/
public function delete($email)
{
$email = strtolower($email);
if (! isset($this->addresses[$email])) {
return false;
}
unset($this->addresses[$email]);
return true;
}
/**
* Return count of addresses
*
* @return int
*/
#[ReturnTypeWillChange]
public function count()
{
return count($this->addresses);
}
/**
* Rewind iterator
*
* @see addresses
*
* @return mixed the value of the first addresses element, or false if the addresses is
* empty.
*/
#[ReturnTypeWillChange]
public function rewind()
{
return reset($this->addresses);
}
/**
* Return current item in iteration
*
* @return Address
*/
#[ReturnTypeWillChange]
public function current()
{
return current($this->addresses);
}
/**
* Return key of current item of iteration
*
* @return string
*/
#[ReturnTypeWillChange]
public function key()
{
return key($this->addresses);
}
/**
* Move to next item
*
* @see addresses
*
* @return mixed the addresses value in the next place that's pointed to by the
* internal array pointer, or false if there are no more elements.
*/
#[ReturnTypeWillChange]
public function next()
{
return next($this->addresses);
}
/**
* Is the current item of iteration valid?
*
* @return bool
*/
#[ReturnTypeWillChange]
public function valid()
{
$key = key($this->addresses);
return $key !== null && $key !== false;
}
/**
* Create an address object
*
* @param string $email
* @param string|null $name
* @return Address
*/
protected function createAddress($email, $name)
{
return new Address($email, $name);
}
}
laminas-mail/src/Headers.php 0000644 00000043672 15240152661 0012001 0 ustar 00 <?php
declare(strict_types=1);
namespace Laminas\Mail;
use ArrayIterator;
use Countable;
use Iterator;
use Laminas\Loader\PluginClassLocator;
use Laminas\Mail\Header\GenericHeader;
use Laminas\Mail\Header\HeaderInterface;
use Laminas\Mail\Header\HeaderLocatorInterface;
use ReturnTypeWillChange;
use Traversable;
use function array_keys;
use function array_shift;
use function assert;
use function count;
use function current;
use function explode;
use function gettype;
use function in_array;
use function is_array;
use function is_int;
use function is_object;
use function is_string;
use function key;
use function next;
use function preg_match;
use function reset;
use function sprintf;
use function str_replace;
use function strtolower;
use function trigger_error;
use function trim;
use const E_USER_DEPRECATED;
/**
* Basic mail headers collection functionality
*
* Handles aggregation of headers
*/
class Headers implements Countable, Iterator
{
/** @var string End of Line for fields */
public const EOL = "\r\n";
/** @var string Start of Line when folding */
public const FOLDING = "\r\n ";
private ?HeaderLocatorInterface $headerLocator = null;
/**
* @todo Remove for 3.0.0.
* @var null|PluginClassLocator
*/
protected $pluginClassLoader;
/** @var array key names for $headers array */
protected $headersKeys = [];
/** @var HeaderInterface[] instances */
protected $headers = [];
/**
* Header encoding; defaults to ASCII
*
* @var string
*/
protected $encoding = 'ASCII';
/**
* Populates headers from string representation
*
* Parses a string for headers, and aggregates them, in order, in the
* current instance, primarily as strings until they are needed (they
* will be lazy loaded)
*
* @param string $string
* @param string $eol EOL string; defaults to {@link EOL}
* @return Headers
* @throws Exception\RuntimeException
*/
public static function fromString($string, $eol = self::EOL)
{
$headers = new static();
$currentLine = '';
$emptyLine = 0;
// iterate the header lines, some might be continuations
$lines = explode($eol, $string);
$total = count($lines);
for ($i = 0; $i < $total; $i += 1) {
$line = $lines[$i];
if ($line === "") {
// Empty line indicates end of headers
// EXCEPT if there are more lines, in which case, there's a possible error condition
$emptyLine += 1;
if ($emptyLine > 2) {
throw new Exception\RuntimeException('Malformed header detected');
}
continue;
} elseif (preg_match('/^\s*$/', $line)) {
// skip empty continuation line
continue;
}
if ($emptyLine > 1) {
throw new Exception\RuntimeException('Malformed header detected');
}
// check if a header name is present
if (preg_match('/^[\x21-\x39\x3B-\x7E]+:.*$/', $line)) {
if ($currentLine) {
// a header name was present, then store the current complete line
$headers->addHeaderLine($currentLine);
}
$currentLine = trim($line);
continue;
}
// continuation: append to current line
// recover the whitespace that break the line (unfolding, rfc2822#section-2.2.3)
if (preg_match('/^\s+.*$/', $line)) {
$currentLine .= ' ' . trim($line);
continue;
}
// Line does not match header format!
throw new Exception\RuntimeException(sprintf(
'Line "%s" does not match header format!',
$line
));
}
if ($currentLine) {
$headers->addHeaderLine($currentLine);
}
return $headers;
}
/**
* Set an alternate PluginClassLocator implementation for loading header classes.
*
* @deprecated since 2.12.0
*
* @todo Remove for version 3.0.0
* @return $this
*/
public function setPluginClassLoader(PluginClassLocator $pluginClassLoader)
{
// Silenced; can be caught in custom error handlers.
@trigger_error(sprintf(
'Since laminas/laminas-mail 2.12.0: Usage of %s is deprecated; use %s::setHeaderLocator() instead',
__METHOD__,
self::class
), E_USER_DEPRECATED);
$this->pluginClassLoader = $pluginClassLoader;
return $this;
}
/**
* Return a PluginClassLocator instance for customizing headers.
*
* Lazyloads a Header\HeaderLoader if necessary.
*
* @deprecated since 2.12.0
*
* @todo Remove for version 3.0.0
* @return PluginClassLocator
*/
public function getPluginClassLoader()
{
// Silenced; can be caught in custom error handlers.
@trigger_error(sprintf(
'Since laminas/laminas-mail 2.12.0: Usage of %s is deprecated; use %s::getHeaderLocator() instead',
__METHOD__,
self::class
), E_USER_DEPRECATED);
if (! $this->pluginClassLoader) {
$this->pluginClassLoader = new Header\HeaderLoader();
}
return $this->pluginClassLoader;
}
/**
* Retrieve the header class locator for customizing headers.
*
* Lazyloads a Header\HeaderLocator instance if necessary.
*/
public function getHeaderLocator(): HeaderLocatorInterface
{
if (! $this->headerLocator) {
$this->setHeaderLocator(new Header\HeaderLocator());
}
assert($this->headerLocator instanceof HeaderLocatorInterface);
return $this->headerLocator;
}
/**
* @todo Return self when we update to 7.4 or later as minimum PHP version.
* @return $this
*/
public function setHeaderLocator(HeaderLocatorInterface $headerLocator)
{
$this->headerLocator = $headerLocator;
return $this;
}
/**
* Set the header encoding
*
* @param string $encoding
* @return Headers
*/
public function setEncoding($encoding)
{
$this->encoding = $encoding;
foreach ($this as $header) {
$header->setEncoding($encoding);
}
return $this;
}
/**
* Get the header encoding
*
* @return string
*/
public function getEncoding()
{
return $this->encoding;
}
/**
* Add many headers at once
*
* Expects an array (or Traversable object) of type/value pairs.
*
* @param array|Traversable $headers
* @throws Exception\InvalidArgumentException
* @return Headers
*/
public function addHeaders($headers)
{
if (! is_array($headers) && ! $headers instanceof Traversable) {
throw new Exception\InvalidArgumentException(sprintf(
'Expected array or Traversable; received "%s"',
is_object($headers) ? $headers::class : gettype($headers)
));
}
foreach ($headers as $name => $value) {
if (is_int($name)) {
if (is_string($value)) {
$this->addHeaderLine($value);
} elseif (is_array($value) && count($value) == 1) {
$this->addHeaderLine(key($value), current($value));
} elseif (is_array($value) && count($value) == 2) {
$this->addHeaderLine($value[0], $value[1]);
} elseif ($value instanceof Header\HeaderInterface) {
$this->addHeader($value);
}
} elseif (is_string($name)) {
$this->addHeaderLine($name, $value);
}
}
return $this;
}
/**
* Add a raw header line, either in name => value, or as a single string 'name: value'
*
* This method allows for lazy-loading in that the parsing and instantiation of HeaderInterface object
* will be delayed until they are retrieved by either get() or current()
*
* @throws Exception\InvalidArgumentException
* @param string $headerFieldNameOrLine
* @param string $fieldValue optional
* @return Headers
*/
public function addHeaderLine($headerFieldNameOrLine, $fieldValue = null)
{
if (! is_string($headerFieldNameOrLine)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects its first argument to be a string; received "%s"',
__METHOD__,
is_object($headerFieldNameOrLine)
? $headerFieldNameOrLine::class
: gettype($headerFieldNameOrLine)
));
}
if ($fieldValue === null) {
$headers = $this->loadHeader($headerFieldNameOrLine);
$headers = is_array($headers) ? $headers : [$headers];
foreach ($headers as $header) {
$this->addHeader($header);
}
} elseif (is_array($fieldValue)) {
foreach ($fieldValue as $i) {
$this->addHeader(Header\GenericMultiHeader::fromString($headerFieldNameOrLine . ':' . $i));
}
} else {
$this->addHeader(GenericHeader::fromString($headerFieldNameOrLine . ':' . $fieldValue));
}
return $this;
}
/**
* Add a Header\Interface to this container, for raw values see {@link addHeaderLine()} and {@link addHeaders()}
*
* @return Headers
*/
public function addHeader(HeaderInterface $header)
{
$key = $this->normalizeFieldName($header->getFieldName());
$this->headersKeys[] = $key;
$this->headers[] = $header;
if ($this->getEncoding() !== 'ASCII') {
$header->setEncoding($this->getEncoding());
}
return $this;
}
/**
* Remove a Header from the container
*
* @param string|HeaderInterface $instanceOrFieldName field name or specific header instance to remove
* @return bool
*/
public function removeHeader($instanceOrFieldName)
{
if (! $instanceOrFieldName instanceof Header\HeaderInterface && ! is_string($instanceOrFieldName)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s requires a string or %s instance; received %s',
__METHOD__,
HeaderInterface::class,
is_object($instanceOrFieldName) ? $instanceOrFieldName::class : gettype($instanceOrFieldName)
));
}
if ($instanceOrFieldName instanceof Header\HeaderInterface) {
$indexes = array_keys($this->headers, $instanceOrFieldName, true);
}
if (is_string($instanceOrFieldName)) {
$key = $this->normalizeFieldName($instanceOrFieldName);
$indexes = array_keys($this->headersKeys, $key, true);
}
if (! empty($indexes)) {
foreach ($indexes as $index) {
unset($this->headersKeys[$index]);
unset($this->headers[$index]);
}
return true;
}
return false;
}
/**
* Clear all headers
*
* Removes all headers from queue
*
* @return Headers
*/
public function clearHeaders()
{
$this->headers = $this->headersKeys = [];
return $this;
}
/**
* Get all headers of a certain name/type
*
* @param string $name
* @return false|ArrayIterator|HeaderInterface Returns false if there is no headers with $name in this
* contain, an ArrayIterator if the header is a MultipleHeadersInterface instance and finally returns
* HeaderInterface for the rest of cases.
*/
public function get($name)
{
$key = $this->normalizeFieldName($name);
$results = [];
foreach (array_keys($this->headersKeys, $key, true) as $index) {
if ($this->headers[$index] instanceof Header\GenericHeader) {
$results[] = $this->lazyLoadHeader($index);
} else {
$results[] = $this->headers[$index];
}
}
switch (count($results)) {
case 0:
return false;
case 1:
if ($results[0] instanceof Header\MultipleHeadersInterface) {
return new ArrayIterator($results);
}
return $results[0];
default:
return new ArrayIterator($results);
}
}
/**
* Test for existence of a type of header
*
* @param string $name
* @return bool
*/
public function has($name)
{
$name = $this->normalizeFieldName($name);
return in_array($name, $this->headersKeys, true);
}
/**
* Advance the pointer for this object as an iterator
*/
#[ReturnTypeWillChange]
public function next()
{
next($this->headers);
}
/**
* Return the current key for this object as an iterator
*
* @return mixed
*/
#[ReturnTypeWillChange]
public function key()
{
return key($this->headers);
}
/**
* Is this iterator still valid?
*
* @return bool
*/
#[ReturnTypeWillChange]
public function valid()
{
return current($this->headers) !== false;
}
/**
* Reset the internal pointer for this object as an iterator
*/
#[ReturnTypeWillChange]
public function rewind()
{
reset($this->headers);
}
/**
* Return the current value for this iterator, lazy loading it if need be
*
* @return HeaderInterface
*/
#[ReturnTypeWillChange]
public function current()
{
$current = current($this->headers);
if ($current instanceof Header\GenericHeader) {
$current = $this->lazyLoadHeader(key($this->headers));
}
return $current;
}
/**
* Return the number of headers in this contain, if all headers have not been parsed, actual count could
* increase if MultipleHeader objects exist in the Request/Response. If you need an exact count, iterate
*
* @return int count of currently known headers
*/
#[ReturnTypeWillChange]
public function count()
{
return count($this->headers);
}
/**
* Render all headers at once
*
* This method handles the normal iteration of headers; it is up to the
* concrete classes to prepend with the appropriate status/request line.
*
* @return string
*/
public function toString()
{
$headers = '';
foreach ($this as $header) {
if ($str = $header->toString()) {
$headers .= $str . self::EOL;
}
}
return $headers;
}
/**
* Return the headers container as an array
*
* @param bool $format Return the values in Mime::Encoded or in Raw format
* @return array
* @todo determine how to produce single line headers, if they are supported
*/
public function toArray($format = HeaderInterface::FORMAT_RAW)
{
$headers = [];
foreach ($this->headers as $header) {
if ($header instanceof Header\MultipleHeadersInterface) {
$name = $header->getFieldName();
if (! isset($headers[$name])) {
$headers[$name] = [];
}
$headers[$name][] = $header->getFieldValue($format);
} else {
$headers[$header->getFieldName()] = $header->getFieldValue($format);
}
}
return $headers;
}
/**
* By calling this, it will force parsing and loading of all headers, after this count() will be accurate
*
* @return bool
*/
public function forceLoading()
{
// phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedForeach
foreach ($this as $item) {
// $item should now be loaded
}
return true;
}
/**
* Create Header object from header line
*
* @param string $headerLine
* @return HeaderInterface|HeaderInterface[]
*/
public function loadHeader($headerLine)
{
[$name] = GenericHeader::splitHeaderLine($headerLine);
/** @var HeaderInterface $class */
$class = $this->resolveHeaderClass($name);
return $class::fromString($headerLine);
}
/**
* @param array-key $index
* @return mixed
*/
protected function lazyLoadHeader($index)
{
$current = $this->headers[$index];
$key = $this->headersKeys[$index];
/** @var GenericHeader $class */
$class = $this->resolveHeaderClass($key);
$encoding = $current->getEncoding();
$headers = $class::fromString($current->toString());
if (is_array($headers)) {
$current = array_shift($headers);
$current->setEncoding($encoding);
$this->headers[$index] = $current;
foreach ($headers as $header) {
$header->setEncoding($encoding);
$this->headersKeys[] = $key;
$this->headers[] = $header;
}
return $current;
}
$current = $headers;
$current->setEncoding($encoding);
$this->headers[$index] = $current;
return $current;
}
/**
* Normalize a field name
*
* @param string $fieldName
* @return string
*/
protected function normalizeFieldName($fieldName)
{
return str_replace(['-', '_', ' ', '.'], '', strtolower($fieldName));
}
/**
* @param string $key
* @return null|string
*/
private function resolveHeaderClass($key)
{
if ($this->pluginClassLoader) {
return $this->pluginClassLoader->load($key) ?: GenericHeader::class;
}
return $this->getHeaderLocator()->get($key, GenericHeader::class);
}
}
laminas-mail/src/Storage/Part/File.php 0000644 00000011655 15240152661 0013613 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Part;
use Laminas\Mail\Headers;
use Laminas\Mail\Storage\Part;
use function count;
use function feof;
use function fgets;
use function fopen;
use function fread;
use function fseek;
use function ftell;
use function is_resource;
use function stream_copy_to_stream;
use function trim;
use const SEEK_END;
class File extends Part
{
/** @var array */
protected $contentPos = [];
/** @var array */
protected $partPos = [];
/** @var resource */
protected $fh;
/**
* Public constructor
*
* This handler supports the following params:
* - file filename or open file handler with message content (required)
* - startPos start position of message or part in file (default: current position)
* - endPos end position of message or part in file (default: end of file)
* - EOL end of Line for messages
*
* @param array $params full message with or without headers
* @throws Exception\RuntimeException
* @throws Exception\InvalidArgumentException
*/
public function __construct(array $params)
{
if (empty($params['file'])) {
throw new Exception\InvalidArgumentException('no file given in params');
}
if (! is_resource($params['file'])) {
$fh = fopen($params['file'], 'r');
} else {
$fh = $params['file'];
}
if (! $fh) {
throw new Exception\RuntimeException('could not open file');
}
$this->fh = $fh;
if (isset($params['startPos'])) {
fseek($this->fh, $params['startPos']);
}
$header = '';
$endPos = $params['endPos'] ?? null;
while (($endPos === null || ftell($this->fh) < $endPos) && trim($line = fgets($this->fh))) {
$header .= $line;
}
if (isset($params['EOL'])) {
$this->headers = Headers::fromString($header, $params['EOL']);
} else {
$this->headers = Headers::fromString($header);
}
$this->contentPos[0] = ftell($this->fh);
if ($endPos !== null) {
$this->contentPos[1] = $endPos;
} else {
fseek($this->fh, 0, SEEK_END);
$this->contentPos[1] = ftell($this->fh);
}
if (! $this->isMultipart()) {
return;
}
$boundary = $this->getHeaderField('content-type', 'boundary');
if (! $boundary) {
throw new Exception\RuntimeException('no boundary found in content type to split message');
}
$part = [];
$pos = $this->contentPos[0];
fseek($this->fh, $pos);
while (! feof($this->fh) && ($endPos === null || $pos < $endPos)) {
$line = fgets($this->fh);
if ($line === false) {
if (feof($this->fh)) {
break;
}
throw new Exception\RuntimeException('error reading file');
}
$lastPos = $pos;
$pos = ftell($this->fh);
$line = trim($line);
if ($line == '--' . $boundary) {
if ($part) {
// not first part
$part[1] = $lastPos;
$this->partPos[] = $part;
}
$part = [$pos];
} elseif ($line == '--' . $boundary . '--') {
$part[1] = $lastPos;
$this->partPos[] = $part;
break;
}
}
$this->countParts = count($this->partPos);
}
/**
* Body of part
*
* If part is multipart the raw content of this part with all sub parts is returned
*
* @param resource $stream Optional
* @return string body
*/
public function getContent($stream = null)
{
fseek($this->fh, $this->contentPos[0]);
if ($stream !== null) {
return stream_copy_to_stream($this->fh, $stream, $this->contentPos[1] - $this->contentPos[0]);
}
$length = $this->contentPos[1] - $this->contentPos[0];
return $length < 1 ? '' : fread($this->fh, $length);
}
/**
* Return size of part
*
* Quite simple implemented currently (not decoding). Handle with care.
*
* @return int size
*/
public function getSize()
{
return $this->contentPos[1] - $this->contentPos[0];
}
/**
* Get part of multipart message
*
* @param int $num number of part starting with 1 for first part
* @throws Exception\RuntimeException
* @return Part wanted part
*/
public function getPart($num)
{
--$num;
if (! isset($this->partPos[$num])) {
throw new Exception\RuntimeException('part not found');
}
return new static([
'file' => $this->fh,
'startPos' => $this->partPos[$num][0],
'endPos' => $this->partPos[$num][1],
]);
}
}
laminas-mail/src/Storage/Part/Exception/InvalidArgumentException.php 0000644 00000000371 15240152661 0021633 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Part\Exception;
use Laminas\Mail\Storage\Exception;
/**
* Exception for Laminas\Mail component.
*/
class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface
{
}
laminas-mail/src/Storage/Part/Exception/ExceptionInterface.php 0000644 00000000275 15240152661 0020445 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Part\Exception;
use Laminas\Mail\Storage\Exception\ExceptionInterface as StorageException;
interface ExceptionInterface extends StorageException
{
}
laminas-mail/src/Storage/Part/Exception/RuntimeException.php 0000644 00000000351 15240152661 0020163 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Part\Exception;
use Laminas\Mail\Storage\Exception;
/**
* Exception for Laminas\Mail component.
*/
class RuntimeException extends Exception\RuntimeException implements ExceptionInterface
{
}
laminas-mail/src/Storage/Part/PartInterface.php 0000644 00000006540 15240152661 0015460 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Part;
use ArrayIterator;
use Laminas\Mail\Header\HeaderInterface;
use Laminas\Mail\Headers;
use RecursiveIterator;
interface PartInterface extends RecursiveIterator
{
/**
* Check if part is a multipart message
*
* @return bool if part is multipart
*/
public function isMultipart();
/**
* Body of part
*
* If part is multipart the raw content of this part with all sub parts is
* returned.
*
* @return string body
* @throws Exception\ExceptionInterface
*/
public function getContent();
/**
* Return size of part
*
* @return int size
*/
public function getSize();
/**
* Get part of multipart message
*
* @param int $num number of part starting with 1 for first part
* @return PartInterface wanted part
* @throws Exception\ExceptionInterface
*/
public function getPart($num);
/**
* Count parts of a multipart part
*
* @return int number of sub-parts
*/
public function countParts();
/**
* Get all headers
*
* The returned headers are as saved internally. All names are lowercased.
* The value is a string or an array if a header with the same name occurs
* more than once.
*
* @return Headers
*/
public function getHeaders();
/**
* Get a header in specified format
*
* Internally headers that occur more than once are saved as array, all
* other as string. If $format is set to string implode is used to concat
* the values (with Laminas\Mime\Mime::LINEEND as delim).
*
* @param string $name name of header, matches case-insensitive, but
* camel-case is replaced with dashes
* @param string $format change type of return value to 'string' or 'array'
* @return string|array|HeaderInterface|ArrayIterator value of header in
* wanted or internal format
* @throws Exception\ExceptionInterface
*/
public function getHeader($name, $format = null);
/**
* Get a specific field from a header like content type or all fields as array
*
* If the header occurs more than once, only the value from the first
* header is returned.
*
* Throws an exception if the requested header does not exist. If the
* specific header field does not exist, returns null.
*
* @param string $name name of header, like in getHeader()
* @param string $wantedPart the wanted part, default is first, if null an
* array with all parts is returned
* @param string $firstName key name for the first part
* @return string|array wanted part or all parts as
* [$firstName => firstPart, partname => value]
* @throws Exception\ExceptionInterface
*/
public function getHeaderField($name, $wantedPart = '0', $firstName = '0');
/**
* Getter for mail headers - name is matched in lowercase
*
* This getter is short for PartInterface::getHeader($name, 'string')
*
* @see PartInterface::getHeader()
*
* @param string $name header name
* @return string value of header
* @throws Exception\ExceptionInterface
*/
public function __get($name);
/**
* magic method to get content of part
*
* @return string content
*/
public function __toString();
}
laminas-mail/src/Storage/Imap.php 0000644 00000042372 15240152661 0012714 0 ustar 00 <?php
namespace Laminas\Mail\Storage;
use Laminas\Mail;
use Laminas\Mail\Protocol;
use function array_key_exists;
use function array_pop;
use function array_push;
use function count;
use function in_array;
use function is_string;
use function ksort;
use function str_starts_with;
use function strrpos;
use function substr;
use const INF;
use const SORT_STRING;
class Imap extends AbstractStorage implements Folder\FolderInterface, Writable\WritableInterface
{
// TODO: with an internal cache we could optimize this class, or create an extra class with
// such optimizations. Especially the various fetch calls could be combined to one cache call
/**
* protocol handler
*
* @var null|Protocol\Imap
*/
protected $protocol;
/**
* name of current folder
*
* @var string
*/
protected $currentFolder = '';
/**
* IMAP folder delimiter character
*
* @var null|string
*/
protected $delimiter;
/**
* IMAP flags to constants translation
*
* @var array
*/
protected static $knownFlags = [
'\Passed' => Mail\Storage::FLAG_PASSED,
'\Answered' => Mail\Storage::FLAG_ANSWERED,
'\Seen' => Mail\Storage::FLAG_SEEN,
'\Unseen' => Mail\Storage::FLAG_UNSEEN,
'\Deleted' => Mail\Storage::FLAG_DELETED,
'\Draft' => Mail\Storage::FLAG_DRAFT,
'\Flagged' => Mail\Storage::FLAG_FLAGGED,
];
/**
* IMAP flags to search criteria
*
* @var array
*/
protected static $searchFlags = [
'\Recent' => 'RECENT',
'\Answered' => 'ANSWERED',
'\Seen' => 'SEEN',
'\Unseen' => 'UNSEEN',
'\Deleted' => 'DELETED',
'\Draft' => 'DRAFT',
'\Flagged' => 'FLAGGED',
];
/**
* Count messages all messages in current box
*
* @param null $flags
* @throws Exception\RuntimeException
* @throws Protocol\Exception\RuntimeException
* @return int number of messages
*/
public function countMessages($flags = null)
{
if (! $this->currentFolder) {
throw new Exception\RuntimeException('No selected folder to count');
}
if ($flags === null) {
return count($this->protocol->search(['ALL']));
}
$params = [];
foreach ((array) $flags as $flag) {
if (isset(static::$searchFlags[$flag])) {
$params[] = static::$searchFlags[$flag];
} else {
$params[] = 'KEYWORD';
$params[] = $this->protocol->escapeString($flag);
}
}
return count($this->protocol->search($params));
}
/**
* get a list of messages with number and size
*
* @param int $id number of message
* @return int|array size of given message of list with all messages as [num => size]
* @throws Protocol\Exception\RuntimeException
*/
public function getSize($id = 0)
{
if ($id) {
return $this->protocol->fetch('RFC822.SIZE', $id);
}
return $this->protocol->fetch('RFC822.SIZE', 1, INF);
}
/**
* Fetch a message
*
* @param int $id number of message
* @return Message
* @throws Protocol\Exception\RuntimeException
*/
public function getMessage($id)
{
$data = $this->protocol->fetch(['FLAGS', 'RFC822.HEADER'], $id);
$header = $data['RFC822.HEADER'];
$flags = [];
foreach ($data['FLAGS'] as $flag) {
$flags[] = static::$knownFlags[$flag] ?? $flag;
}
return new $this->messageClass(['handler' => $this, 'id' => $id, 'headers' => $header, 'flags' => $flags]);
}
/**
* Get raw header of message or part
*
* @param int $id number of message
* @param null|array|string $part path to part or null for message header
* @param int $topLines include this many lines with header (after an empty line)
* @return string raw header
* @throws Exception\RuntimeException
* @throws Protocol\Exception\RuntimeException
*/
public function getRawHeader($id, $part = null, $topLines = 0)
{
if ($part !== null) {
// TODO: implement
throw new Exception\RuntimeException('not implemented');
}
// TODO: toplines
return $this->protocol->fetch('RFC822.HEADER', $id);
}
/**
* Get raw content of message or part
*
* @param int $id number of message
* @param null|array|string $part path to part or null for message content
* @return string raw content
* @throws Protocol\Exception\RuntimeException
* @throws Exception\RuntimeException
*/
public function getRawContent($id, $part = null)
{
if ($part !== null) {
// TODO: implement
throw new Exception\RuntimeException('not implemented');
}
return $this->protocol->fetch('RFC822.TEXT', $id);
}
/**
* create instance with parameters
*
* Supported parameters are
*
* - user username
* - host hostname or ip address of IMAP server [optional, default = 'localhost']
* - password password for user 'username' [optional, default = '']
* - port port for IMAP server [optional, default = 110]
* - ssl 'SSL' or 'TLS' for secure sockets
* - folder select this folder [optional, default = 'INBOX']
*
* @param array|object|Protocol\Imap $params mail reader specific
* parameters or configured Imap protocol object
* @throws Exception\RuntimeException
* @throws Exception\InvalidArgumentException
* @throws Protocol\Exception\RuntimeException
*/
public function __construct($params)
{
$this->has['flags'] = true;
if ($params instanceof Protocol\Imap) {
$this->protocol = $params;
try {
$this->selectFolder('INBOX');
} catch (Exception\ExceptionInterface $e) {
throw new Exception\RuntimeException('cannot select INBOX, is this a valid transport?', 0, $e);
}
return;
}
$params = ParamsNormalizer::normalizeParams($params);
if (! isset($params['user'])) {
throw new Exception\InvalidArgumentException('need at least user in params');
}
$host = $params['host'] ?? 'localhost';
$password = $params['password'] ?? '';
$port = $params['port'] ?? null;
$ssl = $params['ssl'] ?? false;
$folder = $params['folder'] ?? 'INBOX';
if (null !== $port) {
$port = (int) $port;
}
if (! is_string($ssl)) {
$ssl = (bool) $ssl;
}
$this->protocol = new Protocol\Imap();
if (array_key_exists('novalidatecert', $params)) {
$this->protocol->setNoValidateCert((bool) $params['novalidatecert']);
}
$this->protocol->connect((string) $host, $port, $ssl);
if (! $this->protocol->login((string) $params['user'], (string) $password)) {
throw new Exception\RuntimeException('cannot login, user or password wrong');
}
$this->selectFolder((string) $folder);
}
/**
* Close resource for mail lib.
*
* If you need to control, when the resource is closed. Otherwise the
* destructor would call this.
*/
public function close()
{
$this->currentFolder = '';
$this->protocol->logout();
}
/**
* Keep the server busy.
*
* @throws Exception\RuntimeException
*/
public function noop()
{
if (! $this->protocol->noop()) {
throw new Exception\RuntimeException('could not do nothing');
}
}
/**
* Remove a message from server.
*
* If you're doing that from a web environment you should be careful and
* use a uniqueid as parameter if possible to identify the message.
*
* @param int $id number of message
* @throws Exception\RuntimeException
*/
public function removeMessage($id)
{
if (! $this->protocol->store([Mail\Storage::FLAG_DELETED], $id, null, '+')) {
throw new Exception\RuntimeException('cannot set deleted flag');
}
// TODO: expunge here or at close? we can handle an error here better and are more fail safe
if (! $this->protocol->expunge()) {
throw new Exception\RuntimeException('message marked as deleted, but could not expunge');
}
}
/**
* get unique id for one or all messages
*
* if storage does not support unique ids it's the same as the message
* number.
*
* @param int|null $id message number
* @return array|string message number for given message or all messages as array
* @throws Protocol\Exception\RuntimeException
*/
public function getUniqueId($id = null)
{
if ($id) {
return $this->protocol->fetch('UID', $id);
}
return $this->protocol->fetch('UID', 1, INF);
}
/**
* get a message number from a unique id
*
* I.e. if you have a webmailer that supports deleting messages you should
* use unique ids as parameter and use this method to translate it to
* message number right before calling removeMessage()
*
* @param string $id unique id
* @throws Exception\InvalidArgumentException
* @return int message number
*/
public function getNumberByUniqueId($id)
{
// TODO: use search to find number directly
$ids = $this->getUniqueId();
foreach ($ids as $k => $v) {
if ($v == $id) {
return $k;
}
}
throw new Exception\InvalidArgumentException('unique id not found');
}
/**
* get root folder or given folder
*
* @param string $rootFolder get folder structure for given folder, else root
* @throws Exception\RuntimeException
* @throws Exception\InvalidArgumentException
* @throws Protocol\Exception\RuntimeException
* @return Folder root or wanted folder
*/
public function getFolders($rootFolder = null)
{
$folders = $this->protocol->listMailbox((string) $rootFolder);
if (! $folders) {
throw new Exception\InvalidArgumentException('folder not found');
}
ksort($folders, SORT_STRING);
$root = new Folder('/', '/', false);
$stack = [null];
$folderStack = [null];
$parentFolder = $root;
$parent = '';
foreach ($folders as $globalName => $data) {
do {
if (! $parent || str_starts_with($globalName, ! is_string($parent) ? (string) $parent : $parent)) {
$pos = strrpos($globalName, (string) $data['delim']);
if ($pos === false) {
$localName = $globalName;
} else {
$localName = substr($globalName, $pos + 1);
}
$selectable = ! $data['flags'] || ! in_array('\\Noselect', $data['flags']);
array_push($stack, $parent);
$parent = $globalName . $data['delim'];
$folder = new Folder($localName, $globalName, $selectable);
$parentFolder->$localName = $folder;
array_push($folderStack, $parentFolder);
$parentFolder = $folder;
$this->delimiter = $data['delim'];
break;
} elseif ($stack) {
$parent = array_pop($stack);
$parentFolder = array_pop($folderStack);
}
} while ($stack);
if (! $stack) {
throw new Exception\RuntimeException('error while constructing folder tree');
}
}
return $root;
}
/**
* select given folder
*
* folder must be selectable!
*
* @param Folder|string $globalName global name of folder or instance for subfolder
* @throws Exception\RuntimeException
* @throws Protocol\Exception\RuntimeException
*/
public function selectFolder($globalName)
{
$this->currentFolder = (string) $globalName;
if (! $this->protocol->select($this->currentFolder)) {
$this->currentFolder = '';
throw new Exception\RuntimeException('cannot change folder, maybe it does not exist');
}
}
/**
* get Folder instance for current folder
*
* @return string instance of current folder
*/
public function getCurrentFolder()
{
return $this->currentFolder;
}
/**
* create a new folder
*
* This method also creates parent folders if necessary. Some mail storages
* may restrict, which folder may be used as parent or which chars may be
* used in the folder name
*
* @param string $name global name of folder, local name if $parentFolder
* is set
* @param string|Folder $parentFolder parent folder for new folder, else
* root folder is parent
* @throws Exception\RuntimeException
*/
public function createFolder($name, $parentFolder = null)
{
// TODO: we assume / as the hierarchy delim - need to get that from the folder class!
if ($parentFolder instanceof Folder) {
$folder = $parentFolder->getGlobalName() . '/' . $name;
} elseif ($parentFolder !== null) {
$folder = $parentFolder . '/' . $name;
} else {
$folder = $name;
}
if (! $this->protocol->create($folder)) {
throw new Exception\RuntimeException('cannot create folder');
}
}
/**
* remove a folder
*
* @param string|Folder $name name or instance of folder
* @throws Exception\RuntimeException
*/
public function removeFolder($name)
{
if ($name instanceof Folder) {
$name = $name->getGlobalName();
}
if (! $this->protocol->delete($name)) {
throw new Exception\RuntimeException('cannot delete folder');
}
}
/**
* rename and/or move folder
*
* The new name has the same restrictions as in createFolder()
*
* @param string|Folder $oldName name or instance of folder
* @param string $newName new global name of folder
* @throws Exception\RuntimeException
*/
public function renameFolder($oldName, $newName)
{
if ($oldName instanceof Folder) {
$oldName = $oldName->getGlobalName();
}
if (! $this->protocol->rename($oldName, $newName)) {
throw new Exception\RuntimeException('cannot rename folder');
}
}
/**
* append a new message to mail storage
*
* @param string $message message as string or instance of message class
* @param null|string|Folder $folder folder for new message, else current
* folder is taken
* @param null|array $flags set flags for new message, else a default set
* is used
* @throws Exception\RuntimeException
*/
public function appendMessage($message, $folder = null, $flags = null)
{
if ($folder === null) {
$folder = $this->currentFolder;
}
if ($flags === null) {
$flags = [Mail\Storage::FLAG_SEEN];
}
// TODO: handle class instances for $message
if (! $this->protocol->append($folder, $message, $flags)) {
throw new Exception\RuntimeException(
'cannot create message, please check if the folder exists and your flags'
);
}
}
/**
* copy an existing message
*
* @param int $id number of message
* @param string|Folder $folder name or instance of target folder
* @throws Exception\RuntimeException
*/
public function copyMessage($id, $folder)
{
if (! $this->protocol->copy($folder, $id)) {
throw new Exception\RuntimeException('cannot copy message, does the folder exist?');
}
}
/**
* move an existing message
*
* NOTE: IMAP has no native move command, thus it's emulated with copy and delete
*
* @param int $id number of message
* @param string|Folder $folder name or instance of target folder
* @throws Exception\RuntimeException
*/
public function moveMessage($id, $folder)
{
$this->copyMessage($id, $folder);
$this->removeMessage($id);
}
/**
* set flags for message
*
* NOTE: this method can't set the recent flag.
*
* @param int $id number of message
* @param array $flags new flags for message
* @throws Exception\RuntimeException
*/
public function setFlags($id, $flags)
{
if (! $this->protocol->store($flags, $id)) {
throw new Exception\RuntimeException(
'cannot set flags, have you tried to set the recent flag or special chars?'
);
}
}
/**
* get IMAP delimiter
*
* @return string|null
*/
public function delimiter()
{
if (! isset($this->delimiter)) {
$this->getFolders();
}
return $this->delimiter;
}
}
laminas-mail/src/Storage/Message.php 0000644 00000004406 15240152661 0013406 0 ustar 00 <?php
namespace Laminas\Mail\Storage;
use Laminas\Stdlib\ErrorHandler;
use function array_combine;
use function file_get_contents;
use function is_resource;
use function ltrim;
use function stream_get_contents;
class Message extends Part implements Message\MessageInterface
{
/**
* flags for this message
*
* @var array
*/
protected $flags = [];
/**
* Public constructor
*
* In addition to the parameters of Part::__construct() this constructor supports:
* - file filename or file handle of a file with raw message content
* - flags array with flags for message, keys are ignored, use constants defined in \Laminas\Mail\Storage
*
* @param array $params
* @throws Exception\RuntimeException
*/
public function __construct(array $params)
{
if (isset($params['file'])) {
if (! is_resource($params['file'])) {
ErrorHandler::start();
$params['raw'] = file_get_contents($params['file']);
$error = ErrorHandler::stop();
if ($params['raw'] === false) {
throw new Exception\RuntimeException('could not open file', 0, $error);
}
} else {
$params['raw'] = stream_get_contents($params['file']);
}
$params['raw'] = ltrim($params['raw']);
}
if (! empty($params['flags'])) {
// set key and value to the same value for easy lookup
$this->flags = array_combine($params['flags'], $params['flags']);
}
parent::__construct($params);
}
/**
* return toplines as found after headers
*
* @return string toplines
*/
public function getTopLines()
{
return $this->topLines;
}
/**
* check if flag is set
*
* @param mixed $flag a flag name, use constants defined in \Laminas\Mail\Storage
* @return bool true if set, otherwise false
*/
public function hasFlag($flag)
{
return isset($this->flags[$flag]);
}
/**
* get all set flags
*
* @return array array with flags, key and value are the same for easy lookup
*/
public function getFlags()
{
return $this->flags;
}
}
laminas-mail/src/Storage/Pop3.php 0000644 00000021255 15240152661 0012644 0 ustar 00 <?php
namespace Laminas\Mail\Storage;
use Laminas\Mail\Exception as MailException;
use Laminas\Mail\Protocol;
use Laminas\Mail\Protocol\Exception\RuntimeException;
use Laminas\Mail\Storage\Exception\ExceptionInterface;
use Laminas\Mail\Storage\Exception\InvalidArgumentException;
use Laminas\Mail\Storage\Message;
use Laminas\Mime;
use function array_combine;
use function array_key_exists;
use function is_string;
use function range;
use function strtolower;
class Pop3 extends AbstractStorage
{
/**
* protocol handler
*
* @var null|\Laminas\Mail\Protocol\Pop3
*/
protected $protocol;
/**
* Count messages all messages in current box
*
* @return int number of messages
* @throws ExceptionInterface
* @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface
*/
public function countMessages()
{
$count = 0; // "Declare" variable before first usage.
$octets = 0; // "Declare" variable since it's passed by reference
$this->protocol->status($count, $octets);
return (int) $count;
}
/**
* get a list of messages with number and size
*
* @param int $id number of message
* @return int|array size of given message of list with all messages as array(num => size)
* @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface
*/
public function getSize($id = 0)
{
$id = $id ?: null;
return $this->protocol->getList($id);
}
/**
* Fetch a message
*
* @param int $id number of message
* @return Message
* @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface
*/
public function getMessage($id)
{
$bodyLines = 0;
$message = $this->protocol->top($id, $bodyLines, true);
return new $this->messageClass([
'handler' => $this,
'id' => $id,
'headers' => $message,
'noToplines' => $bodyLines < 1,
]);
}
/**
* Get raw header of message or part
*
* @param int $id number of message
* @param null|array|string $part path to part or null for message header
* @param int $topLines include this many lines with header (after an empty line)
* @return string raw header
* @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface
* @throws ExceptionInterface
*/
public function getRawHeader($id, $part = null, $topLines = 0)
{
if ($part !== null) {
// TODO: implement
throw new Exception\RuntimeException('not implemented');
}
return $this->protocol->top($id, 0, true);
}
/**
* Get raw content of message or part
*
* @param int $id number of message
* @param null|array|string $part path to part or null for message content
* @return string raw content
* @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface
* @throws ExceptionInterface
*/
public function getRawContent($id, $part = null)
{
if ($part !== null) {
// TODO: implement
throw new Exception\RuntimeException('not implemented');
}
$content = $this->protocol->retrieve($id);
// TODO: find a way to avoid decoding the headers
$headers = null; // "Declare" variable since it's passed by reference
$body = null; // "Declare" variable before first usage.
Mime\Decode::splitMessage($content, $headers, $body);
return $body;
}
/**
* create instance with parameters
* Supported parameters are
* - host hostname or ip address of POP3 server
* - user username
* - password password for user 'username' [optional, default = '']
* - port port for POP3 server [optional, default = 110]
* - ssl 'SSL' or 'TLS' for secure sockets
*
* @param array|object|Protocol\Pop3 $params mail reader specific
* parameters or configured Pop3 protocol object
* @throws InvalidArgumentException
* @throws RuntimeException
*/
public function __construct($params)
{
$this->has['fetchPart'] = false;
$this->has['top'] = null;
$this->has['uniqueid'] = null;
if ($params instanceof Protocol\Pop3) {
$this->protocol = $params;
return;
}
$params = ParamsNormalizer::normalizeParams($params);
if (! isset($params['user'])) {
throw new InvalidArgumentException('need at least user in params');
}
$host = $params['host'] ?? 'localhost';
$password = $params['password'] ?? '';
$port = $params['port'] ?? null;
$ssl = $params['ssl'] ?? false;
if (null !== $port) {
$port = (int) $port;
}
if (! is_string($ssl)) {
$ssl = (bool) $ssl;
}
$this->protocol = new Protocol\Pop3();
if (array_key_exists('novalidatecert', $params)) {
$this->protocol->setNoValidateCert((bool) $params['novalidatecert']);
}
$this->protocol->connect((string) $host, $port, $ssl);
$this->protocol->login((string) $params['user'], (string) $password);
}
/**
* Close resource for mail lib. If you need to control, when the resource
* is closed. Otherwise the destructor would call this.
*/
public function close()
{
$this->protocol->logout();
}
/**
* Keep the server busy.
*
* @throws RuntimeException
*/
public function noop()
{
$this->protocol->noop();
}
/**
* Remove a message from server. If you're doing that from a web environment
* you should be careful and use a uniqueid as parameter if possible to
* identify the message.
*
* @param int $id number of message
* @throws RuntimeException
*/
public function removeMessage($id)
{
$this->protocol->delete($id);
}
/**
* get unique id for one or all messages
*
* if storage does not support unique ids it's the same as the message number
*
* @param int|null $id message number
* @return array|string message number for given message or all messages as array
* @throws ExceptionInterface
*/
public function getUniqueId($id = null)
{
if (! $this->hasUniqueid) {
if ($id) {
return $id;
}
$count = $this->countMessages();
if ($count < 1) {
return [];
}
$range = range(1, $count);
return array_combine($range, $range);
}
return $this->protocol->uniqueid($id);
}
/**
* get a message number from a unique id
*
* I.e. if you have a webmailer that supports deleting messages you should use unique ids
* as parameter and use this method to translate it to message number right before calling removeMessage()
*
* @param string $id unique id
* @throws InvalidArgumentException
* @return int message number
*/
public function getNumberByUniqueId($id)
{
if (! $this->hasUniqueid) {
return $id;
}
$ids = $this->getUniqueId();
foreach ($ids as $k => $v) {
if ($v == $id) {
return $k;
}
}
throw new InvalidArgumentException('unique id not found');
}
/**
* Special handling for hasTop and hasUniqueid. The headers of the first message is
* retrieved if Top wasn't needed/tried yet.
*
* @see AbstractStorage::__get()
*
* @param string $var
* @return null|string
*/
public function __get($var)
{
$result = parent::__get($var);
if ($result !== null) {
return $result;
}
if (strtolower($var) == 'hastop') {
if ($this->protocol->hasTop === null) {
// need to make a real call, because not all server are honest in their capas
try {
$this->protocol->top(1, 0, false);
} catch (MailException\ExceptionInterface) {
// ignoring error
}
}
$this->has['top'] = $this->protocol->hasTop;
return $this->protocol->hasTop;
}
if (strtolower($var) == 'hasuniqueid') {
$id = null;
try {
$id = $this->protocol->uniqueid(1);
} catch (MailException\ExceptionInterface) {
// ignoring error
}
$this->has['uniqueid'] = (bool) $id;
return $this->has['uniqueid'];
}
return $result;
}
}
laminas-mail/src/Storage/Exception/InvalidArgumentException.php 0000644 00000000354 15240152661 0020726 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Exception;
use Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface
{
}
laminas-mail/src/Storage/Exception/ExceptionInterface.php 0000644 00000000252 15240152661 0017532 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Exception;
use Laminas\Mail\Exception\ExceptionInterface as MailException;
interface ExceptionInterface extends MailException
{
}
laminas-mail/src/Storage/Exception/OutOfBoundsException.php 0000644 00000000344 15240152661 0020043 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Exception;
use Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class OutOfBoundsException extends Exception\OutOfBoundsException implements ExceptionInterface
{
}
laminas-mail/src/Storage/Exception/RuntimeException.php 0000644 00000000334 15240152661 0017256 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Exception;
use Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class RuntimeException extends Exception\RuntimeException implements ExceptionInterface
{
}
laminas-mail/src/Storage/Folder.php 0000644 00000010366 15240152661 0013237 0 ustar 00 <?php
namespace Laminas\Mail\Storage;
use RecursiveIterator;
use ReturnTypeWillChange;
use Stringable;
use function current;
use function key;
use function next;
use function reset;
class Folder implements RecursiveIterator, Stringable
{
/**
* global name (absolute name of folder)
*
* @var string
*/
protected $globalName;
/**
* create a new mail folder instance
*
* @param string $localName local name (name of folder in parent folder)
* @param string $globalName absolute name of folder
* @param bool $selectable if true folder holds messages, if false it's
* just a parent for subfolders (Default: true)
* @param array<string, Folder> $folders subfolders of
* folder array(localName => \Laminas\Mail\Storage\Folder folder)
*/
public function __construct(
protected $localName,
$globalName = '',
protected $selectable = true,
protected array $folders = []
) {
$this->globalName = $globalName ?: $localName;
}
/**
* implements RecursiveIterator::hasChildren()
*
* @return bool current element has children
*/
#[ReturnTypeWillChange]
public function hasChildren()
{
$current = $this->current();
return $current && $current instanceof self && ! $current->isLeaf();
}
/**
* implements RecursiveIterator::getChildren()
*
* @return Folder same as self::current()
*/
#[ReturnTypeWillChange]
public function getChildren()
{
return $this->current();
}
/**
* implements Iterator::valid()
*
* @return bool check if there's a current element
*/
#[ReturnTypeWillChange]
public function valid()
{
return key($this->folders) !== null;
}
/**
* implements Iterator::next()
*/
#[ReturnTypeWillChange]
public function next()
{
next($this->folders);
}
/**
* implements Iterator::key()
*
* @return string key/local name of current element
*/
#[ReturnTypeWillChange]
public function key()
{
return key($this->folders);
}
/**
* implements Iterator::current()
*
* @return Folder current folder
*/
#[ReturnTypeWillChange]
public function current()
{
return current($this->folders);
}
/**
* implements Iterator::rewind()
*/
#[ReturnTypeWillChange]
public function rewind()
{
reset($this->folders);
}
/**
* get subfolder named $name
*
* @param string $name wanted subfolder
* @throws Exception\InvalidArgumentException
* @return Folder folder named $folder
*/
public function __get($name)
{
if (! isset($this->folders[$name])) {
throw new Exception\InvalidArgumentException("no subfolder named $name");
}
return $this->folders[$name];
}
/**
* add or replace subfolder named $name
*
* @param string $name local name of subfolder
* @param Folder $folder instance for new subfolder
*/
public function __set($name, self $folder)
{
$this->folders[$name] = $folder;
}
/**
* remove subfolder named $name
*
* @param string $name local name of subfolder
*/
public function __unset($name)
{
unset($this->folders[$name]);
}
/**
* magic method for easy output of global name
*
* @return string global name of folder
*/
public function __toString(): string
{
return (string) $this->getGlobalName();
}
/**
* get local name
*
* @return string local name
*/
public function getLocalName()
{
return $this->localName;
}
/**
* get global name
*
* @return string global name
*/
public function getGlobalName()
{
return $this->globalName;
}
/**
* is this folder selectable?
*
* @return bool selectable
*/
public function isSelectable()
{
return $this->selectable;
}
/**
* check if folder has no subfolder
*
* @return bool true if no subfolders
*/
public function isLeaf()
{
return empty($this->folders);
}
}
laminas-mail/src/Storage/AbstractStorage.php 0000644 00000020046 15240152661 0015110 0 ustar 00 <?php
namespace Laminas\Mail\Storage;
use ArrayAccess;
use Countable;
use Laminas\Mail\Storage\Message;
use ReturnTypeWillChange;
use SeekableIterator;
use function str_starts_with;
use function strtolower;
use function substr;
abstract class AbstractStorage implements
ArrayAccess,
Countable,
SeekableIterator
{
/**
* class capabilities with default values
*
* @var array
*/
protected $has = [
'uniqueid' => true,
'delete' => false,
'create' => false,
'top' => false,
'fetchPart' => true,
'flags' => false,
];
/**
* current iteration position
*
* @var int
*/
protected $iterationPos = 0;
/**
* maximum iteration position (= message count)
*
* @var null|int
*/
protected $iterationMax;
/**
* used message class, change it in an extended class to extend the returned message class
*
* @var class-string<Message\MessageInterface>
*/
protected $messageClass = Message::class;
/**
* Getter for has-properties. The standard has properties
* are: hasFolder, hasUniqueid, hasDelete, hasCreate, hasTop
*
* The valid values for the has-properties are:
* - true if a feature is supported
* - false if a feature is not supported
* - null is it's not yet known or it can't be know if a feature is supported
*
* @param string $var property name
* @throws Exception\InvalidArgumentException
* @return null|bool supported or not
*/
public function __get($var)
{
if (str_starts_with($var, 'has')) {
$var = strtolower(substr($var, 3));
return $this->has[$var] ?? null;
}
throw new Exception\InvalidArgumentException($var . ' not found');
}
/**
* Get a full list of features supported by the specific mail lib and the server
*
* @return array list of features as array(feature_name => true|false[|null])
*/
public function getCapabilities()
{
return $this->has;
}
/**
* Count messages messages in current box/folder
*
* @return int number of messages
* @throws Exception\ExceptionInterface
*/
abstract public function countMessages();
/**
* Get a list of messages with number and size
*
* @param int $id number of message
* @return int|array size of given message of list with all messages as array(num => size)
*/
abstract public function getSize($id = 0);
/**
* Get a message with headers and body
*
* @param int $id number of message
* @return Message\MessageInterface
*/
abstract public function getMessage($id);
/**
* Get raw header of message or part
*
* @param int $id number of message
* @param null|array|string $part path to part or null for message header
* @param int $topLines include this many lines with header (after an empty line)
* @return string raw header
*/
abstract public function getRawHeader($id, $part = null, $topLines = 0);
/**
* Get raw content of message or part
*
* @param int $id number of message
* @param null|array|string $part path to part or null for message content
* @return string raw content
*/
abstract public function getRawContent($id, $part = null);
/**
* Create instance with parameters
*
* @param array $params mail reader specific parameters
* @throws Exception\ExceptionInterface
*/
abstract public function __construct($params);
/**
* Destructor calls close() and therefore closes the resource.
*/
public function __destruct()
{
$this->close();
}
/**
* Close resource for mail lib. If you need to control, when the resource
* is closed. Otherwise the destructor would call this.
*/
abstract public function close();
/**
* Keep the resource alive.
*/
abstract public function noop();
/**
* delete a message from current box/folder
*
* @param int $id message number
*/
abstract public function removeMessage($id);
/**
* get unique id for one or all messages
*
* if storage does not support unique ids it's the same as the message number
*
* @param int|null $id message number
* @return array|string message number for given message or all messages as array
* @throws Exception\ExceptionInterface
*/
abstract public function getUniqueId($id = null);
/**
* get a message number from a unique id
*
* I.e. if you have a webmailer that supports deleting messages you should use unique ids
* as parameter and use this method to translate it to message number right before calling removeMessage()
*
* @param string $id unique id
* @return int message number
* @throws Exception\ExceptionInterface
*/
abstract public function getNumberByUniqueId($id);
// interface implementations follows
/**
* Countable::count()
*
* @return int
*/
#[ReturnTypeWillChange]
public function count()
{
return $this->countMessages();
}
/**
* ArrayAccess::offsetExists()
*
* @param int $id
* @return bool
*/
#[ReturnTypeWillChange]
public function offsetExists($id)
{
try {
if ($this->getMessage($id)) {
return true;
}
} catch (Exception\ExceptionInterface) {
}
return false;
}
/**
* ArrayAccess::offsetGet()
*
* @param int $id
* @return Message message object
*/
#[ReturnTypeWillChange]
public function offsetGet($id)
{
return $this->getMessage($id);
}
/**
* ArrayAccess::offsetSet()
*
* @throws Exception\RuntimeException
*/
#[ReturnTypeWillChange]
public function offsetSet(mixed $id, mixed $value)
{
throw new Exception\RuntimeException('cannot write mail messages via array access');
}
/**
* ArrayAccess::offsetUnset()
*
* @param int $id
* @return bool success
*/
#[ReturnTypeWillChange]
public function offsetUnset($id)
{
return $this->removeMessage($id);
}
/**
* Iterator::rewind()
*
* Rewind always gets the new count from the storage. Thus if you use
* the interfaces and your scripts take long you should use reset()
* from time to time.
*/
#[ReturnTypeWillChange]
public function rewind()
{
$this->iterationMax = $this->countMessages();
$this->iterationPos = 1;
}
/**
* Iterator::current()
*
* @return Message current message
*/
#[ReturnTypeWillChange]
public function current()
{
return $this->getMessage($this->iterationPos);
}
/**
* Iterator::key()
*
* @return int id of current position
*/
#[ReturnTypeWillChange]
public function key()
{
return $this->iterationPos;
}
/**
* Iterator::next()
*/
#[ReturnTypeWillChange]
public function next()
{
++$this->iterationPos;
}
/**
* Iterator::valid()
*
* @return bool
*/
#[ReturnTypeWillChange]
public function valid()
{
if ($this->iterationMax === null) {
$this->iterationMax = $this->countMessages();
}
return $this->iterationPos && $this->iterationPos <= $this->iterationMax;
}
/**
* SeekableIterator::seek()
*
* @param int $pos
* @throws Exception\OutOfBoundsException
*/
#[ReturnTypeWillChange]
public function seek($pos)
{
if ($this->iterationMax === null) {
$this->iterationMax = $this->countMessages();
}
if ($pos > $this->iterationMax) {
throw new Exception\OutOfBoundsException('this position does not exist');
}
$this->iterationPos = $pos;
}
}
laminas-mail/src/Storage/Writable/WritableInterface.php 0000644 00000005161 15240152661 0017164 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Writable;
use Laminas\Mail\Message;
use Laminas\Mail\Storage;
use Laminas\Mime;
interface WritableInterface
{
/**
* create a new folder
*
* This method also creates parent folders if necessary. Some mail storages
* may restrict, which folder may be used as parent or which chars may be
* used in the folder name
*
* @param string $name global name of folder, local name if $parentFolder
* is set.
* @param string|Storage\Folder $parentFolder parent folder for new folder,
* else root folder is parent.
* @throws Storage\Exception\ExceptionInterface
*/
public function createFolder($name, $parentFolder = null);
/**
* remove a folder
*
* @param string|Storage\Folder $name name or instance of folder.
* @throws Storage\Exception\ExceptionInterface
*/
public function removeFolder($name);
/**
* rename and/or move folder
*
* The new name has the same restrictions as in createFolder()
*
* @param string|Storage\Folder $oldName name or instance of folder.
* @param string $newName new global name of folder.
* @throws Storage\Exception\ExceptionInterface
*/
public function renameFolder($oldName, $newName);
/**
* append a new message to mail storage
*
* @param string|Message|Mime\Message $message message as string or
* instance of message class.
* @param null|string|Storage\Folder $folder folder for new message, else
* current folder is taken.
* @param null|array $flags set flags for new message, else a default set
* is used.
* @throws Storage\Exception\ExceptionInterface
*/
public function appendMessage($message, $folder = null, $flags = null);
/**
* copy an existing message
*
* @param int $id number of message
* @param string|Storage\Folder $folder name or instance of target folder
* @throws Storage\Exception\ExceptionInterface
*/
public function copyMessage($id, $folder);
/**
* move an existing message
*
* @param int $id number of message
* @param string|Storage\Folder $folder name or instance of target folder
* @throws Storage\Exception\ExceptionInterface
*/
public function moveMessage($id, $folder);
/**
* set flags for message
*
* NOTE: this method can't set the recent flag.
*
* @param int $id number of message
* @param array $flags new flags for message
* @throws Storage\Exception\ExceptionInterface
*/
public function setFlags($id, $flags);
}
laminas-mail/src/Storage/Writable/Maildir.php 0000644 00000106342 15240152661 0015156 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Writable;
use Laminas\Mail\Exception as MailException;
use Laminas\Mail\Storage;
use Laminas\Mail\Storage\Exception as StorageException;
use Laminas\Mail\Storage\Exception\ExceptionInterface;
use Laminas\Mail\Storage\Exception\InvalidArgumentException;
use Laminas\Mail\Storage\Exception\RuntimeException;
use Laminas\Mail\Storage\Folder;
use Laminas\Stdlib\ErrorHandler;
use RecursiveIteratorIterator;
use function array_flip;
use function array_keys;
use function array_search;
use function array_values;
use function closedir;
use function copy;
use function dirname;
use function explode;
use function fclose;
use function fgets;
use function file_exists;
use function file_put_contents;
use function filemtime;
use function filesize;
use function fopen;
use function fread;
use function fwrite;
use function get_resource_type;
use function getmypid;
use function implode;
use function is_array;
use function is_dir;
use function is_file;
use function is_numeric;
use function is_resource;
use function link;
use function microtime;
use function mkdir;
use function opendir;
use function php_uname;
use function readdir;
use function rename;
use function rmdir;
use function rtrim;
use function sleep;
use function str_contains;
use function str_starts_with;
use function stream_copy_to_stream;
use function strlen;
use function strpos;
use function strrpos;
use function strtok;
use function substr;
use function time;
use function trim;
use function unlink;
use const DIRECTORY_SEPARATOR;
use const E_WARNING;
use const FILE_APPEND;
class Maildir extends Folder\Maildir implements WritableInterface
{
// TODO: init maildir (+ constructor option create if not found)
/**
* use quota and size of quota if given
*
* @var bool|int
*/
protected $quota;
/**
* create a new maildir
*
* If the given dir is already a valid maildir this will not fail.
*
* @param string $dir directory for the new maildir (may already exist)
* @throws RuntimeException
* @throws InvalidArgumentException
*/
public static function initMaildir($dir)
{
if (file_exists($dir)) {
if (! is_dir($dir)) {
throw new StorageException\InvalidArgumentException('maildir must be a directory if already exists');
}
} else {
ErrorHandler::start();
$test = mkdir($dir);
$error = ErrorHandler::stop();
if (! $test) {
$dir = dirname($dir);
if (! file_exists($dir)) {
throw new StorageException\InvalidArgumentException("parent $dir not found", 0, $error);
} elseif (! is_dir($dir)) {
throw new StorageException\InvalidArgumentException("parent $dir not a directory", 0, $error);
}
throw new StorageException\RuntimeException('cannot create maildir', 0, $error);
}
}
foreach (['cur', 'tmp', 'new'] as $subdir) {
ErrorHandler::start();
$test = mkdir($dir . DIRECTORY_SEPARATOR . $subdir);
$error = ErrorHandler::stop();
if (! $test) {
// ignore if dir exists (i.e. was already valid maildir or two processes try to create one)
if (! file_exists($dir . DIRECTORY_SEPARATOR . $subdir)) {
throw new StorageException\RuntimeException('could not create subdir ' . $subdir, 0, $error);
}
}
}
}
/**
* Create instance with parameters
* Additional parameters are (see parent for more):
* - create if true a new maildir is create if none exists
*
* @param array|object $params mail reader specific parameters
* @throws ExceptionInterface
*/
public function __construct($params)
{
if (is_array($params)) {
$params = (object) $params;
}
if (
! empty($params->create)
&& isset($params->dirname)
&& ! file_exists($params->dirname . DIRECTORY_SEPARATOR . 'cur')
) {
self::initMaildir($params->dirname);
}
parent::__construct($params);
}
/**
* create a new folder
*
* This method also creates parent folders if necessary. Some mail storages may restrict, which folder
* may be used as parent or which chars may be used in the folder name
*
* @param string $name global name of folder, local name if $parentFolder is set
* @param string|Folder $parentFolder parent of new folder, else root folder is parent
* @throws RuntimeException
* @return string only used internally (new created maildir)
*/
public function createFolder($name, $parentFolder = null)
{
if ($parentFolder instanceof Folder) {
$folder = $parentFolder->getGlobalName() . $this->delim . $name;
} elseif ($parentFolder !== null) {
$folder = rtrim($parentFolder, $this->delim) . $this->delim . $name;
} else {
$folder = $name;
}
$folder = trim($folder, $this->delim);
// first we check if we try to create a folder that does exist
$exists = null;
try {
$exists = $this->getFolders($folder);
} catch (MailException\ExceptionInterface) {
// ok
}
if ($exists) {
throw new StorageException\RuntimeException('folder already exists');
}
if (str_contains($folder, $this->delim . $this->delim)) {
throw new StorageException\RuntimeException('invalid name - folder parts may not be empty');
}
if (str_starts_with($folder, 'INBOX' . $this->delim)) {
$folder = substr($folder, 6);
}
$fulldir = $this->rootdir . '.' . $folder;
// check if we got tricked and would create a dir outside of the rootdir or not as direct child
if (
str_contains($folder, DIRECTORY_SEPARATOR) || str_contains($folder, '/')
|| dirname($fulldir) . DIRECTORY_SEPARATOR != $this->rootdir
) {
throw new StorageException\RuntimeException('invalid name - no directory separator allowed in folder name');
}
// has a parent folder?
$parent = null;
if (strpos($folder, $this->delim)) {
// let's see if the parent folder exists
$parent = substr($folder, 0, strrpos($folder, $this->delim));
try {
$this->getFolders($parent);
} catch (MailException\ExceptionInterface) {
// does not - create parent folder
$this->createFolder($parent);
}
}
ErrorHandler::start();
if (! mkdir($fulldir) || ! mkdir($fulldir . DIRECTORY_SEPARATOR . 'cur')) {
$error = ErrorHandler::stop();
throw new StorageException\RuntimeException(
'error while creating new folder, may be created incompletely',
0,
$error
);
}
ErrorHandler::stop();
mkdir($fulldir . DIRECTORY_SEPARATOR . 'new');
mkdir($fulldir . DIRECTORY_SEPARATOR . 'tmp');
$localName = $parent ? substr($folder, strlen($parent) + 1) : $folder;
$this->getFolders($parent)->$localName = new Folder($localName, $folder, true);
return $fulldir;
}
/**
* remove a folder
*
* @param string|Folder $name name or instance of folder
* @throws RuntimeException
*/
public function removeFolder($name)
{
// TODO: This could fail in the middle of the task, which is not optimal.
// But there is no defined standard way to mark a folder as removed and there is no atomar fs-op
// to remove a directory. Also moving the folder to a/the trash folder is not possible, as
// all parent folders must be created. What we could do is add a dash to the front of the
// directory name and it should be ignored as long as other processes obey the standard.
if ($name instanceof Folder) {
$name = $name->getGlobalName();
}
$name = trim($name, $this->delim);
if (str_starts_with($name, 'INBOX' . $this->delim)) {
$name = substr($name, 6);
}
// check if folder exists and has no children
if (! $this->getFolders($name)->isLeaf()) {
throw new StorageException\RuntimeException('delete children first');
}
if ($name == 'INBOX' || $name == DIRECTORY_SEPARATOR || $name == '/') {
throw new StorageException\RuntimeException('wont delete INBOX');
}
if ($name == $this->getCurrentFolder()) {
throw new StorageException\RuntimeException('wont delete selected folder');
}
foreach (['tmp', 'new', 'cur', '.'] as $subdir) {
$dir = $this->rootdir . '.' . $name . DIRECTORY_SEPARATOR . $subdir;
if (! file_exists($dir)) {
continue;
}
$dh = opendir($dir);
if (! $dh) {
throw new StorageException\RuntimeException("error opening $subdir");
}
while (($entry = readdir($dh)) !== false) {
if ($entry == '.' || $entry == '..') {
continue;
}
if (! unlink($dir . DIRECTORY_SEPARATOR . $entry)) {
throw new StorageException\RuntimeException("error cleaning $subdir");
}
}
closedir($dh);
if ($subdir !== '.') {
if (! rmdir($dir)) {
throw new StorageException\RuntimeException("error removing $subdir");
}
}
}
if (! rmdir($this->rootdir . '.' . $name)) {
// at least we should try to make it a valid maildir again
mkdir($this->rootdir . '.' . $name . DIRECTORY_SEPARATOR . 'cur');
throw new StorageException\RuntimeException("error removing maindir");
}
$parent = strpos($name, $this->delim) ? substr($name, 0, strrpos($name, $this->delim)) : null;
$localName = $parent ? substr($name, strlen($parent) + 1) : $name;
unset($this->getFolders($parent)->$localName);
}
/**
* rename and/or move folder
*
* The new name has the same restrictions as in createFolder()
*
* @param string|Folder $oldName name or instance of folder
* @param string $newName new global name of folder
* @throws RuntimeException
*/
public function renameFolder($oldName, $newName)
{
// TODO: This is also not atomar and has similar problems as removeFolder()
if ($oldName instanceof Folder) {
$oldName = $oldName->getGlobalName();
}
$oldName = trim($oldName, $this->delim);
if (str_starts_with($oldName, 'INBOX' . $this->delim)) {
$oldName = substr($oldName, 6);
}
$newName = trim($newName, $this->delim);
if (str_starts_with($newName, 'INBOX' . $this->delim)) {
$newName = substr($newName, 6);
}
if (str_starts_with($newName, $oldName . $this->delim)) {
throw new StorageException\RuntimeException('new folder cannot be a child of old folder');
}
// check if folder exists and has no children
$folder = $this->getFolders($oldName);
if ($oldName == 'INBOX' || $oldName == DIRECTORY_SEPARATOR || $oldName == '/') {
throw new StorageException\RuntimeException('wont rename INBOX');
}
if ($oldName == $this->getCurrentFolder()) {
throw new StorageException\RuntimeException('wont rename selected folder');
}
$newdir = $this->createFolder($newName);
if (! $folder->isLeaf()) {
foreach ($folder as $k => $v) {
$this->renameFolder($v->getGlobalName(), $newName . $this->delim . $k);
}
}
$olddir = $this->rootdir . '.' . $folder;
foreach (['tmp', 'new', 'cur'] as $subdir) {
$subdir = DIRECTORY_SEPARATOR . $subdir;
if (! file_exists($olddir . $subdir)) {
continue;
}
// using copy or moving files would be even better - but also much slower
if (! rename($olddir . $subdir, $newdir . $subdir)) {
throw new StorageException\RuntimeException('error while moving ' . $subdir);
}
}
// create a dummy if removing fails - otherwise we can't read it next time
mkdir($olddir . DIRECTORY_SEPARATOR . 'cur');
$this->removeFolder($oldName);
}
/**
* create a uniqueid for maildir filename
*
* This is nearly the format defined in the maildir standard. The microtime() call should already
* create a uniqueid, the pid is for multicore/-cpu machine that manage to call this function at the
* exact same time, and uname() gives us the hostname for multiple machines accessing the same storage.
*
* If someone disables posix we create a random number of the same size, so this method should also
* work on Windows - if you manage to get maildir working on Windows.
* Microtime could also be disabled, although I've never seen it.
*
* @return string new uniqueid
*/
protected function createUniqueId()
{
$id = '';
$id .= microtime(true);
$id .= '.' . getmypid();
$id .= '.' . php_uname('n');
return $id;
}
/**
* open a temporary maildir file
*
* makes sure tmp/ exists and create a file with a unique name
* you should close the returned filehandle!
*
* @param string $folder name of current folder without leading .
* @throws RuntimeException
* @return array array('dirname' => dir of maildir folder, 'uniq' => unique id, 'filename' => name of create file
* 'handle' => file opened for writing)
*/
protected function createTmpFile($folder = 'INBOX')
{
if ($folder == 'INBOX') {
$tmpdir = $this->rootdir . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR;
} else {
$tmpdir = $this->rootdir . '.' . $folder . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR;
}
if (! file_exists($tmpdir)) {
if (! mkdir($tmpdir)) {
throw new StorageException\RuntimeException('problems creating tmp dir');
}
}
// we should retry to create a unique id if a file with the same name exists
// to avoid a script timeout we only wait 1 second (instead of 2) and stop
// after a defined retry count
// if you change this variable take into account that it can take up to $maxTries seconds
// normally we should have a valid unique name after the first try, we're just following the "standard" here
$maxTries = 5;
for ($i = 0; $i < $maxTries; ++$i) {
$uniq = $this->createUniqueId();
if (! file_exists($tmpdir . $uniq)) {
// here is the race condition! - as defined in the standard
// to avoid having a long time between stat()ing the file and creating it we're opening it here
// to mark the filename as taken
$fh = fopen($tmpdir . $uniq, 'w');
if (! $fh) {
throw new StorageException\RuntimeException('could not open temp file');
}
break;
}
sleep(1);
}
if (! $fh) {
throw new StorageException\RuntimeException(
"tried {$maxTries} unique ids for a temp file, but all were taken - giving up"
);
}
return [
'dirname' => $this->rootdir . '.' . $folder,
'uniq' => $uniq,
'filename' => $tmpdir . $uniq,
'handle' => $fh,
];
}
/**
* create an info string for filenames with given flags
*
* @param array $flags wanted flags, with the reference you'll get the set
* flags with correct key (= char for flag)
* @return string info string for version 2 filenames including the leading colon
* @throws StorageException\InvalidArgumentException
*/
protected function getInfoString(&$flags)
{
// accessing keys is easier, faster and it removes duplicated flags
$wantedFlags = array_flip($flags);
if (isset($wantedFlags[Storage::FLAG_RECENT])) {
throw new StorageException\InvalidArgumentException('recent flag may not be set');
}
$info = ':2,';
$flags = [];
foreach (Storage\Maildir::$knownFlags as $char => $flag) {
if (! isset($wantedFlags[$flag])) {
continue;
}
$info .= $char;
$flags[$char] = $flag;
unset($wantedFlags[$flag]);
}
if (! empty($wantedFlags)) {
$wantedFlags = implode(', ', array_keys($wantedFlags));
throw new StorageException\InvalidArgumentException('unknown flag(s): ' . $wantedFlags);
}
return $info;
}
/**
* append a new message to mail storage
*
* @param string|resource $message message as string or stream resource.
* @param null|string|Folder $folder folder for new message, else current
* folder is taken.
* @param null|array $flags set flags for new message, else a default set
* is used.
* @param bool $recent handle this mail as if recent flag has been set,
* should only be used in delivery.
* @throws StorageException\RuntimeException
*/
public function appendMessage($message, $folder = null, $flags = null, $recent = false)
{
if ($this->quota && $this->checkQuota()) {
throw new StorageException\RuntimeException('storage is over quota!');
}
if ($folder === null) {
$folder = $this->currentFolder;
}
if (! $folder instanceof Folder) {
$folder = $this->getFolders($folder);
}
if ($flags === null) {
$flags = [Storage::FLAG_SEEN];
}
$info = $this->getInfoString($flags);
$tempFile = $this->createTmpFile($folder->getGlobalName());
// TODO: handle class instances for $message
if (is_resource($message) && get_resource_type($message) == 'stream') {
stream_copy_to_stream($message, $tempFile['handle']);
} else {
fwrite($tempFile['handle'], $message);
}
fclose($tempFile['handle']);
// we're adding the size to the filename for maildir++
$size = filesize($tempFile['filename']);
if ($size !== false) {
$info = ',S=' . $size . $info;
}
$newFilename = $tempFile['dirname'] . DIRECTORY_SEPARATOR;
$newFilename .= $recent ? 'new' : 'cur';
$newFilename .= DIRECTORY_SEPARATOR . $tempFile['uniq'] . $info;
// we're throwing any exception after removing our temp file and saving it to this variable instead
$exception = null;
if (! link($tempFile['filename'], $newFilename)) {
$exception = new StorageException\RuntimeException('cannot link message file to final dir');
}
ErrorHandler::start(E_WARNING);
unlink($tempFile['filename']);
ErrorHandler::stop();
if ($exception) {
throw $exception;
}
$this->files[] = [
'uniq' => $tempFile['uniq'],
'flags' => $flags,
'filename' => $newFilename,
];
if ($this->quota) {
$this->addQuotaEntry((int) $size, 1);
}
}
/**
* copy an existing message
*
* @param int $id number of message
* @param string|Folder $folder name or instance of targer folder
* @throws RuntimeException
*/
public function copyMessage($id, $folder)
{
if ($this->quota && $this->checkQuota()) {
throw new StorageException\RuntimeException('storage is over quota!');
}
if (! $folder instanceof Folder) {
$folder = $this->getFolders($folder);
}
$filedata = $this->getFileData($id);
$oldFile = $filedata['filename'];
$flags = $filedata['flags'];
// copied message can't be recent
while (($key = array_search(Storage::FLAG_RECENT, $flags)) !== false) {
unset($flags[$key]);
}
$info = $this->getInfoString($flags);
// we're creating the copy as temp file before moving to cur/
$tempFile = $this->createTmpFile($folder->getGlobalName());
// we don't write directly to the file
fclose($tempFile['handle']);
// we're adding the size to the filename for maildir++
$size = filesize($oldFile);
if ($size !== false) {
$info = ',S=' . $size . $info;
}
$newFile = $tempFile['dirname'] . DIRECTORY_SEPARATOR . 'cur' . DIRECTORY_SEPARATOR . $tempFile['uniq'] . $info;
// we're throwing any exception after removing our temp file and saving it to this variable instead
$exception = null;
if (! copy($oldFile, $tempFile['filename'])) {
$exception = new StorageException\RuntimeException('cannot copy message file');
} elseif (! link($tempFile['filename'], $newFile)) {
$exception = new StorageException\RuntimeException('cannot link message file to final dir');
}
ErrorHandler::start(E_WARNING);
unlink($tempFile['filename']);
ErrorHandler::stop();
if ($exception) {
throw $exception;
}
if (
$folder->getGlobalName() == $this->currentFolder
|| ($this->currentFolder == 'INBOX' && $folder->getGlobalName() == '/')
) {
$this->files[] = [
'uniq' => $tempFile['uniq'],
'flags' => $flags,
'filename' => $newFile,
];
}
if ($this->quota) {
$this->addQuotaEntry((int) $size, 1);
}
}
/**
* move an existing message
*
* @param int $id number of message
* @param string|Folder $folder name or instance of targer folder
* @throws RuntimeException
*/
public function moveMessage($id, $folder)
{
if (! $folder instanceof Folder) {
$folder = $this->getFolders($folder);
}
if (
$folder->getGlobalName() == $this->currentFolder
|| ($this->currentFolder == 'INBOX' && $folder->getGlobalName() == '/')
) {
throw new StorageException\RuntimeException('target is current folder');
}
$filedata = $this->getFileData($id);
$oldFile = $filedata['filename'];
$flags = $filedata['flags'];
// moved message can't be recent
while (($key = array_search(Storage::FLAG_RECENT, $flags)) !== false) {
unset($flags[$key]);
}
$info = $this->getInfoString($flags);
// reserving a new name
$tempFile = $this->createTmpFile($folder->getGlobalName());
fclose($tempFile['handle']);
// we're adding the size to the filename for maildir++
$size = filesize($oldFile);
if ($size !== false) {
$info = ',S=' . $size . $info;
}
$newFile = $tempFile['dirname'] . DIRECTORY_SEPARATOR . 'cur' . DIRECTORY_SEPARATOR . $tempFile['uniq'] . $info;
// we're throwing any exception after removing our temp file and saving it to this variable instead
$exception = null;
if (! rename($oldFile, $newFile)) {
$exception = new StorageException\RuntimeException('cannot move message file');
}
ErrorHandler::start(E_WARNING);
unlink($tempFile['filename']);
ErrorHandler::stop();
if ($exception) {
throw $exception;
}
unset($this->files[$id - 1]);
// remove the gap
$this->files = array_values($this->files);
}
/**
* set flags for message
*
* NOTE: this method can't set the recent flag.
*
* @param int $id number of message
* @param array $flags new flags for message
* @throws RuntimeException
*/
public function setFlags($id, $flags)
{
$info = $this->getInfoString($flags);
$filedata = $this->getFileData($id);
// NOTE: double dirname to make sure we always move to cur. if recent
// flag has been set (message is in new) it will be moved to cur.
$newFilename = dirname($filedata['filename'], 2)
. DIRECTORY_SEPARATOR
. 'cur'
. DIRECTORY_SEPARATOR
. "$filedata[uniq]$info";
ErrorHandler::start();
$test = rename($filedata['filename'], $newFilename);
$error = ErrorHandler::stop();
if (! $test) {
throw new StorageException\RuntimeException('cannot rename file', 0, $error);
}
$filedata['flags'] = $flags;
$filedata['filename'] = $newFilename;
$this->files[$id - 1] = $filedata;
}
/**
* stub for not supported message deletion
*
* @param int $id
* @throws RuntimeException
*/
public function removeMessage($id)
{
$filename = $this->getFileData($id, 'filename');
if ($this->quota) {
$size = filesize($filename);
}
ErrorHandler::start();
$test = unlink($filename);
$error = ErrorHandler::stop();
if (! $test) {
throw new StorageException\RuntimeException('cannot remove message', 0, $error);
}
unset($this->files[$id - 1]);
// remove the gap
$this->files = array_values($this->files);
if ($this->quota) {
$this->addQuotaEntry(0 - (int) $size, -1);
}
}
/**
* enable/disable quota and set a quota value if wanted or needed
*
* You can enable/disable quota with true/false. If you don't have
* a MDA or want to enforce a quota value you can also set this value
* here. Use array('size' => SIZE_QUOTA, 'count' => MAX_MESSAGE) do
* define your quota. Order of these fields does matter!
*
* @param bool|array $value new quota value
*/
public function setQuota($value)
{
$this->quota = $value;
}
/**
* get currently set quota
*
* @see \Laminas\Mail\Storage\Writable\Maildir::setQuota()
*
* @param bool $fromStorage
* @throws RuntimeException
* @return bool|array
*/
public function getQuota($fromStorage = false)
{
if ($fromStorage) {
ErrorHandler::start(E_WARNING);
$fh = fopen($this->rootdir . 'maildirsize', 'r');
$error = ErrorHandler::stop();
if (! $fh) {
throw new StorageException\RuntimeException('cannot open maildirsize', 0, $error);
}
$definition = fgets($fh);
fclose($fh);
$definition = explode(',', trim($definition));
$quota = [];
foreach ($definition as $member) {
$key = $member[strlen($member) - 1];
if ($key == 'S' || $key == 'C') {
$key = $key == 'C' ? 'count' : 'size';
}
$quota[$key] = substr($member, 0, -1);
}
return $quota;
}
return $this->quota;
}
/**
* @see http://www.inter7.com/courierimap/README.maildirquota.html "Calculating maildirsize"
*
* @throws RuntimeException
* @return array
*/
protected function calculateMaildirsize()
{
$timestamps = [];
$messages = 0;
$totalSize = 0;
if (is_array($this->quota)) {
$quota = $this->quota;
} else {
try {
$quota = $this->getQuota(true);
} catch (StorageException\ExceptionInterface $e) {
throw new StorageException\RuntimeException('no quota definition found', 0, $e);
}
}
$folders = new RecursiveIteratorIterator($this->getFolders(), RecursiveIteratorIterator::SELF_FIRST);
foreach ($folders as $folder) {
$subdir = $folder->getGlobalName();
if ($subdir == 'INBOX') {
$subdir = '';
} else {
$subdir = '.' . $subdir;
}
if ($subdir == 'Trash') {
continue;
}
foreach (['cur', 'new'] as $subsubdir) {
$dirname = $this->rootdir . $subdir . DIRECTORY_SEPARATOR . $subsubdir . DIRECTORY_SEPARATOR;
if (! file_exists($dirname)) {
continue;
}
// NOTE: we are using mtime instead of "the latest timestamp". The latest would be atime
// and as we are accessing the directory it would make the whole calculation useless.
$timestamps[$dirname] = filemtime($dirname);
$dh = opendir($dirname);
// NOTE: Should have been checked in constructor. Not throwing an exception here, quotas will
// therefore not be fully enforced, but next request will fail anyway, if problem persists.
if (! $dh) {
continue;
}
while (($entry = readdir()) !== false) {
if ($entry[0] == '.' || ! is_file($dirname . $entry)) {
continue;
}
if (strpos($entry, ',S=')) {
strtok($entry, '=');
$filesize = strtok(':');
if (is_numeric($filesize)) {
$totalSize += $filesize;
++$messages;
continue;
}
}
$size = filesize($dirname . $entry);
if ($size === false) {
// ignore, as we assume file got removed
continue;
}
$totalSize += $size;
++$messages;
}
}
}
$tmp = $this->createTmpFile();
$fh = $tmp['handle'];
$definition = [];
foreach ($quota as $type => $value) {
if ($type == 'size' || $type == 'count') {
$type = $type == 'count' ? 'C' : 'S';
}
$definition[] = $value . $type;
}
$definition = implode(',', $definition);
fwrite($fh, "$definition\n");
fwrite($fh, "$totalSize $messages\n");
fclose($fh);
rename($tmp['filename'], $this->rootdir . 'maildirsize');
foreach ($timestamps as $dir => $timestamp) {
if ($timestamp < filemtime($dir)) {
unlink($this->rootdir . 'maildirsize');
break;
}
}
return [
'size' => $totalSize,
'count' => $messages,
'quota' => $quota,
];
}
/**
* @see http://www.inter7.com/courierimap/README.maildirquota.html "Calculating the quota for a Maildir++"
*
* @param bool $forceRecalc
* @return array
*/
protected function calculateQuota($forceRecalc = false)
{
$fh = null;
$totalSize = 0;
$messages = 0;
$maildirsize = '';
if (
! $forceRecalc
&& file_exists($this->rootdir . 'maildirsize')
&& filesize($this->rootdir . 'maildirsize') < 5120
) {
$fh = fopen($this->rootdir . 'maildirsize', 'r');
}
if ($fh) {
$maildirsize = fread($fh, 5120);
if (strlen($maildirsize) >= 5120) {
fclose($fh);
$fh = null;
$maildirsize = '';
}
}
if (! $fh) {
$result = $this->calculateMaildirsize();
$totalSize = $result['size'];
$messages = $result['count'];
$quota = $result['quota'];
} else {
$maildirsize = explode("\n", $maildirsize);
if (is_array($this->quota)) {
$quota = $this->quota;
} else {
$definition = explode(',', $maildirsize[0]);
$quota = [];
foreach ($definition as $member) {
$key = $member[strlen($member) - 1];
if ($key == 'S' || $key == 'C') {
$key = $key == 'C' ? 'count' : 'size';
}
$quota[$key] = substr($member, 0, -1);
}
}
unset($maildirsize[0]);
foreach ($maildirsize as $line) {
[$size, $count] = explode(' ', trim($line));
$totalSize += $size;
$messages += $count;
}
}
$overQuota = false;
$overQuota = $overQuota || (isset($quota['size']) && $totalSize > $quota['size']);
$overQuota = $overQuota || (isset($quota['count']) && $messages > $quota['count']);
// NOTE: $maildirsize equals false if it wasn't set (AKA we recalculated) or it's only
// one line, because $maildirsize[0] gets unsetted.
// Also we're using local time to calculate the 15 minute offset. Touching a file just for known the
// local time of the file storage isn't worth the hassle.
if ($overQuota && ($maildirsize || filemtime($this->rootdir . 'maildirsize') > time() - 900)) {
$result = $this->calculateMaildirsize();
$totalSize = $result['size'];
$messages = $result['count'];
$quota = $result['quota'];
$overQuota = false;
$overQuota = $overQuota || (isset($quota['size']) && $totalSize > $quota['size']);
$overQuota = $overQuota || (isset($quota['count']) && $messages > $quota['count']);
}
if ($fh) {
// TODO is there a safe way to keep the handle open for writing?
fclose($fh);
}
return [
'size' => $totalSize,
'count' => $messages,
'quota' => $quota,
'over_quota' => $overQuota,
];
}
/**
* @param int $size
* @param int $count
* @return void
*/
protected function addQuotaEntry($size, $count = 1)
{
// if (! file_exists($this->rootdir . 'maildirsize')) {
// TODO: should get file handler from calculateQuota
// }
file_put_contents($this->rootdir . 'maildirsize', "$size $count\n", FILE_APPEND);
}
/**
* check if storage is currently over quota
*
* @see calculateQuota()
*
* @param bool $detailedResponse return known data of quota and current size and message count
* @param bool $forceRecalc
* @return bool|array over quota state or detailed response
*/
public function checkQuota($detailedResponse = false, $forceRecalc = false)
{
$result = $this->calculateQuota($forceRecalc);
return $detailedResponse ? $result : $result['over_quota'];
}
}
laminas-mail/src/Storage/Mbox.php 0000644 00000030767 15240152661 0012740 0 ustar 00 <?php
namespace Laminas\Mail\Storage;
use Laminas\Mail\Storage\Exception\ExceptionInterface;
use Laminas\Mail\Storage\Message\File;
use Laminas\Mail\Storage\Message\MessageInterface;
use Laminas\Stdlib\ErrorHandler;
use function array_combine;
use function count;
use function fclose;
use function fgets;
use function filemtime;
use function fopen;
use function fseek;
use function ftell;
use function is_dir;
use function is_resource;
use function is_subclass_of;
use function range;
use function str_starts_with;
use function stream_get_contents;
use function strlen;
use function strtolower;
use function trim;
use const E_WARNING;
class Mbox extends AbstractStorage
{
/**
* file handle to mbox file
*
* @var null|resource
*/
protected $fh;
/**
* filename of mbox file for __wakeup
*
* @var string
*/
protected $filename;
/**
* modification date of mbox file for __wakeup
*
* @var int
*/
protected $filemtime;
/**
* start and end position of messages as array('start' => start, 'separator' => headersep, 'end' => end)
*
* @var array
*/
protected $positions;
/**
* used message class, change it in an extended class to extend the returned message class
*
* @var class-string<MessageInterface>
*/
protected $messageClass = File::class;
/**
* end of Line for messages
*
* @var string|null
*/
// phpcs:ignore WebimpressCodingStandard.NamingConventions.ValidVariableName.NotCamelCapsProperty
protected $messageEOL;
/**
* Count messages all messages in current box
*
* @return int number of messages
* @throws ExceptionInterface
*/
public function countMessages()
{
return count($this->positions);
}
/**
* Get a list of messages with number and size
*
* @param int|null $id number of message or null for all messages
* @return int|array size of given message of list with all messages as array(num => size)
*/
public function getSize($id = 0)
{
if ($id) {
$pos = $this->positions[$id - 1];
return $pos['end'] - $pos['start'];
}
$result = [];
foreach ($this->positions as $num => $pos) {
$result[$num + 1] = $pos['end'] - $pos['start'];
}
return $result;
}
/**
* Get positions for mail message or throw exception if id is invalid
*
* @param int $id number of message
* @throws Exception\InvalidArgumentException
* @return array positions as in positions
*/
protected function getPos($id)
{
if (! isset($this->positions[$id - 1])) {
throw new Exception\InvalidArgumentException('id does not exist');
}
return $this->positions[$id - 1];
}
/**
* Fetch a message
*
* @param int $id number of message
* @return File
* @throws ExceptionInterface
*/
public function getMessage($id)
{
// TODO that's ugly, would be better to let the message class decide
if (
is_subclass_of($this->messageClass, File::class)
|| strtolower($this->messageClass) === strtolower(File::class)
) {
// TODO top/body lines
$messagePos = $this->getPos($id);
$messageClassParams = [
'file' => $this->fh,
'startPos' => $messagePos['start'],
'endPos' => $messagePos['end'],
];
if (isset($this->messageEOL)) {
$messageClassParams['EOL'] = $this->messageEOL;
}
return new $this->messageClass($messageClassParams);
}
/** @todo Uncomment once we know how to count body lines */
// $bodyLines = 0;
$message = $this->getRawHeader($id);
/* Once we know how to count body lines, we should uncomment the
* following, which would append the body content to the headers.
*
if ($bodyLines) {
$message .= "\n";
while ($bodyLines-- && ftell($this->fh) < $this->positions[$id - 1]['end']) {
$message .= fgets($this->fh);
}
}
*/
return new $this->messageClass(['handler' => $this, 'id' => $id, 'headers' => $message]);
}
/**
* Get raw header of message or part
*
* @param int $id number of message
* @param null|array|string $part path to part or null for message header
* @param int $topLines include this many lines with header (after an empty line)
* @return string raw header
* @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface
* @throws ExceptionInterface
*/
public function getRawHeader($id, $part = null, $topLines = 0)
{
if ($part !== null) {
// TODO: implement
throw new Exception\RuntimeException('not implemented');
}
$messagePos = $this->getPos($id);
// TODO: toplines
return stream_get_contents($this->fh, $messagePos['separator'] - $messagePos['start'], $messagePos['start']);
}
/**
* Get raw content of message or part
*
* @param int $id number of message
* @param null|array|string $part path to part or null for message content
* @return string raw content
* @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface
* @throws ExceptionInterface
*/
public function getRawContent($id, $part = null)
{
if ($part !== null) {
// TODO: implement
throw new Exception\RuntimeException('not implemented');
}
$messagePos = $this->getPos($id);
return stream_get_contents($this->fh, $messagePos['end'] - $messagePos['separator'], $messagePos['separator']);
}
/**
* Create instance with parameters
* Supported parameters are:
* - filename filename of mbox file
*
* @param array|object|Config $params mail reader specific parameters
* @throws Exception\InvalidArgumentException
*/
public function __construct($params)
{
$params = ParamsNormalizer::normalizeParams($params);
if (! isset($params['filename'])) {
throw new Exception\InvalidArgumentException('no valid filename given in params');
}
if (isset($params['messageEOL'])) {
$this->messageEOL = (string) $params['messageEOL'];
}
$this->openMboxFile((string) $params['filename']);
$this->has['top'] = true;
$this->has['uniqueid'] = false;
}
/**
* check if given file is a mbox file
*
* if $file is a resource its file pointer is moved after the first line
*
* @param resource|string $file stream resource of name of file
* @param bool $fileIsString file is string or resource
* @return bool file is mbox file
*/
protected function isMboxFile($file, $fileIsString = true)
{
if ($fileIsString) {
ErrorHandler::start(E_WARNING);
$file = fopen($file, 'r');
ErrorHandler::stop();
if (! $file) {
return false;
}
} else {
fseek($file, 0);
}
$result = false;
$line = fgets($file) ?: '';
if (str_starts_with($line, 'From ')) {
$result = true;
}
if ($fileIsString) {
ErrorHandler::start(E_WARNING);
fclose($file);
ErrorHandler::stop();
}
return $result;
}
/**
* open given file as current mbox file
*
* @param string $filename filename of mbox file
* @throws Exception\RuntimeException
* @throws Exception\InvalidArgumentException
*/
protected function openMboxFile($filename)
{
if ($this->fh) {
$this->close();
}
if (is_dir($filename)) {
throw new Exception\InvalidArgumentException('file is not a valid mbox file');
}
ErrorHandler::start();
$this->fh = fopen($filename, 'r');
$error = ErrorHandler::stop();
if (! $this->fh) {
throw new Exception\RuntimeException('cannot open mbox file', 0, $error);
}
$this->filename = $filename;
$this->filemtime = filemtime($this->filename);
if (! $this->isMboxFile($this->fh, false)) {
ErrorHandler::start(E_WARNING);
fclose($this->fh);
$error = ErrorHandler::stop();
throw new Exception\InvalidArgumentException('file is not a valid mbox format', 0, $error);
}
$messagePos = ['start' => ftell($this->fh), 'separator' => 0, 'end' => 0];
while (($line = fgets($this->fh)) !== false) {
if (str_starts_with($line, 'From ')) {
$messagePos['end'] = ftell($this->fh) - strlen($line) - 2; // + newline
if (! $messagePos['separator']) {
$messagePos['separator'] = $messagePos['end'];
}
$this->positions[] = $messagePos;
$messagePos = ['start' => ftell($this->fh), 'separator' => 0, 'end' => 0];
}
if (! $messagePos['separator'] && ! trim($line)) {
$messagePos['separator'] = ftell($this->fh);
}
}
$messagePos['end'] = ftell($this->fh);
if (! $messagePos['separator']) {
$messagePos['separator'] = $messagePos['end'];
}
$this->positions[] = $messagePos;
}
/**
* Close resource for mail lib. If you need to control, when the resource
* is closed. Otherwise the destructor would call this.
*/
public function close()
{
if (is_resource($this->fh)) {
fclose($this->fh);
}
$this->positions = [];
}
/**
* Waste some CPU cycles doing nothing.
*
* @return bool always return true
*/
public function noop()
{
return true;
}
/**
* stub for not supported message deletion
*
* @param int $id message number
* @throws Exception\RuntimeException
*/
public function removeMessage($id)
{
throw new Exception\RuntimeException('mbox is read-only');
}
/**
* get unique id for one or all messages
*
* Mbox does not support unique ids (yet) - it's always the same as the message number.
* That shouldn't be a problem, because we can't change mbox files. Therefor the message
* number is save enough.
*
* @param int|null $id message number
* @return array|string message number for given message or all messages as array
* @throws ExceptionInterface
*/
public function getUniqueId($id = null)
{
if ($id) {
// check if id exists
$this->getPos($id);
return $id;
}
$range = range(1, $this->countMessages());
return array_combine($range, $range);
}
/**
* get a message number from a unique id
*
* I.e. if you have a webmailer that supports deleting messages you should use unique ids
* as parameter and use this method to translate it to message number right before calling removeMessage()
*
* @param string $id unique id
* @return int message number
* @throws ExceptionInterface
*/
public function getNumberByUniqueId($id)
{
// check if id exists
$this->getPos($id);
return $id;
}
/**
* magic method for serialize()
*
* with this method you can cache the mbox class
*
* @return array name of variables
*/
public function __sleep()
{
return ['filename', 'positions', 'filemtime'];
}
/**
* magic method for unserialize()
*
* with this method you can cache the mbox class
* for cache validation the mtime of the mbox file is used
*
* @throws Exception\RuntimeException
*/
public function __wakeup()
{
ErrorHandler::start();
$filemtime = filemtime($this->filename);
ErrorHandler::stop();
if ($this->filemtime != $filemtime) {
$this->close();
$this->openMboxFile($this->filename);
} else {
ErrorHandler::start();
$this->fh = fopen($this->filename, 'r');
$error = ErrorHandler::stop();
if (! $this->fh) {
throw new Exception\RuntimeException('cannot open mbox file', 0, $error);
}
}
}
}
laminas-mail/src/Storage/Part.php 0000644 00000032360 15240152661 0012730 0 ustar 00 <?php
namespace Laminas\Mail\Storage;
use ArrayIterator;
use Laminas\Mail\Header\HeaderInterface;
use Laminas\Mail\Headers;
use Laminas\Mime;
use Laminas\Mime\Exception\RuntimeException;
use RecursiveIterator;
use ReturnTypeWillChange;
use Stringable;
use function array_map;
use function count;
use function current;
use function implode;
use function is_array;
use function iterator_to_array;
use function preg_replace;
use function stripos;
use function strlen;
use function strtolower;
use function trim;
class Part implements RecursiveIterator, Part\PartInterface, Stringable
{
/**
* Headers of the part
*
* @var Headers|null
*/
protected $headers;
/**
* raw part body
*
* @var null|string
*/
protected $content;
/**
* toplines as fetched with headers
*
* @var string
*/
protected $topLines = '';
/**
* parts of multipart message
*
* @var array
*/
protected $parts = [];
/**
* count of parts of a multipart message
*
* @var null|int
*/
protected $countParts;
/**
* current position of iterator
*
* @var int
*/
protected $iterationPos = 1;
/**
* mail handler, if late fetch is active
*
* @var null|AbstractStorage
*/
protected $mail;
/**
* message number for mail handler
*
* @var int
*/
protected $messageNum = 0;
/**
* Public constructor
*
* Part supports different sources for content. The possible params are:
* - handler an instance of AbstractStorage for late fetch
* - id number of message for handler
* - raw raw content with header and body as string
* - headers headers as array (name => value) or string, if a content part is found it's used as toplines
* - noToplines ignore content found after headers in param 'headers'
* - content content as string
* - strict strictly parse raw content
*
* @param array $params full message with or without headers
* @throws Exception\InvalidArgumentException
*/
public function __construct(array $params)
{
if (isset($params['handler'])) {
if (! $params['handler'] instanceof AbstractStorage) {
throw new Exception\InvalidArgumentException('handler is not a valid mail handler');
}
if (! isset($params['id'])) {
throw new Exception\InvalidArgumentException('need a message id with a handler');
}
$this->mail = $params['handler'];
$this->messageNum = $params['id'];
}
$params['strict'] ??= false;
if (isset($params['raw'])) {
Mime\Decode::splitMessage(
$params['raw'],
$this->headers,
$this->content,
Mime\Mime::LINEEND,
$params['strict']
);
} elseif (isset($params['headers'])) {
if (is_array($params['headers'])) {
$this->headers = new Headers();
$this->headers->addHeaders($params['headers']);
} else {
if (empty($params['noToplines'])) {
Mime\Decode::splitMessage($params['headers'], $this->headers, $this->topLines);
} else {
$this->headers = Headers::fromString($params['headers']);
}
}
if (isset($params['content'])) {
$this->content = $params['content'];
}
}
}
/**
* Check if part is a multipart message
*
* @return bool if part is multipart
*/
public function isMultipart()
{
try {
return stripos($this->contentType, 'multipart/') === 0;
} catch (Exception\ExceptionInterface) {
return false;
}
}
/**
* Body of part
*
* If part is multipart the raw content of this part with all sub parts is returned
*
* @throws Exception\RuntimeException
* @return string body
*/
public function getContent()
{
if ($this->content !== null) {
return $this->content;
}
if ($this->mail) {
return $this->mail->getRawContent($this->messageNum);
}
throw new Exception\RuntimeException('no content');
}
/**
* Return size of part
*
* Quite simple implemented currently (not decoding). Handle with care.
*
* @return int size
*/
public function getSize()
{
return strlen($this->getContent());
}
/**
* Cache content and split in parts if multipart
*
* @throws Exception\RuntimeException
* @return null
*/
protected function cacheContent()
{
// caching content if we can't fetch parts
if ($this->content === null && $this->mail) {
$this->content = $this->mail->getRawContent($this->messageNum);
}
if (! $this->isMultipart()) {
return;
}
// split content in parts
$boundary = $this->getHeaderField('content-type', 'boundary');
if (! $boundary) {
throw new Exception\RuntimeException('no boundary found in content type to split message');
}
$parts = Mime\Decode::splitMessageStruct($this->content, $boundary);
if ($parts === null) {
return;
}
$counter = 1;
foreach ($parts as $part) {
$this->parts[$counter++] = new static(['headers' => $part['header'], 'content' => $part['body']]);
}
}
/**
* Get part of multipart message
*
* @param int $num number of part starting with 1 for first part
* @throws Exception\RuntimeException
* @return Part wanted part
*/
public function getPart($num)
{
if (isset($this->parts[$num])) {
return $this->parts[$num];
}
if (! $this->mail && $this->content === null) {
throw new Exception\RuntimeException('part not found');
}
// if ($this->mail && $this->mail->hasFetchPart) {
// TODO: fetch part
// return
// }
$this->cacheContent();
if (! isset($this->parts[$num])) {
throw new Exception\RuntimeException('part not found');
}
return $this->parts[$num];
}
/**
* Count parts of a multipart part
*
* @return int number of sub-parts
*/
public function countParts()
{
if ($this->countParts) {
return $this->countParts;
}
$this->countParts = count($this->parts);
if ($this->countParts) {
return $this->countParts;
}
// if ($this->mail && $this->mail->hasFetchPart) {
// TODO: fetch part
// return
// }
$this->cacheContent();
$this->countParts = count($this->parts);
return $this->countParts;
}
/**
* Access headers collection
*
* Lazy-loads if not already attached.
*
* @return Headers
* @throws Exception\RuntimeException
*/
public function getHeaders()
{
if (null === $this->headers) {
if ($this->mail) {
$part = $this->mail->getRawHeader($this->messageNum);
$this->headers = Headers::fromString($part);
} else {
$this->headers = new Headers();
}
}
if (! $this->headers instanceof Headers) {
throw new Exception\RuntimeException(
'$this->headers must be an instance of Headers'
);
}
return $this->headers;
}
/**
* Get a header in specified format
*
* Internally headers that occur more than once are saved as array, all other as string. If $format
* is set to string implode is used to concat the values (with Mime::LINEEND as delim).
*
* @param string $name name of header, matches case-insensitive, but camel-case is replaced with dashes
* @param string $format change type of return value to 'string' or 'array'
* @throws Exception\InvalidArgumentException
* @return string|array|HeaderInterface|ArrayIterator value of header in wanted or internal format
*/
public function getHeader($name, $format = null)
{
$header = $this->getHeaders()->get($name);
if ($header === false) {
$lowerName = strtolower(preg_replace('%([a-z])([A-Z])%', '\1-\2', $name));
$header = $this->getHeaders()->get($lowerName);
if ($header === false) {
throw new Exception\InvalidArgumentException(
"Header with Name $name or $lowerName not found"
);
}
}
switch ($format) {
case 'string':
if ($header instanceof HeaderInterface) {
$return = $header->getFieldValue(HeaderInterface::FORMAT_RAW);
} else {
$return = trim(implode(
Mime\Mime::LINEEND,
array_map(static fn($header): string
=> $header->getFieldValue(HeaderInterface::FORMAT_RAW), iterator_to_array($header))
), Mime\Mime::LINEEND);
}
break;
case 'array':
if ($header instanceof HeaderInterface) {
$return = [$header->getFieldValue()];
} else {
$return = [];
foreach ($header as $h) {
$return[] = $h->getFieldValue(HeaderInterface::FORMAT_RAW);
}
}
break;
default:
$return = $header;
}
return $return;
}
/**
* Get a specific field from a header like content type or all fields as array
*
* If the header occurs more than once, only the value from the first header
* is returned.
*
* Throws an Exception if the requested header does not exist. If
* the specific header field does not exist, returns null.
*
* @param string $name name of header, like in getHeader()
* @param string $wantedPart the wanted part, default is first, if null an array with all parts is returned
* @param string $firstName key name for the first part
* @return string|array wanted part or all parts as array($firstName => firstPart, partname => value)
* @throws RuntimeException
*/
public function getHeaderField($name, $wantedPart = '0', $firstName = '0')
{
return Mime\Decode::splitHeaderField(current($this->getHeader($name, 'array')), $wantedPart, $firstName);
}
/**
* Getter for mail headers - name is matched in lowercase
*
* This getter is short for Part::getHeader($name, 'string')
*
* @see Part::getHeader()
*
* @param string $name header name
* @return string value of header
* @throws Exception\ExceptionInterface
*/
public function __get($name)
{
return $this->getHeader($name, 'string');
}
/**
* Isset magic method proxy to hasHeader
*
* This method is short syntax for Part::hasHeader($name);
*
* @see Part::hasHeader
*
* @param string $name
* @return bool
*/
public function __isset($name)
{
return $this->getHeaders()->has($name);
}
/**
* magic method to get content of part
*
* @return string content
*/
public function __toString(): string
{
return $this->getContent();
}
/**
* implements RecursiveIterator::hasChildren()
*
* @return bool current element has children/is multipart
*/
#[ReturnTypeWillChange]
public function hasChildren()
{
$current = $this->current();
return $current && $current instanceof self && $current->isMultipart();
}
/**
* implements RecursiveIterator::getChildren()
*
* @return Part same as self::current()
*/
#[ReturnTypeWillChange]
public function getChildren()
{
return $this->current();
}
/**
* implements Iterator::valid()
*
* @return bool check if there's a current element
*/
#[ReturnTypeWillChange]
public function valid()
{
if ($this->countParts === null) {
$this->countParts();
}
return $this->iterationPos && $this->iterationPos <= $this->countParts;
}
/**
* implements Iterator::next()
*/
#[ReturnTypeWillChange]
public function next()
{
++$this->iterationPos;
}
/**
* implements Iterator::key()
*
* @return string key/number of current part
*/
#[ReturnTypeWillChange]
public function key()
{
return $this->iterationPos;
}
/**
* implements Iterator::current()
*
* @return Part current part
*/
#[ReturnTypeWillChange]
public function current()
{
return $this->getPart($this->iterationPos);
}
/**
* implements Iterator::rewind()
*/
#[ReturnTypeWillChange]
public function rewind()
{
$this->countParts();
$this->iterationPos = 1;
}
}
laminas-mail/src/Storage/Folder/Mbox.php 0000644 00000016351 15240152661 0014144 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Folder;
use Laminas\Mail\Storage;
use Laminas\Mail\Storage\Exception;
use Laminas\Mail\Storage\ParamsNormalizer;
use Laminas\Stdlib\ErrorHandler;
use function array_merge;
use function closedir;
use function explode;
use function is_dir;
use function is_file;
use function opendir;
use function readdir;
use function rtrim;
use function sprintf;
use function str_contains;
use function trim;
use const DIRECTORY_SEPARATOR;
use const E_WARNING;
class Mbox extends Storage\Mbox implements FolderInterface
{
/**
* Storage\Folder root folder for folder structure
*
* @var Storage\Folder
*/
protected $rootFolder;
/**
* rootdir of folder structure
*
* @var string
*/
protected $rootdir;
/**
* name of current folder
*
* @var string
*/
protected $currentFolder;
/**
* Create instance with parameters
*
* Disallowed parameters are:
* - filename use \Laminas\Mail\Storage\Mbox for a single file
*
* Supported parameters are:
*
* - dirname rootdir of mbox structure
* - folder initial selected folder, default is 'INBOX'
*
* @param array|object $params Array, iterable object, or stdClass object
* with reader specific parameters
* @throws Exception\InvalidArgumentException
*/
public function __construct($params)
{
$params = ParamsNormalizer::normalizeParams($params);
if (isset($params['filename'])) {
throw new Exception\InvalidArgumentException(sprintf('use %s for a single file', Storage\Mbox::class));
}
if (! isset($params['dirname'])) {
throw new Exception\InvalidArgumentException('no dirname provided in params');
}
$dirname = (string) $params['dirname'];
if (! is_dir($dirname)) {
throw new Exception\InvalidArgumentException('$dirname provided in params is not a directory');
}
$this->rootdir = rtrim($dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
$folder = $params['folder'] ?? 'INBOX';
$this->buildFolderTree($this->rootdir);
$this->selectFolder((string) $folder);
$this->has['top'] = true;
$this->has['uniqueid'] = false;
}
/**
* find all subfolders and mbox files for folder structure
*
* Result is save in Storage\Folder instances with the root in $this->rootFolder.
* $parentFolder and $parentGlobalName are only used internally for recursion.
*
* @param string $currentDir call with root dir, also used for recursion.
* @param Storage\Folder|null $parentFolder used for recursion
* @param string $parentGlobalName used for recursion
* @throws Exception\InvalidArgumentException
*/
protected function buildFolderTree($currentDir, $parentFolder = null, $parentGlobalName = '')
{
if (! $parentFolder) {
$this->rootFolder = new Storage\Folder('/', '/', false);
$parentFolder = $this->rootFolder;
}
ErrorHandler::start(E_WARNING);
$dh = opendir($currentDir);
ErrorHandler::stop();
if (! $dh) {
throw new Exception\InvalidArgumentException("can't read dir $currentDir");
}
while (($entry = readdir($dh)) !== false) {
// ignore hidden files for mbox
if ($entry[0] == '.') {
continue;
}
$absoluteEntry = $currentDir . $entry;
$globalName = $parentGlobalName . DIRECTORY_SEPARATOR . $entry;
if (is_file($absoluteEntry) && $this->isMboxFile($absoluteEntry)) {
$parentFolder->$entry = new Storage\Folder($entry, $globalName);
continue;
}
if (! is_dir($absoluteEntry)) { /* || $entry == '.' || $entry == '..' */
continue;
}
$folder = new Storage\Folder($entry, $globalName, false);
$parentFolder->$entry = $folder;
$this->buildFolderTree($absoluteEntry . DIRECTORY_SEPARATOR, $folder, $globalName);
}
closedir($dh);
}
/**
* get root folder or given folder
*
* @param string $rootFolder get folder structure for given folder, else root
* @return Storage\Folder root or wanted folder
* @throws Exception\InvalidArgumentException
*/
public function getFolders($rootFolder = null)
{
if (! $rootFolder) {
return $this->rootFolder;
}
$currentFolder = $this->rootFolder;
$subname = trim($rootFolder, DIRECTORY_SEPARATOR);
while ($currentFolder) {
if (str_contains($subname, DIRECTORY_SEPARATOR)) {
[$entry, $subname] = explode(DIRECTORY_SEPARATOR, $subname, 2);
} else {
$entry = $subname;
$subname = null;
}
$currentFolder = $currentFolder->$entry;
if (! $subname) {
break;
}
}
if ($currentFolder->getGlobalName() != DIRECTORY_SEPARATOR . trim($rootFolder, DIRECTORY_SEPARATOR)) {
throw new Exception\InvalidArgumentException("folder $rootFolder not found");
}
return $currentFolder;
}
/**
* select given folder
*
* folder must be selectable!
*
* @param Storage\Folder|string $globalName global name of folder or
* instance for subfolder
* @throws Exception\RuntimeException
*/
public function selectFolder($globalName)
{
$this->currentFolder = (string) $globalName;
// getting folder from folder tree for validation
$folder = $this->getFolders($this->currentFolder);
try {
$this->openMboxFile($this->rootdir . $folder->getGlobalName());
} catch (Exception\ExceptionInterface $e) {
// check what went wrong
if (! $folder->isSelectable()) {
throw new Exception\RuntimeException("{$this->currentFolder} is not selectable", 0, $e);
}
// seems like file has vanished; rebuilding folder tree - but it's still an exception
$this->buildFolderTree($this->rootdir);
throw new Exception\RuntimeException(
'seems like the mbox file has vanished; I have rebuilt the folder tree; '
. 'search for another folder and try again',
0,
$e
);
}
}
/**
* get Storage\Folder instance for current folder
*
* @return string instance of current folder
* @throws Exception\ExceptionInterface
*/
public function getCurrentFolder()
{
return $this->currentFolder;
}
/**
* magic method for serialize()
*
* with this method you can cache the mbox class
*
* @return array name of variables
*/
public function __sleep()
{
return array_merge(parent::__sleep(), ['currentFolder', 'rootFolder', 'rootdir']);
}
/**
* magic method for unserialize(), with this method you can cache the mbox class
*/
public function __wakeup()
{
// if cache is stall selectFolder() rebuilds the tree on error
parent::__wakeup();
}
}
laminas-mail/src/Storage/Folder/FolderInterface.php 0000644 00000001561 15240152661 0016270 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Folder;
use Laminas\Mail\Storage\Exception\ExceptionInterface;
use Laminas\Mail\Storage\Folder;
interface FolderInterface
{
/**
* get root folder or given folder
*
* @param string $rootFolder get folder structure for given folder, else root
* @return Folder root or wanted folder
*/
public function getFolders($rootFolder = null);
/**
* select given folder
*
* folder must be selectable!
*
* @param Folder|string $globalName global name of folder or instance for subfolder
* @throws ExceptionInterface
*/
public function selectFolder($globalName);
/**
* get Laminas\Mail\Storage\Folder instance for current folder
*
* @return string instance of current folder
* @throws ExceptionInterface
*/
public function getCurrentFolder();
}
laminas-mail/src/Storage/Folder/Maildir.php 0000644 00000016472 15240152661 0014624 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Folder;
use Laminas\Mail\Storage;
use Laminas\Mail\Storage\Exception;
use Laminas\Mail\Storage\Exception\InvalidArgumentException;
use Laminas\Mail\Storage\Folder;
use Laminas\Mail\Storage\ParamsNormalizer;
use Laminas\Stdlib\ErrorHandler;
use function array_pop;
use function array_push;
use function closedir;
use function explode;
use function is_dir;
use function opendir;
use function readdir;
use function rtrim;
use function sort;
use function str_contains;
use function str_starts_with;
use function strlen;
use function substr;
use function trim;
use const DIRECTORY_SEPARATOR;
use const E_WARNING;
class Maildir extends Storage\Maildir implements FolderInterface
{
/**
* root folder for folder structure
*
* @var Storage\Folder
*/
protected $rootFolder;
/**
* rootdir of folder structure
*
* @var string
*/
protected $rootdir;
/**
* name of current folder
*
* @var string
*/
protected $currentFolder;
/**
* delim char for subfolders
*
* @var string
*/
protected $delim;
/**
* Create instance with parameters
*
* Supported parameters are:
*
* - dirname rootdir of maildir structure
* - delim delim char for folder structure, default is '.'
* - folder initial selected folder, default is 'INBOX'
*
* @param object|array $params mail reader specific parameters
* @throws Exception\InvalidArgumentException
*/
public function __construct($params)
{
$params = ParamsNormalizer::normalizeParams($params);
if (! isset($params['dirname'])) {
throw new Exception\InvalidArgumentException('no dirname provided in params');
}
$dirname = (string) $params['dirname'];
if (! is_dir($dirname)) {
throw new Exception\InvalidArgumentException('$dirname provided in params is not a directory');
}
$this->rootdir = rtrim($dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
$delim = $params['delim'] ?? '.';
$this->delim = (string) $delim;
$folder = $params['folder'] ?? 'INBOX';
$this->buildFolderTree();
$this->selectFolder((string) $folder);
$this->has['top'] = true;
$this->has['flags'] = true;
}
/**
* find all subfolders and mbox files for folder structure
*
* Result is save in Storage\Folder instances with the root in $this->rootFolder.
* $parentFolder and $parentGlobalName are only used internally for recursion.
*
* @throws Exception\RuntimeException
*/
protected function buildFolderTree()
{
$this->rootFolder = new Storage\Folder('/', '/', false);
$this->rootFolder->INBOX = new Storage\Folder('INBOX', 'INBOX', true);
ErrorHandler::start(E_WARNING);
$dh = opendir($this->rootdir);
$error = ErrorHandler::stop();
if (! $dh) {
throw new Exception\RuntimeException("can't read folders in maildir", 0, $error);
}
$dirs = [];
while (($entry = readdir($dh)) !== false) {
// maildir++ defines folders must start with .
if ($entry[0] != '.' || $entry == '.' || $entry == '..') {
continue;
}
if ($this->isMaildir($this->rootdir . $entry)) {
$dirs[] = $entry;
}
}
closedir($dh);
sort($dirs);
$stack = [null];
$folderStack = [null];
$parentFolder = $this->rootFolder;
$parent = '.';
foreach ($dirs as $dir) {
do {
if (str_starts_with($dir, $parent)) {
$local = substr($dir, strlen((string) $parent));
if (str_contains($local, $this->delim)) {
throw new Exception\RuntimeException('error while reading maildir');
}
array_push($stack, $parent);
$parent = $dir . $this->delim;
$folder = new Storage\Folder($local, substr($dir, 1), true);
$parentFolder->$local = $folder;
array_push($folderStack, $parentFolder);
$parentFolder = $folder;
break;
} elseif ($stack) {
$parent = array_pop($stack);
$parentFolder = array_pop($folderStack);
}
} while ($stack);
if (! $stack) {
throw new Exception\RuntimeException('error while reading maildir');
}
}
}
/**
* get root folder or given folder
*
* @param string $rootFolder get folder structure for given folder, else root
* @throws InvalidArgumentException
* @return Folder root or wanted folder
*/
public function getFolders($rootFolder = null)
{
if (! $rootFolder || $rootFolder == 'INBOX') {
return $this->rootFolder;
}
// rootdir is same as INBOX in maildir
if (str_starts_with($rootFolder, 'INBOX' . $this->delim)) {
$rootFolder = substr($rootFolder, 6);
}
$currentFolder = $this->rootFolder;
$subname = trim($rootFolder, $this->delim);
while ($currentFolder) {
if (str_contains($subname, $this->delim)) {
[$entry, $subname] = explode($this->delim, $subname, 2);
} else {
$entry = $subname;
$subname = null;
}
$currentFolder = $currentFolder->$entry;
if (! $subname) {
break;
}
}
if ($currentFolder->getGlobalName() != rtrim($rootFolder, $this->delim)) {
throw new Exception\InvalidArgumentException("folder $rootFolder not found");
}
return $currentFolder;
}
/**
* select given folder
*
* folder must be selectable!
*
* @param Storage\Folder|string $globalName global name of folder or
* instance for subfolder
* @throws Exception\RuntimeException
*/
public function selectFolder($globalName)
{
$this->currentFolder = (string) $globalName;
// getting folder from folder tree for validation
$folder = $this->getFolders($this->currentFolder);
try {
$this->openMaildir($this->rootdir . '.' . $folder->getGlobalName());
} catch (Exception\ExceptionInterface $e) {
// check what went wrong
if (! $folder->isSelectable()) {
throw new Exception\RuntimeException("{$this->currentFolder} is not selectable", 0, $e);
}
// seems like file has vanished; rebuilding folder tree - but it's still an exception
$this->buildFolderTree();
throw new Exception\RuntimeException(
'seems like the maildir has vanished; I have rebuilt the folder tree; '
. 'search for another folder and try again',
0,
$e
);
}
}
/**
* get Storage\Folder instance for current folder
*
* @return string instance of current folder
*/
public function getCurrentFolder()
{
return $this->currentFolder;
}
}
laminas-mail/src/Storage/Maildir.php 0000644 00000031320 15240152661 0013376 0 ustar 00 <?php
namespace Laminas\Mail\Storage;
use Laminas\Mail;
use Laminas\Mail\Storage\Exception\ExceptionInterface;
use Laminas\Mail\Storage\Message\File;
use Laminas\Stdlib\ErrorHandler;
use function array_flip;
use function closedir;
use function count;
use function ctype_digit;
use function explode;
use function fclose;
use function feof;
use function fgets;
use function file_exists;
use function filesize;
use function fopen;
use function is_array;
use function is_dir;
use function is_file;
use function is_subclass_of;
use function opendir;
use function readdir;
use function sprintf;
use function str_contains;
use function strcmp;
use function stream_get_contents;
use function strlen;
use function substr;
use function trim;
use function usort;
use const E_WARNING;
class Maildir extends AbstractStorage
{
/**
* used message class, change it in an extended class to extend the returned message class
*
* @var class-string<Mail\Storage\Message\MessageInterface>
*/
protected $messageClass = File::class;
/**
* data of found message files in maildir dir
*
* @var array
*/
protected $files = [];
/**
* known flag chars in filenames
*
* This list has to be in alphabetical order for setFlags()
*
* @var array
*/
protected static $knownFlags = [
'D' => Mail\Storage::FLAG_DRAFT,
'F' => Mail\Storage::FLAG_FLAGGED,
'P' => Mail\Storage::FLAG_PASSED,
'R' => Mail\Storage::FLAG_ANSWERED,
'S' => Mail\Storage::FLAG_SEEN,
'T' => Mail\Storage::FLAG_DELETED,
];
// TODO: getFlags($id) for fast access if headers are not needed (i.e. just setting flags)?
/**
* Count messages all messages in current box
*
* @param mixed $flags
* @return int number of messages
*/
public function countMessages($flags = null)
{
if ($flags === null) {
return count($this->files);
}
$count = 0;
if (! is_array($flags)) {
foreach ($this->files as $file) {
if (isset($file['flaglookup'][$flags])) {
++$count;
}
}
return $count;
}
$flags = array_flip($flags);
foreach ($this->files as $file) {
foreach ($flags as $flag => $v) {
if (! isset($file['flaglookup'][$flag])) {
continue 2;
}
}
++$count;
}
return $count;
}
/**
* Get one or all fields from file structure. Also checks if message is valid
*
* @param int $id message number
* @param string|null $field wanted field
* @throws Exception\InvalidArgumentException
* @return string|array wanted field or all fields as array
*/
protected function getFileData($id, $field = null)
{
if (! isset($this->files[$id - 1])) {
throw new Exception\InvalidArgumentException('id does not exist');
}
if (! $field) {
return $this->files[$id - 1];
}
if (! isset($this->files[$id - 1][$field])) {
throw new Exception\InvalidArgumentException('field does not exist');
}
return $this->files[$id - 1][$field];
}
/**
* Get a list of messages with number and size
*
* @param int|null $id number of message or null for all messages
* @return int|array size of given message of list with all messages as array(num => size)
*/
public function getSize($id = null)
{
if ($id !== null) {
$filedata = $this->getFileData($id);
return $filedata['size'] ?? filesize($filedata['filename']);
}
$result = [];
foreach ($this->files as $num => $data) {
$result[$num + 1] = $data['size'] ?? filesize($data['filename']);
}
return $result;
}
/**
* Fetch a message
*
* @param int $id number of message
* @return File
* @throws ExceptionInterface
*/
public function getMessage($id)
{
// TODO that's ugly, would be better to let the message class decide
if (
trim($this->messageClass, '\\') === File::class
|| is_subclass_of($this->messageClass, File::class)
) {
return new $this->messageClass([
'file' => $this->getFileData($id, 'filename'),
'flags' => $this->getFileData($id, 'flags'),
]);
}
return new $this->messageClass([
'handler' => $this,
'id' => $id,
'headers' => $this->getRawHeader($id),
'flags' => $this->getFileData($id, 'flags'),
]);
}
/**
* Get raw header of message or part
*
* @param int $id number of message
* @param null|array|string $part path to part or null for message header
* @param int $topLines include this many lines with header (after an empty line)
* @throws Exception\RuntimeException
* @return string raw header
*/
public function getRawHeader($id, $part = null, $topLines = 0)
{
if ($part !== null) {
// TODO: implement
throw new Exception\RuntimeException('not implemented');
}
$fh = fopen($this->getFileData($id, 'filename'), 'r');
$content = '';
while (! feof($fh)) {
$line = fgets($fh);
if (! trim($line)) {
break;
}
$content .= $line;
}
fclose($fh);
return $content;
}
/**
* Get raw content of message or part
*
* @param int $id number of message
* @param null|array|string $part path to part or null for message content
* @throws Exception\RuntimeException
* @return string raw content
*/
public function getRawContent($id, $part = null)
{
if ($part !== null) {
// TODO: implement
throw new Exception\RuntimeException('not implemented');
}
$fh = fopen($this->getFileData($id, 'filename'), 'r');
while (! feof($fh)) {
$line = fgets($fh);
if (! trim($line)) {
break;
}
}
$content = stream_get_contents($fh);
fclose($fh);
return $content;
}
/**
* Create instance with parameters
* Supported parameters are:
* - dirname dirname of mbox file
*
* @param array|object $params Array, iterable object, or stdClass object
* with reader specific parameters
* @throws Exception\InvalidArgumentException
*/
public function __construct($params)
{
$params = ParamsNormalizer::normalizeParams($params);
if (! isset($params['dirname'])) {
throw new Exception\InvalidArgumentException('no dirname provided in params');
}
$dirname = (string) $params['dirname'];
if (! is_dir($dirname)) {
throw new Exception\InvalidArgumentException(sprintf('Maildir "%s" is not a directory', $dirname));
}
if (! $this->isMaildir($dirname)) {
throw new Exception\InvalidArgumentException('invalid maildir given');
}
$this->has['top'] = true;
$this->has['flags'] = true;
$this->openMaildir($dirname);
}
/**
* check if a given dir is a valid maildir
*
* @param string $dirname name of dir
* @return bool dir is valid maildir
*/
protected function isMaildir($dirname)
{
if (file_exists($dirname . '/new') && ! is_dir($dirname . '/new')) {
return false;
}
if (file_exists($dirname . '/tmp') && ! is_dir($dirname . '/tmp')) {
return false;
}
return is_dir($dirname . '/cur');
}
/**
* open given dir as current maildir
*
* @param string $dirname name of maildir
* @throws Exception\RuntimeException
*/
protected function openMaildir($dirname)
{
if ($this->files) {
$this->close();
}
ErrorHandler::start(E_WARNING);
$dh = opendir($dirname . '/cur/');
$error = ErrorHandler::stop();
if (! $dh) {
throw new Exception\RuntimeException('cannot open maildir', 0, $error);
}
$this->getMaildirFiles($dh, $dirname . '/cur/');
closedir($dh);
ErrorHandler::start(E_WARNING);
$dh = opendir($dirname . '/new/');
$error = ErrorHandler::stop();
if (! $dh) {
throw new Exception\RuntimeException('cannot read recent mails in maildir', 0, $error);
}
$this->getMaildirFiles($dh, $dirname . '/new/', [Mail\Storage::FLAG_RECENT]);
closedir($dh);
}
/**
* find all files in opened dir handle and add to maildir files
*
* @param resource $dh dir handle used for search
* @param string $dirname dirname of dir in $dh
* @param array $defaultFlags default flags for given dir
*/
protected function getMaildirFiles($dh, $dirname, $defaultFlags = [])
{
while (($entry = readdir($dh)) !== false) {
if ($entry[0] == '.' || ! is_file($dirname . $entry)) {
continue;
}
if (str_contains($entry, ':')) {
[$uniq, $info] = explode(':', $entry, 2);
} else {
$uniq = $entry;
$info = '';
}
if (str_contains($uniq, ',')) {
[, $size] = explode(',', $uniq, 2);
} else {
$size = '';
}
if (strlen($size) >= 2 && $size[0] === 'S' && $size[1] === '=') {
$size = substr($size, 2);
}
if (! ctype_digit($size)) {
$size = null;
}
if (str_contains($info, ',')) {
[$version, $flags] = explode(',', $info, 2);
} else {
$version = $info;
$flags = '';
}
if ($version !== '2') {
$flags = '';
}
$namedFlags = $defaultFlags;
$length = strlen($flags);
for ($i = 0; $i < $length; ++$i) {
$flag = $flags[$i];
$namedFlags[$flag] = static::$knownFlags[$flag] ?? $flag;
}
$data = [
'uniq' => $uniq,
'flags' => $namedFlags,
'flaglookup' => array_flip($namedFlags),
'filename' => $dirname . $entry,
];
if ($size !== null) {
$data['size'] = (int) $size;
}
$this->files[] = $data;
}
usort($this->files, static fn($a, $b): int => strcmp($a['filename'], $b['filename']));
}
/**
* Close resource for mail lib. If you need to control, when the resource
* is closed. Otherwise the destructor would call this.
*/
public function close()
{
$this->files = [];
}
/**
* Waste some CPU cycles doing nothing.
*
* @return bool always return true
*/
public function noop()
{
return true;
}
/**
* stub for not supported message deletion
*
* @param int $id
* @throws Exception\RuntimeException
*/
public function removeMessage($id)
{
throw new Exception\RuntimeException('maildir is (currently) read-only');
}
/**
* get unique id for one or all messages
*
* if storage does not support unique ids it's the same as the message number
*
* @param int|null $id message number
* @return array|string message number for given message or all messages as array
*/
public function getUniqueId($id = null)
{
if ($id) {
return $this->getFileData($id, 'uniq');
}
$ids = [];
foreach ($this->files as $num => $file) {
$ids[$num + 1] = $file['uniq'];
}
return $ids;
}
/**
* get a message number from a unique id
*
* I.e. if you have a webmailer that supports deleting messages you should use unique ids
* as parameter and use this method to translate it to message number right before calling removeMessage()
*
* @param string $id unique id
* @throws Exception\InvalidArgumentException
* @return int message number
*/
public function getNumberByUniqueId($id)
{
foreach ($this->files as $num => $file) {
if ($file['uniq'] == $id) {
return $num + 1;
}
}
throw new Exception\InvalidArgumentException('unique id not found');
}
}
laminas-mail/src/Storage/Message/File.php 0000644 00000003115 15240152661 0014261 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Message;
use Laminas\Mail\Storage\Exception\ExceptionInterface;
use Laminas\Mail\Storage\Part;
use function array_combine;
class File extends Part\File implements MessageInterface
{
/**
* flags for this message
*
* @var array
*/
protected $flags = [];
/**
* Public constructor
*
* In addition to the parameters of Laminas\Mail\Storage\Part::__construct() this constructor supports:
* - flags array with flags for message, keys are ignored, use constants defined in Laminas\Mail\Storage
*
* @param array $params
* @throws ExceptionInterface
*/
public function __construct(array $params)
{
if (! empty($params['flags'])) {
// set key and value to the same value for easy lookup
$this->flags = array_combine($params['flags'], $params['flags']);
}
parent::__construct($params);
}
/**
* return toplines as found after headers
*
* @return string toplines
*/
public function getTopLines()
{
return $this->topLines;
}
/**
* check if flag is set
*
* @param mixed $flag a flag name, use constants defined in \Laminas\Mail\Storage
* @return bool true if set, otherwise false
*/
public function hasFlag($flag)
{
return isset($this->flags[$flag]);
}
/**
* get all set flags
*
* @return array array with flags, key and value are the same for easy lookup
*/
public function getFlags()
{
return $this->flags;
}
}
laminas-mail/src/Storage/Message/MessageInterface.php 0000644 00000001127 15240152661 0016610 0 ustar 00 <?php
namespace Laminas\Mail\Storage\Message;
interface MessageInterface
{
/**
* return toplines as found after headers
*
* @return string toplines
*/
public function getTopLines();
/**
* check if flag is set
*
* @param mixed $flag a flag name, use constants defined in Laminas\Mail\Storage
* @return bool true if set, otherwise false
*/
public function hasFlag($flag);
/**
* get all set flags
*
* @return array array with flags, key and value are the same for easy lookup
*/
public function getFlags();
}
laminas-mail/src/Storage/ParamsNormalizer.php 0000644 00000001722 15240152661 0015306 0 ustar 00 <?php
namespace Laminas\Mail\Storage;
use Traversable;
use Webmozart\Assert\Assert;
use function get_object_vars;
use function gettype;
use function is_array;
use function is_object;
use function iterator_to_array;
use function sprintf;
/**
* @internal
*/
final class ParamsNormalizer
{
/**
* @return array<string, mixed>
*/
public static function normalizeParams(mixed $params): array
{
if ($params instanceof Traversable) {
$params = iterator_to_array($params);
}
if (is_object($params)) {
$params = get_object_vars($params);
}
if (! is_array($params)) {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid $params provided; expected array|Traversable|object, received %s',
gettype($params)
));
}
Assert::isMap($params, 'Expected $params to have only string keys');
return $params;
}
}
laminas-mail/README.md 0000644 00000006474 15240152661 0010404 0 ustar 00 # laminas-mail
[](https://github.com/laminas/laminas-mail/actions?query=workflow%3A"Continuous+Integration")
> ## 🇷🇺 Русским гражданам
>
> Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм.
>
> У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую.
>
> Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!"
>
> ## 🇺🇸 To Citizens of Russia
>
> We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism.
>
> One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences.
>
> You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!"
`Laminas\Mail` provides generalized functionality to compose and send both text and
MIME-compliant multipart email messages. Mail can be sent with `Laminas\Mail` via
the `Mail\Transport\Sendmail`, `Mail\Transport\Smtp` or the `Mail\Transport\File`
transport. Of course, you can also implement your own transport by implementing
the `Mail\Transport\TransportInterface`.
- File issues at https://github.com/laminas/laminas-mail/issues
- Documentation is at https://docs.laminas.dev/laminas-mail/
laminas-mail/composer.json 0000644 00000005101 15240152661 0011631 0 ustar 00 {
"name": "laminas/laminas-mail",
"description": "Provides generalized functionality to compose and send both text and MIME-compliant multipart e-mail messages",
"keywords": [
"laminas",
"mail"
],
"homepage": "https://laminas.dev",
"license": "BSD-3-Clause",
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"ext-iconv": "*",
"laminas/laminas-loader": "^2.8.0",
"laminas/laminas-mime": "^2.10.0",
"laminas/laminas-stdlib": "^3.11.0",
"laminas/laminas-validator": "^2.23.0",
"symfony/polyfill-mbstring": "^1.16.0",
"webmozart/assert": "^1.11.0",
"symfony/polyfill-intl-idn": "^1.26.0"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"laminas/laminas-crypt": "^3.9.0",
"laminas/laminas-db": "^2.15.0",
"laminas/laminas-servicemanager": "^3.19",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.18.0",
"symfony/process": "^6.0.11",
"vimeo/psalm": "^4.29"
},
"suggest": {
"laminas/laminas-crypt": "^3.8 Crammd5 support in SMTP Auth",
"laminas/laminas-servicemanager": "^3.16 when using SMTP to deliver messages"
},
"config": {
"sort-packages": true,
"allow-plugins": {
"composer/package-versions-deprecated": true,
"dealerdirect/phpcodesniffer-composer-installer": true
},
"platform": {
"php": "8.0.99"
}
},
"extra": {
"laminas": {
"component": "Laminas\\Mail",
"config-provider": "Laminas\\Mail\\ConfigProvider"
}
},
"autoload": {
"psr-4": {
"Laminas\\Mail\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"LaminasTest\\Mail\\": "test/"
}
},
"scripts": {
"check": [
"@cs-check",
"@static-analysis",
"@test"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"static-analysis": "psalm --shepherd --stats",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
},
"support": {
"issues": "https://github.com/laminas/laminas-mail/issues",
"forum": "https://discourse.laminas.dev",
"chat": "https://laminas.dev/chat",
"source": "https://github.com/laminas/laminas-mail",
"docs": "https://docs.laminas.dev/laminas-mail/",
"rss": "https://github.com/laminas/laminas-mail/releases.atom"
}
}
laminas-mail/COPYRIGHT.md 0000644 00000000133 15240152661 0011001 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/)
laminas-mail/composer.lock 0000644 00000537333 15240152661 0011631 0 ustar 00 {
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "21c8501f4e6081d4a793a0da5e924a17",
"packages": [
{
"name": "laminas/laminas-loader",
"version": "2.9.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-loader.git",
"reference": "51ed9c3fa42d1098a9997571730c0cbf42d078d3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-loader/zipball/51ed9c3fa42d1098a9997571730c0cbf42d078d3",
"reference": "51ed9c3fa42d1098a9997571730c0cbf42d078d3",
"shasum": ""
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-loader": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"phpunit/phpunit": "~9.5.25"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Loader\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Autoloading and plugin loading strategies",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"loader"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-loader/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-loader/issues",
"rss": "https://github.com/laminas/laminas-loader/releases.atom",
"source": "https://github.com/laminas/laminas-loader"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-16T12:50:49+00:00"
},
{
"name": "laminas/laminas-mime",
"version": "2.11.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-mime.git",
"reference": "60ec04b755821c79c1987ce291b44e69f2c0831f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-mime/zipball/60ec04b755821c79c1987ce291b44e69f2c0831f",
"reference": "60ec04b755821c79c1987ce291b44e69f2c0831f",
"shasum": ""
},
"require": {
"laminas/laminas-stdlib": "^2.7 || ^3.0",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-mime": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"laminas/laminas-mail": "^2.19.0",
"phpunit/phpunit": "~9.5.25"
},
"suggest": {
"laminas/laminas-mail": "Laminas\\Mail component"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Mime\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Create and parse MIME messages and parts",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"mime"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-mime/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-mime/issues",
"rss": "https://github.com/laminas/laminas-mime/releases.atom",
"source": "https://github.com/laminas/laminas-mime"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-18T08:38:15+00:00"
},
{
"name": "laminas/laminas-servicemanager",
"version": "3.19.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-servicemanager.git",
"reference": "ed160729bb8721127efdaac799f9a298963345b1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/ed160729bb8721127efdaac799f9a298963345b1",
"reference": "ed160729bb8721127efdaac799f9a298963345b1",
"shasum": ""
},
"require": {
"laminas/laminas-stdlib": "^3.2.1",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"psr/container": "^1.0"
},
"conflict": {
"ext-psr": "*",
"laminas/laminas-code": "<3.3.1",
"zendframework/zend-code": "<3.3.1",
"zendframework/zend-servicemanager": "*"
},
"provide": {
"psr/container-implementation": "^1.0"
},
"replace": {
"container-interop/container-interop": "^1.2.0"
},
"require-dev": {
"composer/package-versions-deprecated": "^1.11.99.5",
"laminas/laminas-coding-standard": "~2.4.0",
"laminas/laminas-container-config-test": "^0.7",
"laminas/laminas-dependency-plugin": "^2.2",
"mikey179/vfsstream": "^1.6.11@alpha",
"ocramius/proxy-manager": "^2.14.1",
"phpbench/phpbench": "^1.2.6",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.28"
},
"suggest": {
"ocramius/proxy-manager": "ProxyManager ^2.1.1 to handle lazy initialization of services"
},
"bin": [
"bin/generate-deps-for-config-factory",
"bin/generate-factory-for-class"
],
"type": "library",
"autoload": {
"files": [
"src/autoload.php"
],
"psr-4": {
"Laminas\\ServiceManager\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Factory-Driven Dependency Injection Container",
"homepage": "https://laminas.dev",
"keywords": [
"PSR-11",
"dependency-injection",
"di",
"dic",
"laminas",
"service-manager",
"servicemanager"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-servicemanager/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-servicemanager/issues",
"rss": "https://github.com/laminas/laminas-servicemanager/releases.atom",
"source": "https://github.com/laminas/laminas-servicemanager"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-10T20:59:22+00:00"
},
{
"name": "laminas/laminas-stdlib",
"version": "3.15.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-stdlib.git",
"reference": "63b66bd4b696f024f42616b9d95cdb10e5109c27"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/63b66bd4b696f024f42616b9d95cdb10e5109c27",
"reference": "63b66bd4b696f024f42616b9d95cdb10e5109c27",
"shasum": ""
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-stdlib": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "^2.4.0",
"phpbench/phpbench": "^1.2.6",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.28"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Stdlib\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "SPL extensions, array utilities, error handlers, and more",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"stdlib"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-stdlib/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-stdlib/issues",
"rss": "https://github.com/laminas/laminas-stdlib/releases.atom",
"source": "https://github.com/laminas/laminas-stdlib"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-10T19:10:24+00:00"
},
{
"name": "laminas/laminas-validator",
"version": "2.28.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-validator.git",
"reference": "695bfa40b0a83dc1c5c58bdf74a03fdbeb516c39"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-validator/zipball/695bfa40b0a83dc1c5c58bdf74a03fdbeb516c39",
"reference": "695bfa40b0a83dc1c5c58bdf74a03fdbeb516c39",
"shasum": ""
},
"require": {
"laminas/laminas-servicemanager": "^3.12.0",
"laminas/laminas-stdlib": "^3.13",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"psr/http-message": "^1.0.1"
},
"conflict": {
"zendframework/zend-validator": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "^2.4.0",
"laminas/laminas-db": "^2.15.0",
"laminas/laminas-filter": "^2.23.0",
"laminas/laminas-http": "^2.17.0",
"laminas/laminas-i18n": "^2.19",
"laminas/laminas-session": "^2.13.0",
"laminas/laminas-uri": "^2.10.0",
"phpunit/phpunit": "^9.5.25",
"psalm/plugin-phpunit": "^0.18.0",
"psr/http-client": "^1.0.1",
"psr/http-factory": "^1.0.1",
"vimeo/psalm": "^4.28"
},
"suggest": {
"laminas/laminas-db": "Laminas\\Db component, required by the (No)RecordExists validator",
"laminas/laminas-filter": "Laminas\\Filter component, required by the Digits validator",
"laminas/laminas-i18n": "Laminas\\I18n component to allow translation of validation error messages",
"laminas/laminas-i18n-resources": "Translations of validator messages",
"laminas/laminas-servicemanager": "Laminas\\ServiceManager component to allow using the ValidatorPluginManager and validator chains",
"laminas/laminas-session": "Laminas\\Session component, ^2.8; required by the Csrf validator",
"laminas/laminas-uri": "Laminas\\Uri component, required by the Uri and Sitemap\\Loc validators",
"psr/http-message": "psr/http-message, required when validating PSR-7 UploadedFileInterface instances via the Upload and UploadFile validators"
},
"type": "library",
"extra": {
"laminas": {
"component": "Laminas\\Validator",
"config-provider": "Laminas\\Validator\\ConfigProvider"
}
},
"autoload": {
"psr-4": {
"Laminas\\Validator\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Validation classes for a wide range of domains, and the ability to chain validators to create complex validation criteria",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"validator"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-validator/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-validator/issues",
"rss": "https://github.com/laminas/laminas-validator/releases.atom",
"source": "https://github.com/laminas/laminas-validator"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-11-14T08:50:44+00:00"
},
{
"name": "psr/container",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
"shasum": ""
},
"require": {
"php": ">=7.4.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
"homepage": "https://github.com/php-fig/container",
"keywords": [
"PSR-11",
"container",
"container-interface",
"container-interop",
"psr"
],
"support": {
"issues": "https://github.com/php-fig/container/issues",
"source": "https://github.com/php-fig/container/tree/1.1.2"
},
"time": "2021-11-05T16:50:12+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-message/tree/master"
},
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "639084e360537a19f9ee352433b84ce831f3d2da"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da",
"reference": "639084e360537a19f9ee352433b84ce831f3d2da",
"shasum": ""
},
"require": {
"php": ">=7.1",
"symfony/polyfill-intl-normalizer": "^1.10",
"symfony/polyfill-php72": "^1.10"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Idn\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Laurent Bassin",
"email": "laurent@bassin.info"
},
{
"name": "Trevor Rowbotham",
"email": "trevor.rowbotham@pm.me"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"idn",
"intl",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's Normalizer class and related functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"intl",
"normalizer",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-mbstring": "*"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php72\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "webmozart/assert",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/webmozarts/assert.git",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"php": "^7.2 || ^8.0"
},
"conflict": {
"phpstan/phpstan": "<0.12.20",
"vimeo/psalm": "<4.6.1 || 4.6.2"
},
"require-dev": {
"phpunit/phpunit": "^8.5.13"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.10-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\Assert\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Assertions to validate method input/output with nice error messages.",
"keywords": [
"assert",
"check",
"validate"
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.11.0"
},
"time": "2022-06-03T18:03:27+00:00"
}
],
"packages-dev": [
{
"name": "amphp/amp",
"version": "v2.6.2",
"source": {
"type": "git",
"url": "https://github.com/amphp/amp.git",
"reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb",
"reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"amphp/php-cs-fixer-config": "dev-master",
"amphp/phpunit-util": "^1",
"ext-json": "*",
"jetbrains/phpstorm-stubs": "^2019.3",
"phpunit/phpunit": "^7 | ^8 | ^9",
"psalm/phar": "^3.11@dev",
"react/promise": "^2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
},
"autoload": {
"files": [
"lib/functions.php",
"lib/Internal/functions.php"
],
"psr-4": {
"Amp\\": "lib"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Daniel Lowrey",
"email": "rdlowrey@php.net"
},
{
"name": "Aaron Piotrowski",
"email": "aaron@trowski.com"
},
{
"name": "Bob Weinand",
"email": "bobwei9@hotmail.com"
},
{
"name": "Niklas Keller",
"email": "me@kelunik.com"
}
],
"description": "A non-blocking concurrency framework for PHP applications.",
"homepage": "https://amphp.org/amp",
"keywords": [
"async",
"asynchronous",
"awaitable",
"concurrency",
"event",
"event-loop",
"future",
"non-blocking",
"promise"
],
"support": {
"irc": "irc://irc.freenode.org/amphp",
"issues": "https://github.com/amphp/amp/issues",
"source": "https://github.com/amphp/amp/tree/v2.6.2"
},
"funding": [
{
"url": "https://github.com/amphp",
"type": "github"
}
],
"time": "2022-02-20T17:52:18+00:00"
},
{
"name": "amphp/byte-stream",
"version": "v1.8.1",
"source": {
"type": "git",
"url": "https://github.com/amphp/byte-stream.git",
"reference": "acbd8002b3536485c997c4e019206b3f10ca15bd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd",
"reference": "acbd8002b3536485c997c4e019206b3f10ca15bd",
"shasum": ""
},
"require": {
"amphp/amp": "^2",
"php": ">=7.1"
},
"require-dev": {
"amphp/php-cs-fixer-config": "dev-master",
"amphp/phpunit-util": "^1.4",
"friendsofphp/php-cs-fixer": "^2.3",
"jetbrains/phpstorm-stubs": "^2019.3",
"phpunit/phpunit": "^6 || ^7 || ^8",
"psalm/phar": "^3.11.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"files": [
"lib/functions.php"
],
"psr-4": {
"Amp\\ByteStream\\": "lib"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Aaron Piotrowski",
"email": "aaron@trowski.com"
},
{
"name": "Niklas Keller",
"email": "me@kelunik.com"
}
],
"description": "A stream abstraction to make working with non-blocking I/O simple.",
"homepage": "http://amphp.org/byte-stream",
"keywords": [
"amp",
"amphp",
"async",
"io",
"non-blocking",
"stream"
],
"support": {
"irc": "irc://irc.freenode.org/amphp",
"issues": "https://github.com/amphp/byte-stream/issues",
"source": "https://github.com/amphp/byte-stream/tree/v1.8.1"
},
"funding": [
{
"url": "https://github.com/amphp",
"type": "github"
}
],
"time": "2021-03-30T17:13:30+00:00"
},
{
"name": "composer/package-versions-deprecated",
"version": "1.11.99.5",
"source": {
"type": "git",
"url": "https://github.com/composer/package-versions-deprecated.git",
"reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d",
"reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.1.0 || ^2.0",
"php": "^7 || ^8"
},
"replace": {
"ocramius/package-versions": "1.11.99"
},
"require-dev": {
"composer/composer": "^1.9.3 || ^2.0@dev",
"ext-zip": "^1.13",
"phpunit/phpunit": "^6.5 || ^7"
},
"type": "composer-plugin",
"extra": {
"class": "PackageVersions\\Installer",
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"PackageVersions\\": "src/PackageVersions"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be"
}
],
"description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
"support": {
"issues": "https://github.com/composer/package-versions-deprecated/issues",
"source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-01-17T14:14:24+00:00"
},
{
"name": "composer/pcre",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
"reference": "4482b6409ca6bfc2af043a5711cd21ac3e7a8dfb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/4482b6409ca6bfc2af043a5711cd21ac3e7a8dfb",
"reference": "4482b6409ca6bfc2af043a5711cd21ac3e7a8dfb",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1.3",
"phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Pcre\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "PCRE wrapping library that offers type-safe preg_* replacements.",
"keywords": [
"PCRE",
"preg",
"regex",
"regular expression"
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.0.2"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-11-03T20:24:16+00:00"
},
{
"name": "composer/semver",
"version": "3.3.2",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1.4",
"symfony/phpunit-bridge": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Semver\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
},
{
"name": "Rob Bast",
"email": "rob.bast@gmail.com",
"homepage": "http://robbast.nl"
}
],
"description": "Semver library that offers utilities, version constraint parsing and validation.",
"keywords": [
"semantic",
"semver",
"validation",
"versioning"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.3.2"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-04-01T19:23:25+00:00"
},
{
"name": "composer/xdebug-handler",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
"reference": "ced299686f41dce890debac69273b47ffe98a40c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c",
"reference": "ced299686f41dce890debac69273b47ffe98a40c",
"shasum": ""
},
"require": {
"composer/pcre": "^1 || ^2 || ^3",
"php": "^7.2.5 || ^8.0",
"psr/log": "^1 || ^2 || ^3"
},
"require-dev": {
"phpstan/phpstan": "^1.0",
"phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Composer\\XdebugHandler\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "John Stevenson",
"email": "john-stevenson@blueyonder.co.uk"
}
],
"description": "Restarts a process without Xdebug.",
"keywords": [
"Xdebug",
"performance"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/xdebug-handler/issues",
"source": "https://github.com/composer/xdebug-handler/tree/3.0.3"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-02-25T21:32:43+00:00"
},
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
"version": "v0.7.2",
"source": {
"type": "git",
"url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
"phpcompatibility/php-compatibility": "^9.0"
},
"type": "composer-plugin",
"extra": {
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
"Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Franck Nijhof",
"email": "franck.nijhof@dealerdirect.com",
"homepage": "http://www.frenck.nl",
"role": "Developer / IT Manager"
},
{
"name": "Contributors",
"homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
"homepage": "http://www.dealerdirect.com",
"keywords": [
"PHPCodeSniffer",
"PHP_CodeSniffer",
"code quality",
"codesniffer",
"composer",
"installer",
"phpcbf",
"phpcs",
"plugin",
"qa",
"quality",
"standard",
"standards",
"style guide",
"stylecheck",
"tests"
],
"support": {
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
"time": "2022-02-04T12:51:07+00:00"
},
{
"name": "dnoegel/php-xdg-base-dir",
"version": "v0.1.1",
"source": {
"type": "git",
"url": "https://github.com/dnoegel/php-xdg-base-dir.git",
"reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd",
"reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"require-dev": {
"phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35"
},
"type": "library",
"autoload": {
"psr-4": {
"XdgBaseDir\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "implementation of xdg base directory specification for php",
"support": {
"issues": "https://github.com/dnoegel/php-xdg-base-dir/issues",
"source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1"
},
"time": "2019-12-04T15:06:13+00:00"
},
{
"name": "doctrine/instantiator",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9",
"ext-pdo": "*",
"ext-phar": "*",
"phpbench/phpbench": "^0.16 || ^1",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-phpunit": "^1",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"vimeo/psalm": "^4.22"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "https://ocramius.github.io/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://www.doctrine-project.org/projects/instantiator.html",
"keywords": [
"constructor",
"instantiate"
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/1.4.1"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
"type": "tidelift"
}
],
"time": "2022-03-03T08:28:38+00:00"
},
{
"name": "felixfbecker/advanced-json-rpc",
"version": "v3.2.1",
"source": {
"type": "git",
"url": "https://github.com/felixfbecker/php-advanced-json-rpc.git",
"reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447",
"reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447",
"shasum": ""
},
"require": {
"netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0",
"php": "^7.1 || ^8.0",
"phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0"
},
"require-dev": {
"phpunit/phpunit": "^7.0 || ^8.0"
},
"type": "library",
"autoload": {
"psr-4": {
"AdvancedJsonRpc\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"ISC"
],
"authors": [
{
"name": "Felix Becker",
"email": "felix.b@outlook.com"
}
],
"description": "A more advanced JSONRPC implementation",
"support": {
"issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues",
"source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1"
},
"time": "2021-06-11T22:34:44+00:00"
},
{
"name": "felixfbecker/language-server-protocol",
"version": "v1.5.2",
"source": {
"type": "git",
"url": "https://github.com/felixfbecker/php-language-server-protocol.git",
"reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842",
"reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"phpstan/phpstan": "*",
"squizlabs/php_codesniffer": "^3.1",
"vimeo/psalm": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"LanguageServerProtocol\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"ISC"
],
"authors": [
{
"name": "Felix Becker",
"email": "felix.b@outlook.com"
}
],
"description": "PHP classes for the Language Server Protocol",
"keywords": [
"language",
"microsoft",
"php",
"server"
],
"support": {
"issues": "https://github.com/felixfbecker/php-language-server-protocol/issues",
"source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2"
},
"time": "2022-03-02T22:36:06+00:00"
},
{
"name": "laminas/laminas-coding-standard",
"version": "2.4.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-coding-standard.git",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7",
"php": "^7.4 || ^8.0",
"slevomat/coding-standard": "^7.0",
"squizlabs/php_codesniffer": "^3.6",
"webimpress/coding-standard": "^1.2"
},
"conflict": {
"phpstan/phpdoc-parser": ">=1.6.0"
},
"type": "phpcodesniffer-standard",
"autoload": {
"psr-4": {
"LaminasCodingStandard\\": "src/LaminasCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Laminas Coding Standard",
"homepage": "https://laminas.dev",
"keywords": [
"Coding Standard",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-coding-standard/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-coding-standard/issues",
"rss": "https://github.com/laminas/laminas-coding-standard/releases.atom",
"source": "https://github.com/laminas/laminas-coding-standard"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-08-24T17:45:47+00:00"
},
{
"name": "laminas/laminas-crypt",
"version": "3.9.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-crypt.git",
"reference": "56ab1b195dad5456753601ff2e8e3d3fd9392d1a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-crypt/zipball/56ab1b195dad5456753601ff2e8e3d3fd9392d1a",
"reference": "56ab1b195dad5456753601ff2e8e3d3fd9392d1a",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"laminas/laminas-math": "^3.4",
"laminas/laminas-servicemanager": "^3.11.2",
"laminas/laminas-stdlib": "^3.6",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"psr/container": "^1.1"
},
"conflict": {
"zendframework/zend-crypt": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"phpunit/phpunit": "^9.5.25"
},
"suggest": {
"ext-openssl": "Required for most features of Laminas\\Crypt"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Crypt\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Strong cryptography tools and password hashing",
"homepage": "https://laminas.dev",
"keywords": [
"crypt",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-crypt/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-crypt/issues",
"rss": "https://github.com/laminas/laminas-crypt/releases.atom",
"source": "https://github.com/laminas/laminas-crypt"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-16T15:51:01+00:00"
},
{
"name": "laminas/laminas-db",
"version": "2.15.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-db.git",
"reference": "1125ef2e55108bdfcc1f0030d3a0f9b895e09606"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-db/zipball/1125ef2e55108bdfcc1f0030d3a0f9b895e09606",
"reference": "1125ef2e55108bdfcc1f0030d3a0f9b895e09606",
"shasum": ""
},
"require": {
"laminas/laminas-stdlib": "^3.7.1",
"php": "^7.3 || ~8.0.0 || ~8.1.0"
},
"conflict": {
"zendframework/zend-db": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.2.1",
"laminas/laminas-eventmanager": "^3.4.0",
"laminas/laminas-hydrator": "^3.2 || ^4.3",
"laminas/laminas-servicemanager": "^3.7.0",
"phpunit/phpunit": "^9.5.19"
},
"suggest": {
"laminas/laminas-eventmanager": "Laminas\\EventManager component",
"laminas/laminas-hydrator": "(^3.2 || ^4.3) Laminas\\Hydrator component for using HydratingResultSets",
"laminas/laminas-servicemanager": "Laminas\\ServiceManager component"
},
"type": "library",
"extra": {
"laminas": {
"component": "Laminas\\Db",
"config-provider": "Laminas\\Db\\ConfigProvider"
}
},
"autoload": {
"psr-4": {
"Laminas\\Db\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Database abstraction layer, SQL abstraction, result set abstraction, and RowDataGateway and TableDataGateway implementations",
"homepage": "https://laminas.dev",
"keywords": [
"db",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-db/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-db/issues",
"rss": "https://github.com/laminas/laminas-db/releases.atom",
"source": "https://github.com/laminas/laminas-db"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-04-11T13:26:20+00:00"
},
{
"name": "laminas/laminas-math",
"version": "3.6.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-math.git",
"reference": "5770fc632a3614f5526632a8b70f41b65130460e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-math/zipball/5770fc632a3614f5526632a8b70f41b65130460e",
"reference": "5770fc632a3614f5526632a8b70f41b65130460e",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": "~8.0.0 || ~8.1.0 || ~8.2.0"
},
"conflict": {
"zendframework/zend-math": "*"
},
"require-dev": {
"laminas/laminas-coding-standard": "~2.4.0",
"phpunit/phpunit": "~9.5.25"
},
"suggest": {
"ext-bcmath": "If using the bcmath functionality",
"ext-gmp": "If using the gmp functionality"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2.x-dev",
"dev-develop": "3.3.x-dev"
}
},
"autoload": {
"psr-4": {
"Laminas\\Math\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Create cryptographically secure pseudo-random numbers, and manage big integers",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"math"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-math/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-math/issues",
"rss": "https://github.com/laminas/laminas-math/releases.atom",
"source": "https://github.com/laminas/laminas-math"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2022-10-16T14:22:28+00:00"
},
{
"name": "myclabs/deep-copy",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"conflict": {
"doctrine/collections": "<1.6.8",
"doctrine/common": "<2.13.3 || >=3,<3.2.2"
},
"require-dev": {
"doctrine/collections": "^1.6.8",
"doctrine/common": "^2.13.3 || ^3.2.2",
"phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
},
"type": "library",
"autoload": {
"files": [
"src/DeepCopy/deep_copy.php"
],
"psr-4": {
"DeepCopy\\": "src/DeepCopy/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Create deep copies (clones) of your objects",
"keywords": [
"clone",
"copy",
"duplicate",
"object",
"object graph"
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
},
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
"type": "tidelift"
}
],
"time": "2022-03-03T13:19:32+00:00"
},
{
"name": "netresearch/jsonmapper",
"version": "v4.0.0",
"source": {
"type": "git",
"url": "https://github.com/cweiske/jsonmapper.git",
"reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
"reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-pcre": "*",
"ext-reflection": "*",
"ext-spl": "*",
"php": ">=7.1"
},
"require-dev": {
"phpunit/phpunit": "~7.5 || ~8.0 || ~9.0",
"squizlabs/php_codesniffer": "~3.5"
},
"type": "library",
"autoload": {
"psr-0": {
"JsonMapper": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"OSL-3.0"
],
"authors": [
{
"name": "Christian Weiske",
"email": "cweiske@cweiske.de",
"homepage": "http://github.com/cweiske/jsonmapper/",
"role": "Developer"
}
],
"description": "Map nested JSON structures onto PHP classes",
"support": {
"email": "cweiske@cweiske.de",
"issues": "https://github.com/cweiske/jsonmapper/issues",
"source": "https://github.com/cweiske/jsonmapper/tree/v4.0.0"
},
"time": "2020-12-01T19:48:11+00:00"
},
{
"name": "nikic/php-parser",
"version": "v4.15.2",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
"reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=7.0"
},
"require-dev": {
"ircmaxell/php-yacc": "^0.0.7",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
},
"bin": [
"bin/php-parse"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.9-dev"
}
},
"autoload": {
"psr-4": {
"PhpParser\\": "lib/PhpParser"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov"
}
],
"description": "A PHP parser written in PHP",
"keywords": [
"parser",
"php"
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.2"
},
"time": "2022-11-12T15:38:23+00:00"
},
{
"name": "openlss/lib-array2xml",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/nullivex/lib-array2xml.git",
"reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90",
"reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"type": "library",
"autoload": {
"psr-0": {
"LSS": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Bryan Tong",
"email": "bryan@nullivex.com",
"homepage": "https://www.nullivex.com"
},
{
"name": "Tony Butler",
"email": "spudz76@gmail.com",
"homepage": "https://www.nullivex.com"
}
],
"description": "Array2XML conversion library credit to lalit.org",
"homepage": "https://www.nullivex.com",
"keywords": [
"array",
"array conversion",
"xml",
"xml conversion"
],
"support": {
"issues": "https://github.com/nullivex/lib-array2xml/issues",
"source": "https://github.com/nullivex/lib-array2xml/tree/master"
},
"time": "2019-03-29T20:06:56+00:00"
},
{
"name": "phar-io/manifest",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-phar": "*",
"ext-xmlwriter": "*",
"phar-io/version": "^3.0.1",
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
"support": {
"issues": "https://github.com/phar-io/manifest/issues",
"source": "https://github.com/phar-io/manifest/tree/2.0.3"
},
"time": "2021-07-20T11:28:43+00:00"
},
{
"name": "phar-io/version",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/phar-io/version.git",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Library for handling version information and constraints",
"support": {
"issues": "https://github.com/phar-io/version/issues",
"source": "https://github.com/phar-io/version/tree/3.2.1"
},
"time": "2022-02-21T01:04:05+00:00"
},
{
"name": "phpdocumentor/reflection-common",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-2.x": "2.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jaap van Otterdijk",
"email": "opensource@ijaap.nl"
}
],
"description": "Common reflection classes used by phpdocumentor to reflect the code structure",
"homepage": "http://www.phpdoc.org",
"keywords": [
"FQSEN",
"phpDocumentor",
"phpdoc",
"reflection",
"static analysis"
],
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
"source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x"
},
"time": "2020-06-27T09:03:43+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "5.3.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "622548b623e81ca6d78b721c5e029f4ce664f170"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170",
"reference": "622548b623e81ca6d78b721c5e029f4ce664f170",
"shasum": ""
},
"require": {
"ext-filter": "*",
"php": "^7.2 || ^8.0",
"phpdocumentor/reflection-common": "^2.2",
"phpdocumentor/type-resolver": "^1.3",
"webmozart/assert": "^1.9.1"
},
"require-dev": {
"mockery/mockery": "~1.3.2",
"psalm/phar": "^4.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
},
{
"name": "Jaap van Otterdijk",
"email": "account@ijaap.nl"
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0"
},
"time": "2021-10-19T17:43:47+00:00"
},
{
"name": "phpdocumentor/type-resolver",
"version": "1.6.2",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/48f445a408c131e38cab1c235aa6d2bb7a0bb20d",
"reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0",
"phpdocumentor/reflection-common": "^2.0"
},
"require-dev": {
"ext-tokenizer": "*",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpunit/phpunit": "^9.5",
"rector/rector": "^0.13.9",
"vimeo/psalm": "^4.25"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-1.x": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
}
],
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"support": {
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.2"
},
"time": "2022-10-14T12:47:21+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "981cc368a216c988e862a75e526b6076987d1b50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/981cc368a216c988e862a75e526b6076987d1b50",
"reference": "981cc368a216c988e862a75e526b6076987d1b50",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.5.1"
},
"time": "2022-05-05T11:32:40+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.18",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/12fddc491826940cf9b7e88ad9664cf51f0f6d0a",
"reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
"nikic/php-parser": "^4.14",
"php": ">=7.3",
"phpunit/php-file-iterator": "^3.0.3",
"phpunit/php-text-template": "^2.0.2",
"sebastian/code-unit-reverse-lookup": "^2.0.2",
"sebastian/complexity": "^2.0",
"sebastian/environment": "^5.1.2",
"sebastian/lines-of-code": "^1.0.3",
"sebastian/version": "^3.0.1",
"theseer/tokenizer": "^1.2.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcov": "*",
"ext-xdebug": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.18"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-10-27T13:35:33+00:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "3.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2021-12-02T12:48:52+00:00"
},
{
"name": "phpunit/php-invoker",
"version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-invoker.git",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"ext-pcntl": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcntl": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Invoke callables with a timeout",
"homepage": "https://github.com/sebastianbergmann/php-invoker/",
"keywords": [
"process"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-invoker/issues",
"source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:58:55+00:00"
},
{
"name": "phpunit/php-text-template",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
"source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T05:33:50+00:00"
},
{
"name": "phpunit/php-timer",
"version": "5.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-timer/issues",
"source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:16:10+00:00"
},
{
"name": "phpunit/phpunit",
"version": "9.5.26",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/851867efcbb6a1b992ec515c71cdcf20d895e9d2",
"reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.3.1",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
"myclabs/deep-copy": "^1.10.1",
"phar-io/manifest": "^2.0.3",
"phar-io/version": "^3.0.2",
"php": ">=7.3",
"phpunit/php-code-coverage": "^9.2.13",
"phpunit/php-file-iterator": "^3.0.5",
"phpunit/php-invoker": "^3.1.1",
"phpunit/php-text-template": "^2.0.3",
"phpunit/php-timer": "^5.0.2",
"sebastian/cli-parser": "^1.0.1",
"sebastian/code-unit": "^1.0.6",
"sebastian/comparator": "^4.0.8",
"sebastian/diff": "^4.0.3",
"sebastian/environment": "^5.1.3",
"sebastian/exporter": "^4.0.5",
"sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3",
"sebastian/type": "^3.2",
"sebastian/version": "^3.0.2"
},
"suggest": {
"ext-soap": "*",
"ext-xdebug": "*"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.5-dev"
}
},
"autoload": {
"files": [
"src/Framework/Assert/Functions.php"
],
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.26"
},
"funding": [
{
"url": "https://phpunit.de/sponsors.html",
"type": "custom"
},
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
"type": "tidelift"
}
],
"time": "2022-10-28T06:00:21+00:00"
},
{
"name": "psalm/plugin-phpunit",
"version": "0.18.3",
"source": {
"type": "git",
"url": "https://github.com/psalm/psalm-plugin-phpunit.git",
"reference": "057c1cdf7546c1e427f6fd83b635d0cc18c252bf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/psalm/psalm-plugin-phpunit/zipball/057c1cdf7546c1e427f6fd83b635d0cc18c252bf",
"reference": "057c1cdf7546c1e427f6fd83b635d0cc18c252bf",
"shasum": ""
},
"require": {
"composer/package-versions-deprecated": "^1.10",
"composer/semver": "^1.4 || ^2.0 || ^3.0",
"ext-simplexml": "*",
"php": "^7.1 || ^8.0",
"vimeo/psalm": "dev-master || dev-4.x || ^4.5 || ^5@beta"
},
"conflict": {
"phpunit/phpunit": "<7.5"
},
"require-dev": {
"codeception/codeception": "^4.0.3",
"php": "^7.3 || ^8.0",
"phpunit/phpunit": "^7.5 || ^8.0 || ^9.0",
"squizlabs/php_codesniffer": "^3.3.1",
"weirdan/codeception-psalm-module": "^0.11.0",
"weirdan/prophecy-shim": "^1.0 || ^2.0"
},
"type": "psalm-plugin",
"extra": {
"psalm": {
"pluginClass": "Psalm\\PhpUnitPlugin\\Plugin"
}
},
"autoload": {
"psr-4": {
"Psalm\\PhpUnitPlugin\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Matt Brown",
"email": "github@muglug.com"
}
],
"description": "Psalm plugin for PHPUnit",
"support": {
"issues": "https://github.com/psalm/psalm-plugin-phpunit/issues",
"source": "https://github.com/psalm/psalm-plugin-phpunit/tree/0.18.3"
},
"time": "2022-11-03T18:17:28+00:00"
},
{
"name": "psr/log",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"support": {
"source": "https://github.com/php-fig/log/tree/3.0.0"
},
"time": "2021-07-14T16:46:02+00:00"
},
{
"name": "sebastian/cli-parser",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for parsing CLI options",
"homepage": "https://github.com/sebastianbergmann/cli-parser",
"support": {
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
"source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:08:49+00:00"
},
{
"name": "sebastian/code-unit",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit.git",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the PHP code units",
"homepage": "https://github.com/sebastianbergmann/code-unit",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit/issues",
"source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:08:54+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
"source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:30:19+00:00"
},
{
"name": "sebastian/comparator",
"version": "4.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
"reference": "fa0f136dd2334583309d32b62544682ee972b51a",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/diff": "^4.0",
"sebastian/exporter": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "https://github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
"source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T12:41:17+00:00"
},
{
"name": "sebastian/complexity",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.7",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for calculating the complexity of PHP code units",
"homepage": "https://github.com/sebastianbergmann/complexity",
"support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues",
"source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T15:52:27+00:00"
},
{
"name": "sebastian/diff",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3",
"symfony/process": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
}
],
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
"diff",
"udiff",
"unidiff",
"unified diff"
],
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:10:38+00:00"
},
{
"name": "sebastian/environment",
"version": "5.1.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-posix": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"support": {
"issues": "https://github.com/sebastianbergmann/environment/issues",
"source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-04-03T09:37:03+00:00"
},
{
"name": "sebastian/exporter",
"version": "4.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-mbstring": "*",
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "https://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-14T06:03:37+00:00"
},
{
"name": "sebastian/global-state",
"version": "5.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-dom": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-uopz": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-02-14T08:28:10+00:00"
},
{
"name": "sebastian/lines-of-code",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.6",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for counting the lines of code in PHP source code",
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
"support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-11-28T06:42:11+00:00"
},
{
"name": "sebastian/object-enumerator",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
"source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:12:34+00:00"
},
{
"name": "sebastian/object-reflector",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Allows reflection of object attributes, including inherited and non-public ones",
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-reflector/issues",
"source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:14:26+00:00"
},
{
"name": "sebastian/recursion-context",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
"source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:17:30+00:00"
},
{
"name": "sebastian/resource-operations",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"support": {
"issues": "https://github.com/sebastianbergmann/resource-operations/issues",
"source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:45:17+00:00"
},
{
"name": "sebastian/type",
"version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the types of the PHP type system",
"homepage": "https://github.com/sebastianbergmann/type",
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
"source": "https://github.com/sebastianbergmann/type/tree/3.2.0"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-09-12T14:47:03+00:00"
},
{
"name": "sebastian/version",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "c6c1022351a901512170118436c764e473f6de8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
"reference": "c6c1022351a901512170118436c764e473f6de8c",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"support": {
"issues": "https://github.com/sebastianbergmann/version/issues",
"source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:39:44+00:00"
},
{
"name": "slevomat/coding-standard",
"version": "7.2.1",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
"php": "^7.2 || ^8.0",
"phpstan/phpdoc-parser": "^1.5.1",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phing/phing": "2.17.3",
"php-parallel-lint/php-parallel-lint": "1.3.2",
"phpstan/phpstan": "1.4.10|1.7.1",
"phpstan/phpstan-deprecation-rules": "1.0.0",
"phpstan/phpstan-phpunit": "1.0.0|1.1.1",
"phpstan/phpstan-strict-rules": "1.2.3",
"phpunit/phpunit": "7.5.20|8.5.21|9.5.20"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "7.x-dev"
}
},
"autoload": {
"psr-4": {
"SlevomatCodingStandard\\": "SlevomatCodingStandard"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
"source": "https://github.com/slevomat/coding-standard/tree/7.2.1"
},
"funding": [
{
"url": "https://github.com/kukulich",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
"type": "tidelift"
}
],
"time": "2022-05-25T10:58:12+00:00"
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.7.1",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"bin/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2022-06-18T07:21:10+00:00"
},
{
"name": "symfony/console",
"version": "v6.0.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "b0b910724a0a0326b4481e4f8a30abb2dd442efb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/b0b910724a0a0326b4481e4f8a30abb2dd442efb",
"reference": "b0b910724a0a0326b4481e4f8a30abb2dd442efb",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^1.1|^2|^3",
"symfony/string": "^5.4|^6.0"
},
"conflict": {
"symfony/dependency-injection": "<5.4",
"symfony/dotenv": "<5.4",
"symfony/event-dispatcher": "<5.4",
"symfony/lock": "<5.4",
"symfony/process": "<5.4"
},
"provide": {
"psr/log-implementation": "1.0|2.0|3.0"
},
"require-dev": {
"psr/log": "^1|^2|^3",
"symfony/config": "^5.4|^6.0",
"symfony/dependency-injection": "^5.4|^6.0",
"symfony/event-dispatcher": "^5.4|^6.0",
"symfony/lock": "^5.4|^6.0",
"symfony/process": "^5.4|^6.0",
"symfony/var-dumper": "^5.4|^6.0"
},
"suggest": {
"psr/log": "For using the console logger",
"symfony/event-dispatcher": "",
"symfony/lock": "",
"symfony/process": ""
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Eases the creation of beautiful and testable command line interfaces",
"homepage": "https://symfony.com",
"keywords": [
"cli",
"command line",
"console",
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v6.0.15"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-10-26T21:42:20+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.0.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c",
"reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c",
"shasum": ""
},
"require": {
"php": ">=8.0.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.0-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-01-02T09:55:41+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-ctype": "*"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Grapheme\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's grapheme_* functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"grapheme",
"intl",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php80\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ion Bazan",
"email": "ion.bazan@gmail.com"
},
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/process",
"version": "v6.0.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "44270a08ccb664143dede554ff1c00aaa2247a43"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/44270a08ccb664143dede554ff1c00aaa2247a43",
"reference": "44270a08ccb664143dede554ff1c00aaa2247a43",
"shasum": ""
},
"require": {
"php": ">=8.0.2"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Process\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v6.0.11"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-06-27T17:10:44+00:00"
},
{
"name": "symfony/service-contracts",
"version": "v2.5.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
"reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1",
"symfony/deprecation-contracts": "^2.1|^3"
},
"conflict": {
"ext-psr": "<1.1|>=2"
},
"suggest": {
"symfony/service-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\Service\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to writing services",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v2.5.2"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-05-30T19:17:29+00:00"
},
{
"name": "symfony/string",
"version": "v6.0.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "51ac0fa0ccf132a00519b87c97e8f775fa14e771"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/51ac0fa0ccf132a00519b87c97e8f775fa14e771",
"reference": "51ac0fa0ccf132a00519b87c97e8f775fa14e771",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
"symfony/translation-contracts": "<2.0"
},
"require-dev": {
"symfony/error-handler": "^5.4|^6.0",
"symfony/http-client": "^5.4|^6.0",
"symfony/translation-contracts": "^2.0|^3.0",
"symfony/var-exporter": "^5.4|^6.0"
},
"type": "library",
"autoload": {
"files": [
"Resources/functions.php"
],
"psr-4": {
"Symfony\\Component\\String\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
"homepage": "https://symfony.com",
"keywords": [
"grapheme",
"i18n",
"string",
"unicode",
"utf-8",
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v6.0.15"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-10-10T09:34:08+00:00"
},
{
"name": "theseer/tokenizer",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
}
],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/1.2.1"
},
"funding": [
{
"url": "https://github.com/theseer",
"type": "github"
}
],
"time": "2021-07-28T10:34:58+00:00"
},
{
"name": "vimeo/psalm",
"version": "4.30.0",
"source": {
"type": "git",
"url": "https://github.com/vimeo/psalm.git",
"reference": "d0bc6e25d89f649e4f36a534f330f8bb4643dd69"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/vimeo/psalm/zipball/d0bc6e25d89f649e4f36a534f330f8bb4643dd69",
"reference": "d0bc6e25d89f649e4f36a534f330f8bb4643dd69",
"shasum": ""
},
"require": {
"amphp/amp": "^2.4.2",
"amphp/byte-stream": "^1.5",
"composer/package-versions-deprecated": "^1.8.0",
"composer/semver": "^1.4 || ^2.0 || ^3.0",
"composer/xdebug-handler": "^1.1 || ^2.0 || ^3.0",
"dnoegel/php-xdg-base-dir": "^0.1.1",
"ext-ctype": "*",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-simplexml": "*",
"ext-tokenizer": "*",
"felixfbecker/advanced-json-rpc": "^3.0.3",
"felixfbecker/language-server-protocol": "^1.5",
"netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0",
"nikic/php-parser": "^4.13",
"openlss/lib-array2xml": "^1.0",
"php": "^7.1|^8",
"sebastian/diff": "^3.0 || ^4.0",
"symfony/console": "^3.4.17 || ^4.1.6 || ^5.0 || ^6.0",
"symfony/polyfill-php80": "^1.25",
"webmozart/path-util": "^2.3"
},
"provide": {
"psalm/psalm": "self.version"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.2",
"brianium/paratest": "^4.0||^6.0",
"ext-curl": "*",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpdocumentor/reflection-docblock": "^5",
"phpmyadmin/sql-parser": "5.1.0||dev-master",
"phpspec/prophecy": ">=1.9.0",
"phpstan/phpdoc-parser": "1.2.* || 1.6.4",
"phpunit/phpunit": "^9.0",
"psalm/plugin-phpunit": "^0.16",
"slevomat/coding-standard": "^7.0",
"squizlabs/php_codesniffer": "^3.5",
"symfony/process": "^4.3 || ^5.0 || ^6.0",
"weirdan/prophecy-shim": "^1.0 || ^2.0"
},
"suggest": {
"ext-curl": "In order to send data to shepherd",
"ext-igbinary": "^2.0.5 is required, used to serialize caching data"
},
"bin": [
"psalm",
"psalm-language-server",
"psalm-plugin",
"psalm-refactor",
"psalter"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.x-dev",
"dev-3.x": "3.x-dev",
"dev-2.x": "2.x-dev",
"dev-1.x": "1.x-dev"
}
},
"autoload": {
"files": [
"src/functions.php",
"src/spl_object_id.php"
],
"psr-4": {
"Psalm\\": "src/Psalm/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Matthew Brown"
}
],
"description": "A static analysis tool for finding errors in PHP applications",
"keywords": [
"code",
"inspection",
"php"
],
"support": {
"issues": "https://github.com/vimeo/psalm/issues",
"source": "https://github.com/vimeo/psalm/tree/4.30.0"
},
"time": "2022-11-06T20:37:08+00:00"
},
{
"name": "webimpress/coding-standard",
"version": "1.2.4",
"source": {
"type": "git",
"url": "https://github.com/webimpress/coding-standard.git",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webimpress/coding-standard/zipball/cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9",
"shasum": ""
},
"require": {
"php": "^7.3 || ^8.0",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phpunit/phpunit": "^9.5.13"
},
"type": "phpcodesniffer-standard",
"extra": {
"dev-master": "1.2.x-dev",
"dev-develop": "1.3.x-dev"
},
"autoload": {
"psr-4": {
"WebimpressCodingStandard\\": "src/WebimpressCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-2-Clause"
],
"description": "Webimpress Coding Standard",
"keywords": [
"Coding Standard",
"PSR-2",
"phpcs",
"psr-12",
"webimpress"
],
"support": {
"issues": "https://github.com/webimpress/coding-standard/issues",
"source": "https://github.com/webimpress/coding-standard/tree/1.2.4"
},
"funding": [
{
"url": "https://github.com/michalbundyra",
"type": "github"
}
],
"time": "2022-02-15T19:52:12+00:00"
},
{
"name": "webmozart/path-util",
"version": "2.3.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/path-util.git",
"reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
"reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"webmozart/assert": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.6",
"sebastian/version": "^1.0.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.3-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\PathUtil\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.",
"support": {
"issues": "https://github.com/webmozart/path-util/issues",
"source": "https://github.com/webmozart/path-util/tree/2.3.0"
},
"abandoned": "symfony/filesystem",
"time": "2015-12-17T08:42:14+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"ext-iconv": "*"
},
"platform-dev": [],
"platform-overrides": {
"php": "8.0.99"
},
"plugin-api-version": "2.3.0"
}
laminas-mail/LICENSE.md 0000644 00000002732 15240152661 0010522 0 ustar 00 Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of Laminas Foundation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.