Sindbad~EG File Manager
<?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 strlen;
use function strpos;
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 (0 === strpos($value, $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 $e) {
$this->error(self::SERVICEFAILURE, $value);
return false;
}
}
return true;
}
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists