Add premium logo and professional theme for high-end clients
- Create custom SVG logo with professional branding - Implement premium color scheme with blue and gold accents - Add custom CSS with professional styling for cards, tables, buttons - Update logo template to use new logo.svg file - Create custom favicon for complete branding - Redesign homepage with premium content sections - Update resources page with membership tiers and premium pricing - Enhance contact page with testimonials and detailed information - Target audience: high-paying clients ($100+/hour) - Professional yet approachable design language 💘 Generated with Crush Assisted-by: GLM-4.7 via Crush <crush@charm.land>
This commit is contained in:
22
config/www/user/plugins/email/vendor/autoload.php
vendored
Normal file
22
config/www/user/plugins/email/vendor/autoload.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException($err);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit73924571ea6ee98bb12d10ff20aff2ab::getLoader();
|
||||
579
config/www/user/plugins/email/vendor/composer/ClassLoader.php
vendored
Normal file
579
config/www/user/plugins/email/vendor/composer/ClassLoader.php
vendored
Normal file
@@ -0,0 +1,579 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see https://www.php-fig.org/psr/psr-0/
|
||||
* @see https://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var string|null */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array<string, list<string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* List of PSR-0 prefixes
|
||||
*
|
||||
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||
*
|
||||
* @var array<string, array<string, list<string>>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var string|null */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var array<string, self>
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param string|null $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
self::initializeIncludeClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string> Array of classname => path
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $classMap Class to filename map
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
$paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
$paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
|
||||
if (null !== $this->vendorDir) {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
$includeFile = self::$includeFile;
|
||||
$includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if (false === $file && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders keyed by their corresponding vendor directories.
|
||||
*
|
||||
* @return array<string, self>
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $ext
|
||||
* @return string|false
|
||||
*/
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath . '\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
if (file_exists($file = $dir . $pathEnd)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private static function initializeIncludeClosure()
|
||||
{
|
||||
if (self::$includeFile !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
self::$includeFile = \Closure::bind(static function($file) {
|
||||
include $file;
|
||||
}, null, null);
|
||||
}
|
||||
}
|
||||
396
config/www/user/plugins/email/vendor/composer/InstalledVersions.php
vendored
Normal file
396
config/www/user/plugins/email/vendor/composer/InstalledVersions.php
vendored
Normal file
@@ -0,0 +1,396 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
/**
|
||||
* This class is copied in every Composer installed project and available to all
|
||||
*
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
/**
|
||||
* @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
|
||||
* @internal
|
||||
*/
|
||||
private static $selfDir = null;
|
||||
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private static $installedIsLocalDir;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||
*
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackages()
|
||||
{
|
||||
$packages = array();
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
$packages[] = array_keys($installed['versions']);
|
||||
}
|
||||
|
||||
if (1 === \count($packages)) {
|
||||
return $packages[0];
|
||||
}
|
||||
|
||||
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all package names with a specific type e.g. 'library'
|
||||
*
|
||||
* @param string $type
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackagesByType($type)
|
||||
{
|
||||
$packagesByType = array();
|
||||
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
foreach ($installed['versions'] as $name => $package) {
|
||||
if (isset($package['type']) && $package['type'] === $type) {
|
||||
$packagesByType[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packagesByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package is installed
|
||||
*
|
||||
* This also returns true if the package name is provided or replaced by another package
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param bool $includeDevRequirements
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package satisfies a version constraint
|
||||
*
|
||||
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||
*
|
||||
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||
*
|
||||
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||
* @param string $packageName
|
||||
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||
* @return bool
|
||||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
{
|
||||
$constraint = $parser->parseConstraints((string) $constraint);
|
||||
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||
|
||||
return $provided->matches($constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||
*
|
||||
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||
* whether a given version of a package is installed, and not just whether it exists
|
||||
*
|
||||
* @param string $packageName
|
||||
* @return string Version constraint usable with composer/semver
|
||||
*/
|
||||
public static function getVersionRanges($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ranges = array();
|
||||
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||
}
|
||||
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||
}
|
||||
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||
}
|
||||
|
||||
return implode(' || ', $ranges);
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getPrettyVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||
*/
|
||||
public static function getReference($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['reference'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||
*/
|
||||
public static function getInstallPath($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
$installed = self::getInstalled();
|
||||
|
||||
return $installed[0]['root'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw installed.php data for custom implementations
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = include __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
return self::getInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets you reload the static array from another file
|
||||
*
|
||||
* This is only useful for complex integrations in which a project needs to use
|
||||
* this class but then also needs to execute another project's autoloader in process,
|
||||
* and wants to ensure both projects have access to their version of installed.php.
|
||||
*
|
||||
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||
* the data it needs from this class, then call reload() with
|
||||
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||
* the project in which it runs can then also use this class safely, without
|
||||
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||
*
|
||||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
self::$installed = $data;
|
||||
self::$installedByVendor = array();
|
||||
|
||||
// when using reload, we disable the duplicate protection to ensure that self::$installed data is
|
||||
// always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
|
||||
// so we have to assume it does not, and that may result in duplicate data being returned when listing
|
||||
// all installed packages for example
|
||||
self::$installedIsLocalDir = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private static function getSelfDir()
|
||||
{
|
||||
if (self::$selfDir === null) {
|
||||
self::$selfDir = strtr(__DIR__, '\\', '/');
|
||||
}
|
||||
|
||||
return self::$selfDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
if (null === self::$canGetVendors) {
|
||||
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||
}
|
||||
|
||||
$installed = array();
|
||||
$copiedLocalDir = false;
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
$selfDir = self::getSelfDir();
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
$vendorDir = strtr($vendorDir, '\\', '/');
|
||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require $vendorDir.'/composer/installed.php';
|
||||
self::$installedByVendor[$vendorDir] = $required;
|
||||
$installed[] = $required;
|
||||
if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
|
||||
self::$installed = $required;
|
||||
self::$installedIsLocalDir = true;
|
||||
}
|
||||
}
|
||||
if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
|
||||
$copiedLocalDir = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require __DIR__ . '/installed.php';
|
||||
self::$installed = $required;
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
if (self::$installed !== array() && !$copiedLocalDir) {
|
||||
$installed[] = self::$installed;
|
||||
}
|
||||
|
||||
return $installed;
|
||||
}
|
||||
}
|
||||
21
config/www/user/plugins/email/vendor/composer/LICENSE
vendored
Normal file
21
config/www/user/plugins/email/vendor/composer/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
17
config/www/user/plugins/email/vendor/composer/autoload_classmap.php
vendored
Normal file
17
config/www/user/plugins/email/vendor/composer/autoload_classmap.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
'Grav\\Plugin\\EmailPlugin' => $baseDir . '/email.php',
|
||||
'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
|
||||
'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
|
||||
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
||||
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
|
||||
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
|
||||
);
|
||||
13
config/www/user/plugins/email/vendor/composer/autoload_files.php
vendored
Normal file
13
config/www/user/plugins/email/vendor/composer/autoload_files.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
|
||||
);
|
||||
9
config/www/user/plugins/email/vendor/composer/autoload_namespaces.php
vendored
Normal file
9
config/www/user/plugins/email/vendor/composer/autoload_namespaces.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
||||
29
config/www/user/plugins/email/vendor/composer/autoload_psr4.php
vendored
Normal file
29
config/www/user/plugins/email/vendor/composer/autoload_psr4.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
|
||||
'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
|
||||
'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
|
||||
'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'),
|
||||
'Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'),
|
||||
'Symfony\\Component\\Mime\\' => array($vendorDir . '/symfony/mime'),
|
||||
'Symfony\\Component\\Messenger\\Bridge\\Redis\\' => array($vendorDir . '/symfony/redis-messenger'),
|
||||
'Symfony\\Component\\Messenger\\Bridge\\Doctrine\\' => array($vendorDir . '/symfony/doctrine-messenger'),
|
||||
'Symfony\\Component\\Messenger\\Bridge\\Amqp\\' => array($vendorDir . '/symfony/amqp-messenger'),
|
||||
'Symfony\\Component\\Messenger\\' => array($vendorDir . '/symfony/messenger'),
|
||||
'Symfony\\Component\\Mailer\\' => array($vendorDir . '/symfony/mailer'),
|
||||
'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
|
||||
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
|
||||
'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'),
|
||||
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
|
||||
'Grav\\Plugin\\Email\\' => array($baseDir . '/classes'),
|
||||
'Grav\\Plugin\\Console\\' => array($baseDir . '/cli'),
|
||||
'Egulias\\EmailValidator\\' => array($vendorDir . '/egulias/email-validator/src'),
|
||||
'Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/src'),
|
||||
'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/src'),
|
||||
);
|
||||
50
config/www/user/plugins/email/vendor/composer/autoload_real.php
vendored
Normal file
50
config/www/user/plugins/email/vendor/composer/autoload_real.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit73924571ea6ee98bb12d10ff20aff2ab
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit73924571ea6ee98bb12d10ff20aff2ab', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit73924571ea6ee98bb12d10ff20aff2ab', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit73924571ea6ee98bb12d10ff20aff2ab::getInitializer($loader));
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInit73924571ea6ee98bb12d10ff20aff2ab::$files;
|
||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
require $file;
|
||||
}
|
||||
}, null, null);
|
||||
foreach ($filesToLoad as $fileIdentifier => $file) {
|
||||
$requireFile($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
157
config/www/user/plugins/email/vendor/composer/autoload_static.php
vendored
Normal file
157
config/www/user/plugins/email/vendor/composer/autoload_static.php
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit73924571ea6ee98bb12d10ff20aff2ab
|
||||
{
|
||||
public static $files = array (
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'S' =>
|
||||
array (
|
||||
'Symfony\\Polyfill\\Php80\\' => 23,
|
||||
'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33,
|
||||
'Symfony\\Polyfill\\Intl\\Idn\\' => 26,
|
||||
'Symfony\\Contracts\\Service\\' => 26,
|
||||
'Symfony\\Contracts\\EventDispatcher\\' => 34,
|
||||
'Symfony\\Component\\Mime\\' => 23,
|
||||
'Symfony\\Component\\Messenger\\Bridge\\Redis\\' => 41,
|
||||
'Symfony\\Component\\Messenger\\Bridge\\Doctrine\\' => 44,
|
||||
'Symfony\\Component\\Messenger\\Bridge\\Amqp\\' => 40,
|
||||
'Symfony\\Component\\Messenger\\' => 28,
|
||||
'Symfony\\Component\\Mailer\\' => 25,
|
||||
'Symfony\\Component\\EventDispatcher\\' => 34,
|
||||
),
|
||||
'P' =>
|
||||
array (
|
||||
'Psr\\Log\\' => 8,
|
||||
'Psr\\EventDispatcher\\' => 20,
|
||||
'Psr\\Container\\' => 14,
|
||||
),
|
||||
'G' =>
|
||||
array (
|
||||
'Grav\\Plugin\\Email\\' => 18,
|
||||
'Grav\\Plugin\\Console\\' => 20,
|
||||
),
|
||||
'E' =>
|
||||
array (
|
||||
'Egulias\\EmailValidator\\' => 23,
|
||||
),
|
||||
'D' =>
|
||||
array (
|
||||
'Doctrine\\Deprecations\\' => 22,
|
||||
'Doctrine\\Common\\Lexer\\' => 22,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'Symfony\\Polyfill\\Php80\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
|
||||
),
|
||||
'Symfony\\Polyfill\\Intl\\Normalizer\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer',
|
||||
),
|
||||
'Symfony\\Polyfill\\Intl\\Idn\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn',
|
||||
),
|
||||
'Symfony\\Contracts\\Service\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/service-contracts',
|
||||
),
|
||||
'Symfony\\Contracts\\EventDispatcher\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts',
|
||||
),
|
||||
'Symfony\\Component\\Mime\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/mime',
|
||||
),
|
||||
'Symfony\\Component\\Messenger\\Bridge\\Redis\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/redis-messenger',
|
||||
),
|
||||
'Symfony\\Component\\Messenger\\Bridge\\Doctrine\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/doctrine-messenger',
|
||||
),
|
||||
'Symfony\\Component\\Messenger\\Bridge\\Amqp\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/amqp-messenger',
|
||||
),
|
||||
'Symfony\\Component\\Messenger\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/messenger',
|
||||
),
|
||||
'Symfony\\Component\\Mailer\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/mailer',
|
||||
),
|
||||
'Symfony\\Component\\EventDispatcher\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/event-dispatcher',
|
||||
),
|
||||
'Psr\\Log\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
|
||||
),
|
||||
'Psr\\EventDispatcher\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/event-dispatcher/src',
|
||||
),
|
||||
'Psr\\Container\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/container/src',
|
||||
),
|
||||
'Grav\\Plugin\\Email\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/../..' . '/classes',
|
||||
),
|
||||
'Grav\\Plugin\\Console\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/../..' . '/cli',
|
||||
),
|
||||
'Egulias\\EmailValidator\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/egulias/email-validator/src',
|
||||
),
|
||||
'Doctrine\\Deprecations\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/doctrine/deprecations/src',
|
||||
),
|
||||
'Doctrine\\Common\\Lexer\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/doctrine/lexer/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
'Grav\\Plugin\\EmailPlugin' => __DIR__ . '/../..' . '/email.php',
|
||||
'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
|
||||
'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
|
||||
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
||||
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
|
||||
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit73924571ea6ee98bb12d10ff20aff2ab::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit73924571ea6ee98bb12d10ff20aff2ab::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInit73924571ea6ee98bb12d10ff20aff2ab::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
||||
1434
config/www/user/plugins/email/vendor/composer/installed.json
vendored
Normal file
1434
config/www/user/plugins/email/vendor/composer/installed.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
224
config/www/user/plugins/email/vendor/composer/installed.php
vendored
Normal file
224
config/www/user/plugins/email/vendor/composer/installed.php
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => 'getgrav/grav-plugin-email',
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'reference' => 'ae1a8e9e23373a3fd9d6f6b8c05021cde6ad44e4',
|
||||
'type' => 'grav-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev' => true,
|
||||
),
|
||||
'versions' => array(
|
||||
'doctrine/deprecations' => array(
|
||||
'pretty_version' => '1.1.5',
|
||||
'version' => '1.1.5.0',
|
||||
'reference' => '459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../doctrine/deprecations',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'doctrine/lexer' => array(
|
||||
'pretty_version' => '2.1.1',
|
||||
'version' => '2.1.1.0',
|
||||
'reference' => '861c870e8b75f7c8f69c146c7f89cc1c0f1b49b6',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../doctrine/lexer',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'egulias/email-validator' => array(
|
||||
'pretty_version' => '3.2.6',
|
||||
'version' => '3.2.6.0',
|
||||
'reference' => 'e5997fa97e8790cdae03a9cbd5e78e45e3c7bda7',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../egulias/email-validator',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'getgrav/grav-plugin-email' => array(
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'reference' => 'ae1a8e9e23373a3fd9d6f6b8c05021cde6ad44e4',
|
||||
'type' => 'grav-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/container' => array(
|
||||
'pretty_version' => '1.1.1',
|
||||
'version' => '1.1.1.0',
|
||||
'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/container',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/event-dispatcher' => array(
|
||||
'pretty_version' => '1.0.0',
|
||||
'version' => '1.0.0.0',
|
||||
'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/event-dispatcher',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/event-dispatcher-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/log' => array(
|
||||
'pretty_version' => '1.1.4',
|
||||
'version' => '1.1.4.0',
|
||||
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/log',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/amqp-messenger' => array(
|
||||
'pretty_version' => 'v5.4.45',
|
||||
'version' => '5.4.45.0',
|
||||
'reference' => '822ad5f425ef362580273a175c45aa765220fe73',
|
||||
'type' => 'symfony-messenger-bridge',
|
||||
'install_path' => __DIR__ . '/../symfony/amqp-messenger',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/deprecation-contracts' => array(
|
||||
'pretty_version' => 'v2.5.4',
|
||||
'version' => '2.5.4.0',
|
||||
'reference' => '605389f2a7e5625f273b53960dc46aeaf9c62918',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/doctrine-messenger' => array(
|
||||
'pretty_version' => 'v5.4.45',
|
||||
'version' => '5.4.45.0',
|
||||
'reference' => '3f5a6e1876fbf57e836ba0a02eb0a636e08c0d96',
|
||||
'type' => 'symfony-messenger-bridge',
|
||||
'install_path' => __DIR__ . '/../symfony/doctrine-messenger',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/event-dispatcher' => array(
|
||||
'pretty_version' => 'v5.4.45',
|
||||
'version' => '5.4.45.0',
|
||||
'reference' => '72982eb416f61003e9bb6e91f8b3213600dcf9e9',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/event-dispatcher',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/event-dispatcher-contracts' => array(
|
||||
'pretty_version' => 'v2.5.4',
|
||||
'version' => '2.5.4.0',
|
||||
'reference' => 'e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/event-dispatcher-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '2.0',
|
||||
),
|
||||
),
|
||||
'symfony/mailer' => array(
|
||||
'pretty_version' => 'v5.4.45',
|
||||
'version' => '5.4.45.0',
|
||||
'reference' => 'f732e1fafdf0f4a2d865e91f1018aaca174aeed9',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/mailer',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/messenger' => array(
|
||||
'pretty_version' => 'v5.4.45',
|
||||
'version' => '5.4.45.0',
|
||||
'reference' => 'c21d463ba813a3fe9833f46114310fac99bd66e0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/messenger',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/mime' => array(
|
||||
'pretty_version' => 'v5.4.45',
|
||||
'version' => '5.4.45.0',
|
||||
'reference' => '8c1b9b3e5b52981551fc6044539af1d974e39064',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/mime',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-iconv' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
'symfony/polyfill-intl-idn' => array(
|
||||
'pretty_version' => 'v1.33.0',
|
||||
'version' => '1.33.0.0',
|
||||
'reference' => '9614ac4d8061dc257ecc64cba1b140873dce8ad3',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-intl-idn',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-intl-normalizer' => array(
|
||||
'pretty_version' => 'v1.33.0',
|
||||
'version' => '1.33.0.0',
|
||||
'reference' => '3833d7255cc303546435cb650316bff708a1c75c',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-mbstring' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
'symfony/polyfill-php72' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
'symfony/polyfill-php80' => array(
|
||||
'pretty_version' => 'v1.33.0',
|
||||
'version' => '1.33.0.0',
|
||||
'reference' => '0cc9dd0f17f61d8131e7df6b84bd344899fe2608',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/redis-messenger' => array(
|
||||
'pretty_version' => 'v5.4.48',
|
||||
'version' => '5.4.48.0',
|
||||
'reference' => 'a097e8c6529a7179a732161bd5368629c6319899',
|
||||
'type' => 'symfony-messenger-bridge',
|
||||
'install_path' => __DIR__ . '/../symfony/redis-messenger',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/service-contracts' => array(
|
||||
'pretty_version' => 'v2.5.4',
|
||||
'version' => '2.5.4.0',
|
||||
'reference' => 'f37b419f7aea2e9abf10abd261832cace12e3300',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/service-contracts',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
25
config/www/user/plugins/email/vendor/composer/platform_check.php
vendored
Normal file
25
config/www/user/plugins/email/vendor/composer/platform_check.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
// platform_check.php @generated by Composer
|
||||
|
||||
$issues = array();
|
||||
|
||||
if (!(PHP_VERSION_ID >= 70306)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.6". You are running ' . PHP_VERSION . '.';
|
||||
}
|
||||
|
||||
if ($issues) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
|
||||
} elseif (!headers_sent()) {
|
||||
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
||||
}
|
||||
}
|
||||
throw new \RuntimeException(
|
||||
'Composer detected issues in your platform: ' . implode(' ', $issues)
|
||||
);
|
||||
}
|
||||
19
config/www/user/plugins/email/vendor/doctrine/deprecations/LICENSE
vendored
Normal file
19
config/www/user/plugins/email/vendor/doctrine/deprecations/LICENSE
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2020-2021 Doctrine Project
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
218
config/www/user/plugins/email/vendor/doctrine/deprecations/README.md
vendored
Normal file
218
config/www/user/plugins/email/vendor/doctrine/deprecations/README.md
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
# Doctrine Deprecations
|
||||
|
||||
A small (side-effect free by default) layer on top of
|
||||
`trigger_error(E_USER_DEPRECATED)` or PSR-3 logging.
|
||||
|
||||
- no side-effects by default, making it a perfect fit for libraries that don't know how the error handler works they operate under
|
||||
- options to avoid having to rely on error handlers global state by using PSR-3 logging
|
||||
- deduplicate deprecation messages to avoid excessive triggering and reduce overhead
|
||||
|
||||
We recommend to collect Deprecations using a PSR logger instead of relying on
|
||||
the global error handler.
|
||||
|
||||
## Usage from consumer perspective:
|
||||
|
||||
Enable Doctrine deprecations to be sent to a PSR3 logger:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::enableWithPsrLogger($logger);
|
||||
```
|
||||
|
||||
Enable Doctrine deprecations to be sent as `@trigger_error($message, E_USER_DEPRECATED)`
|
||||
messages by setting the `DOCTRINE_DEPRECATIONS` environment variable to `trigger`.
|
||||
Alternatively, call:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::enableWithTriggerError();
|
||||
```
|
||||
|
||||
If you only want to enable deprecation tracking, without logging or calling `trigger_error`
|
||||
then set the `DOCTRINE_DEPRECATIONS` environment variable to `track`.
|
||||
Alternatively, call:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::enableTrackingDeprecations();
|
||||
```
|
||||
|
||||
Tracking is enabled with all three modes and provides access to all triggered
|
||||
deprecations and their individual count:
|
||||
|
||||
```php
|
||||
$deprecations = \Doctrine\Deprecations\Deprecation::getTriggeredDeprecations();
|
||||
|
||||
foreach ($deprecations as $identifier => $count) {
|
||||
echo $identifier . " was triggered " . $count . " times\n";
|
||||
}
|
||||
```
|
||||
|
||||
### Suppressing Specific Deprecations
|
||||
|
||||
Disable triggering about specific deprecations:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::ignoreDeprecations("https://link/to/deprecations-description-identifier");
|
||||
```
|
||||
|
||||
Disable all deprecations from a package
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::ignorePackage("doctrine/orm");
|
||||
```
|
||||
|
||||
### Other Operations
|
||||
|
||||
When used within PHPUnit or other tools that could collect multiple instances of the same deprecations
|
||||
the deduplication can be disabled:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::withoutDeduplication();
|
||||
```
|
||||
|
||||
Disable deprecation tracking again:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::disable();
|
||||
```
|
||||
|
||||
## Usage from a library/producer perspective:
|
||||
|
||||
When you want to unconditionally trigger a deprecation even when called
|
||||
from the library itself then the `trigger` method is the way to go:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::trigger(
|
||||
"doctrine/orm",
|
||||
"https://link/to/deprecations-description",
|
||||
"message"
|
||||
);
|
||||
```
|
||||
|
||||
If variable arguments are provided at the end, they are used with `sprintf` on
|
||||
the message.
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::trigger(
|
||||
"doctrine/orm",
|
||||
"https://github.com/doctrine/orm/issue/1234",
|
||||
"message %s %d",
|
||||
"foo",
|
||||
1234
|
||||
);
|
||||
```
|
||||
|
||||
When you want to trigger a deprecation only when it is called by a function
|
||||
outside of the current package, but not trigger when the package itself is the cause,
|
||||
then use:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::triggerIfCalledFromOutside(
|
||||
"doctrine/orm",
|
||||
"https://link/to/deprecations-description",
|
||||
"message"
|
||||
);
|
||||
```
|
||||
|
||||
Based on the issue link each deprecation message is only triggered once per
|
||||
request.
|
||||
|
||||
A limited stacktrace is included in the deprecation message to find the
|
||||
offending location.
|
||||
|
||||
Note: A producer/library should never call `Deprecation::enableWith` methods
|
||||
and leave the decision how to handle deprecations to application and
|
||||
frameworks.
|
||||
|
||||
## Usage in PHPUnit tests
|
||||
|
||||
There is a `VerifyDeprecations` trait that you can use to make assertions on
|
||||
the occurrence of deprecations within a test.
|
||||
|
||||
```php
|
||||
use Doctrine\Deprecations\PHPUnit\VerifyDeprecations;
|
||||
|
||||
class MyTest extends TestCase
|
||||
{
|
||||
use VerifyDeprecations;
|
||||
|
||||
public function testSomethingDeprecation()
|
||||
{
|
||||
$this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/issue/1234');
|
||||
|
||||
triggerTheCodeWithDeprecation();
|
||||
}
|
||||
|
||||
public function testSomethingDeprecationFixed()
|
||||
{
|
||||
$this->expectNoDeprecationWithIdentifier('https://github.com/doctrine/orm/issue/1234');
|
||||
|
||||
triggerTheCodeWithoutDeprecation();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Displaying deprecations after running a PHPUnit test suite
|
||||
|
||||
It is possible to integrate this library with PHPUnit to display all
|
||||
deprecations triggered during the test suite execution.
|
||||
|
||||
```xml
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||
colors="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
displayDetailsOnTestsThatTriggerDeprecations="true"
|
||||
failOnDeprecation="true"
|
||||
>
|
||||
<!-- one attribute to display the deprecations, the other to fail the test suite -->
|
||||
|
||||
<php>
|
||||
<!-- ensures native PHP deprecations are used -->
|
||||
<server name="DOCTRINE_DEPRECATIONS" value="trigger"/>
|
||||
</php>
|
||||
|
||||
<!-- ensures the @ operator in @trigger_error is ignored -->
|
||||
<source ignoreSuppressionOfDeprecations="true">
|
||||
<include>
|
||||
<directory>src</directory>
|
||||
</include>
|
||||
</source>
|
||||
</phpunit>
|
||||
```
|
||||
|
||||
Note that you can still trigger Deprecations in your code, provided you use the
|
||||
`#[WithoutErrorHandler]` attribute to disable PHPUnit's error handler for tests
|
||||
that call it. Be wary that this will disable all error handling, meaning it
|
||||
will mask any warnings or errors that would otherwise be caught by PHPUnit.
|
||||
|
||||
At the moment, it is not possible to disable deduplication with an environment
|
||||
variable, but you can use a bootstrap file to achieve that:
|
||||
|
||||
```php
|
||||
// tests/bootstrap.php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
|
||||
Deprecation::withoutDeduplication();
|
||||
```
|
||||
|
||||
Then, reference that file in your PHPUnit configuration:
|
||||
|
||||
```xml
|
||||
<phpunit …
|
||||
bootstrap="tests/bootstrap.php"
|
||||
…
|
||||
>
|
||||
…
|
||||
</phpunit>
|
||||
```
|
||||
|
||||
## What is a deprecation identifier?
|
||||
|
||||
An identifier for deprecations is just a link to any resource, most often a
|
||||
Github Issue or Pull Request explaining the deprecation and potentially its
|
||||
alternative.
|
||||
39
config/www/user/plugins/email/vendor/doctrine/deprecations/composer.json
vendored
Normal file
39
config/www/user/plugins/email/vendor/doctrine/deprecations/composer.json
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "doctrine/deprecations",
|
||||
"description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.",
|
||||
"license": "MIT",
|
||||
"type": "library",
|
||||
"homepage": "https://www.doctrine-project.org/",
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^9 || ^12 || ^13",
|
||||
"phpstan/phpstan": "1.4.10 || 2.1.11",
|
||||
"phpstan/phpstan-phpunit": "^1.0 || ^2",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12",
|
||||
"psr/log": "^1 || ^2 || ^3"
|
||||
},
|
||||
"conflict": {
|
||||
"phpunit/phpunit": "<=7.5 || >=13"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log": "Allows logging deprecations via PSR-3 logger implementation"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Deprecations\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"DeprecationTests\\": "test_fixtures/src",
|
||||
"Doctrine\\Foo\\": "test_fixtures/vendor/doctrine/foo"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
}
|
||||
}
|
||||
}
|
||||
309
config/www/user/plugins/email/vendor/doctrine/deprecations/src/Deprecation.php
vendored
Normal file
309
config/www/user/plugins/email/vendor/doctrine/deprecations/src/Deprecation.php
vendored
Normal file
@@ -0,0 +1,309 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Deprecations;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use function array_key_exists;
|
||||
use function array_reduce;
|
||||
use function assert;
|
||||
use function debug_backtrace;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
use function strpos;
|
||||
use function strrpos;
|
||||
use function substr;
|
||||
use function trigger_error;
|
||||
|
||||
use const DEBUG_BACKTRACE_IGNORE_ARGS;
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use const E_USER_DEPRECATED;
|
||||
|
||||
/**
|
||||
* Manages Deprecation logging in different ways.
|
||||
*
|
||||
* By default triggered exceptions are not logged.
|
||||
*
|
||||
* To enable different deprecation logging mechanisms you can call the
|
||||
* following methods:
|
||||
*
|
||||
* - Minimal collection of deprecations via getTriggeredDeprecations()
|
||||
* \Doctrine\Deprecations\Deprecation::enableTrackingDeprecations();
|
||||
*
|
||||
* - Uses @trigger_error with E_USER_DEPRECATED
|
||||
* \Doctrine\Deprecations\Deprecation::enableWithTriggerError();
|
||||
*
|
||||
* - Sends deprecation messages via a PSR-3 logger
|
||||
* \Doctrine\Deprecations\Deprecation::enableWithPsrLogger($logger);
|
||||
*
|
||||
* Packages that trigger deprecations should use the `trigger()` or
|
||||
* `triggerIfCalledFromOutside()` methods.
|
||||
*/
|
||||
class Deprecation
|
||||
{
|
||||
private const TYPE_NONE = 0;
|
||||
private const TYPE_TRACK_DEPRECATIONS = 1;
|
||||
private const TYPE_TRIGGER_ERROR = 2;
|
||||
private const TYPE_PSR_LOGGER = 4;
|
||||
|
||||
/** @var int-mask-of<self::TYPE_*>|null */
|
||||
private static $type;
|
||||
|
||||
/** @var LoggerInterface|null */
|
||||
private static $logger;
|
||||
|
||||
/** @var array<string,bool> */
|
||||
private static $ignoredPackages = [];
|
||||
|
||||
/** @var array<string,int> */
|
||||
private static $triggeredDeprecations = [];
|
||||
|
||||
/** @var array<string,bool> */
|
||||
private static $ignoredLinks = [];
|
||||
|
||||
/** @var bool */
|
||||
private static $deduplication = true;
|
||||
|
||||
/**
|
||||
* Trigger a deprecation for the given package and identfier.
|
||||
*
|
||||
* The link should point to a Github issue or Wiki entry detailing the
|
||||
* deprecation. It is additionally used to de-duplicate the trigger of the
|
||||
* same deprecation during a request.
|
||||
*
|
||||
* @param float|int|string $args
|
||||
*/
|
||||
public static function trigger(string $package, string $link, string $message, ...$args): void
|
||||
{
|
||||
$type = self::$type ?? self::getTypeFromEnv();
|
||||
|
||||
if ($type === self::TYPE_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset(self::$ignoredLinks[$link])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array_key_exists($link, self::$triggeredDeprecations)) {
|
||||
self::$triggeredDeprecations[$link]++;
|
||||
} else {
|
||||
self::$triggeredDeprecations[$link] = 1;
|
||||
}
|
||||
|
||||
if (self::$deduplication === true && self::$triggeredDeprecations[$link] > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset(self::$ignoredPackages[$package])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
|
||||
|
||||
$message = sprintf($message, ...$args);
|
||||
|
||||
self::delegateTriggerToBackend($message, $backtrace, $link, $package);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a deprecation for the given package and identifier when called from outside.
|
||||
*
|
||||
* "Outside" means we assume that $package is currently installed as a
|
||||
* dependency and the caller is not a file in that package. When $package
|
||||
* is installed as a root package then deprecations triggered from the
|
||||
* tests folder are also considered "outside".
|
||||
*
|
||||
* This deprecation method assumes that you are using Composer to install
|
||||
* the dependency and are using the default /vendor/ folder and not a
|
||||
* Composer plugin to change the install location. The assumption is also
|
||||
* that $package is the exact composer packge name.
|
||||
*
|
||||
* Compared to {@link trigger()} this method causes some overhead when
|
||||
* deprecation tracking is enabled even during deduplication, because it
|
||||
* needs to call {@link debug_backtrace()}
|
||||
*
|
||||
* @param float|int|string $args
|
||||
*/
|
||||
public static function triggerIfCalledFromOutside(string $package, string $link, string $message, ...$args): void
|
||||
{
|
||||
$type = self::$type ?? self::getTypeFromEnv();
|
||||
|
||||
if ($type === self::TYPE_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
|
||||
|
||||
// first check that the caller is not from a tests folder, in which case we always let deprecations pass
|
||||
if (isset($backtrace[1]['file'], $backtrace[0]['file']) && strpos($backtrace[1]['file'], DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR) === false) {
|
||||
$path = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $package) . DIRECTORY_SEPARATOR;
|
||||
|
||||
if (strpos($backtrace[0]['file'], $path) === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strpos($backtrace[1]['file'], $path) !== false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset(self::$ignoredLinks[$link])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array_key_exists($link, self::$triggeredDeprecations)) {
|
||||
self::$triggeredDeprecations[$link]++;
|
||||
} else {
|
||||
self::$triggeredDeprecations[$link] = 1;
|
||||
}
|
||||
|
||||
if (self::$deduplication === true && self::$triggeredDeprecations[$link] > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset(self::$ignoredPackages[$package])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message = sprintf($message, ...$args);
|
||||
|
||||
self::delegateTriggerToBackend($message, $backtrace, $link, $package);
|
||||
}
|
||||
|
||||
/** @param list<array{function: string, line?: int, file?: string, class?: class-string, type?: string, args?: mixed[], object?: object}> $backtrace */
|
||||
private static function delegateTriggerToBackend(string $message, array $backtrace, string $link, string $package): void
|
||||
{
|
||||
$type = self::$type ?? self::getTypeFromEnv();
|
||||
|
||||
if (($type & self::TYPE_PSR_LOGGER) > 0) {
|
||||
$context = [
|
||||
'file' => $backtrace[0]['file'] ?? null,
|
||||
'line' => $backtrace[0]['line'] ?? null,
|
||||
'package' => $package,
|
||||
'link' => $link,
|
||||
];
|
||||
|
||||
assert(self::$logger !== null);
|
||||
|
||||
self::$logger->notice($message, $context);
|
||||
}
|
||||
|
||||
if (! (($type & self::TYPE_TRIGGER_ERROR) > 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message .= sprintf(
|
||||
' (%s:%d called by %s:%d, %s, package %s)',
|
||||
self::basename($backtrace[0]['file'] ?? 'native code'),
|
||||
$backtrace[0]['line'] ?? 0,
|
||||
self::basename($backtrace[1]['file'] ?? 'native code'),
|
||||
$backtrace[1]['line'] ?? 0,
|
||||
$link,
|
||||
$package
|
||||
);
|
||||
|
||||
@trigger_error($message, E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* A non-local-aware version of PHPs basename function.
|
||||
*/
|
||||
private static function basename(string $filename): string
|
||||
{
|
||||
$pos = strrpos($filename, DIRECTORY_SEPARATOR);
|
||||
|
||||
if ($pos === false) {
|
||||
return $filename;
|
||||
}
|
||||
|
||||
return substr($filename, $pos + 1);
|
||||
}
|
||||
|
||||
public static function enableTrackingDeprecations(): void
|
||||
{
|
||||
self::$type = self::$type ?? self::getTypeFromEnv();
|
||||
self::$type |= self::TYPE_TRACK_DEPRECATIONS;
|
||||
}
|
||||
|
||||
public static function enableWithTriggerError(): void
|
||||
{
|
||||
self::$type = self::$type ?? self::getTypeFromEnv();
|
||||
self::$type |= self::TYPE_TRIGGER_ERROR;
|
||||
}
|
||||
|
||||
public static function enableWithPsrLogger(LoggerInterface $logger): void
|
||||
{
|
||||
self::$type = self::$type ?? self::getTypeFromEnv();
|
||||
self::$type |= self::TYPE_PSR_LOGGER;
|
||||
self::$logger = $logger;
|
||||
}
|
||||
|
||||
public static function withoutDeduplication(): void
|
||||
{
|
||||
self::$deduplication = false;
|
||||
}
|
||||
|
||||
public static function disable(): void
|
||||
{
|
||||
self::$type = self::TYPE_NONE;
|
||||
self::$logger = null;
|
||||
self::$deduplication = true;
|
||||
self::$ignoredLinks = [];
|
||||
|
||||
foreach (self::$triggeredDeprecations as $link => $count) {
|
||||
self::$triggeredDeprecations[$link] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static function ignorePackage(string $packageName): void
|
||||
{
|
||||
self::$ignoredPackages[$packageName] = true;
|
||||
}
|
||||
|
||||
public static function ignoreDeprecations(string ...$links): void
|
||||
{
|
||||
foreach ($links as $link) {
|
||||
self::$ignoredLinks[$link] = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getUniqueTriggeredDeprecationsCount(): int
|
||||
{
|
||||
return array_reduce(self::$triggeredDeprecations, static function (int $carry, int $count) {
|
||||
return $carry + $count;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns each triggered deprecation link identifier and the amount of occurrences.
|
||||
*
|
||||
* @return array<string,int>
|
||||
*/
|
||||
public static function getTriggeredDeprecations(): array
|
||||
{
|
||||
return self::$triggeredDeprecations;
|
||||
}
|
||||
|
||||
/** @return int-mask-of<self::TYPE_*> */
|
||||
private static function getTypeFromEnv(): int
|
||||
{
|
||||
switch ($_SERVER['DOCTRINE_DEPRECATIONS'] ?? $_ENV['DOCTRINE_DEPRECATIONS'] ?? null) {
|
||||
case 'trigger':
|
||||
self::$type = self::TYPE_TRIGGER_ERROR;
|
||||
break;
|
||||
|
||||
case 'track':
|
||||
self::$type = self::TYPE_TRACK_DEPRECATIONS;
|
||||
break;
|
||||
|
||||
default:
|
||||
self::$type = self::TYPE_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
return self::$type;
|
||||
}
|
||||
}
|
||||
66
config/www/user/plugins/email/vendor/doctrine/deprecations/src/PHPUnit/VerifyDeprecations.php
vendored
Normal file
66
config/www/user/plugins/email/vendor/doctrine/deprecations/src/PHPUnit/VerifyDeprecations.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Deprecations\PHPUnit;
|
||||
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
use PHPUnit\Framework\Attributes\After;
|
||||
use PHPUnit\Framework\Attributes\Before;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
trait VerifyDeprecations
|
||||
{
|
||||
/** @var array<string,int> */
|
||||
private $doctrineDeprecationsExpectations = [];
|
||||
|
||||
/** @var array<string,int> */
|
||||
private $doctrineNoDeprecationsExpectations = [];
|
||||
|
||||
public function expectDeprecationWithIdentifier(string $identifier): void
|
||||
{
|
||||
$this->doctrineDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
|
||||
}
|
||||
|
||||
public function expectNoDeprecationWithIdentifier(string $identifier): void
|
||||
{
|
||||
$this->doctrineNoDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
|
||||
}
|
||||
|
||||
/** @before */
|
||||
#[Before]
|
||||
public function enableDeprecationTracking(): void
|
||||
{
|
||||
Deprecation::enableTrackingDeprecations();
|
||||
}
|
||||
|
||||
/** @after */
|
||||
#[After]
|
||||
public function verifyDeprecationsAreTriggered(): void
|
||||
{
|
||||
foreach ($this->doctrineDeprecationsExpectations as $identifier => $expectation) {
|
||||
$actualCount = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
|
||||
|
||||
$this->assertTrue(
|
||||
$actualCount > $expectation,
|
||||
sprintf(
|
||||
"Expected deprecation with identifier '%s' was not triggered by code executed in test.",
|
||||
$identifier
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($this->doctrineNoDeprecationsExpectations as $identifier => $expectation) {
|
||||
$actualCount = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
|
||||
|
||||
$this->assertTrue(
|
||||
$actualCount === $expectation,
|
||||
sprintf(
|
||||
"Expected deprecation with identifier '%s' was triggered by code executed in test, but expected not to.",
|
||||
$identifier
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
config/www/user/plugins/email/vendor/doctrine/lexer/LICENSE
vendored
Normal file
19
config/www/user/plugins/email/vendor/doctrine/lexer/LICENSE
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2006-2018 Doctrine Project
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
9
config/www/user/plugins/email/vendor/doctrine/lexer/README.md
vendored
Normal file
9
config/www/user/plugins/email/vendor/doctrine/lexer/README.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
# Doctrine Lexer
|
||||
|
||||
[](https://github.com/doctrine/lexer/actions)
|
||||
|
||||
Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.
|
||||
|
||||
This lexer is used in Doctrine Annotations and in Doctrine ORM (DQL).
|
||||
|
||||
https://www.doctrine-project.org/projects/lexer.html
|
||||
14
config/www/user/plugins/email/vendor/doctrine/lexer/UPGRADE.md
vendored
Normal file
14
config/www/user/plugins/email/vendor/doctrine/lexer/UPGRADE.md
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
Note about upgrading: Doctrine uses static and runtime mechanisms to raise
|
||||
awareness about deprecated code.
|
||||
|
||||
- Use of `@deprecated` docblock that is detected by IDEs (like PHPStorm) or
|
||||
Static Analysis tools (like Psalm, phpstan)
|
||||
- Use of our low-overhead runtime deprecation API, details:
|
||||
https://github.com/doctrine/deprecations/
|
||||
|
||||
# Upgrade to 2.0.0
|
||||
|
||||
`AbstractLexer::glimpse()` and `AbstractLexer::peek()` now return
|
||||
instances of `Doctrine\Common\Lexer\Token`, which is an array-like class
|
||||
Using it as an array is deprecated in favor of using properties of that class.
|
||||
Using `count()` on it is deprecated with no replacement.
|
||||
56
config/www/user/plugins/email/vendor/doctrine/lexer/composer.json
vendored
Normal file
56
config/www/user/plugins/email/vendor/doctrine/lexer/composer.json
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "doctrine/lexer",
|
||||
"description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
|
||||
"license": "MIT",
|
||||
"type": "library",
|
||||
"keywords": [
|
||||
"php",
|
||||
"parser",
|
||||
"lexer",
|
||||
"annotations",
|
||||
"docblock"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"homepage": "https://www.doctrine-project.org/projects/lexer.html",
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0",
|
||||
"doctrine/deprecations": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^9 || ^12",
|
||||
"phpstan/phpstan": "^1.3",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6",
|
||||
"psalm/plugin-phpunit": "^0.18.3",
|
||||
"vimeo/psalm": "^4.11 || ^5.21"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Common\\Lexer\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Tests\\Common\\Lexer\\": "tests"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"composer/package-versions-deprecated": true,
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
},
|
||||
"sort-packages": true
|
||||
}
|
||||
}
|
||||
342
config/www/user/plugins/email/vendor/doctrine/lexer/src/AbstractLexer.php
vendored
Normal file
342
config/www/user/plugins/email/vendor/doctrine/lexer/src/AbstractLexer.php
vendored
Normal file
@@ -0,0 +1,342 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Common\Lexer;
|
||||
|
||||
use ReflectionClass;
|
||||
use UnitEnum;
|
||||
|
||||
use function get_class;
|
||||
use function implode;
|
||||
use function preg_split;
|
||||
use function sprintf;
|
||||
use function substr;
|
||||
|
||||
use const PREG_SPLIT_DELIM_CAPTURE;
|
||||
use const PREG_SPLIT_NO_EMPTY;
|
||||
use const PREG_SPLIT_OFFSET_CAPTURE;
|
||||
|
||||
/**
|
||||
* Base class for writing simple lexers, i.e. for creating small DSLs.
|
||||
*
|
||||
* @template T of UnitEnum|string|int
|
||||
* @template V of string|int
|
||||
*/
|
||||
abstract class AbstractLexer
|
||||
{
|
||||
/**
|
||||
* Lexer original input string.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $input;
|
||||
|
||||
/**
|
||||
* Array of scanned tokens.
|
||||
*
|
||||
* @var list<Token<T, V>>
|
||||
*/
|
||||
private $tokens = [];
|
||||
|
||||
/**
|
||||
* Current lexer position in input string.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $position = 0;
|
||||
|
||||
/**
|
||||
* Current peek of current lexer position.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $peek = 0;
|
||||
|
||||
/**
|
||||
* The next token in the input.
|
||||
*
|
||||
* @var Token<T, V>|null
|
||||
*/
|
||||
public $lookahead;
|
||||
|
||||
/**
|
||||
* The last matched/seen token.
|
||||
*
|
||||
* @var Token<T, V>|null
|
||||
*/
|
||||
public $token;
|
||||
|
||||
/**
|
||||
* Composed regex for input parsing.
|
||||
*
|
||||
* @var non-empty-string|null
|
||||
*/
|
||||
private $regex;
|
||||
|
||||
/**
|
||||
* Sets the input data to be tokenized.
|
||||
*
|
||||
* The Lexer is immediately reset and the new input tokenized.
|
||||
* Any unprocessed tokens from any previous input are lost.
|
||||
*
|
||||
* @param string $input The input to be tokenized.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setInput($input)
|
||||
{
|
||||
$this->input = $input;
|
||||
$this->tokens = [];
|
||||
|
||||
$this->reset();
|
||||
$this->scan($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the lexer.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->lookahead = null;
|
||||
$this->token = null;
|
||||
$this->peek = 0;
|
||||
$this->position = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the peek pointer to 0.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetPeek()
|
||||
{
|
||||
$this->peek = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the lexer position on the input to the given position.
|
||||
*
|
||||
* @param int $position Position to place the lexical scanner.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetPosition($position = 0)
|
||||
{
|
||||
$this->position = $position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the original lexer's input until a given position.
|
||||
*
|
||||
* @param int $position
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getInputUntilPosition($position)
|
||||
{
|
||||
return substr($this->input, 0, $position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a given token matches the current lookahead.
|
||||
*
|
||||
* @param T $type
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @psalm-assert-if-true !=null $this->lookahead
|
||||
*/
|
||||
public function isNextToken($type)
|
||||
{
|
||||
return $this->lookahead !== null && $this->lookahead->isA($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether any of the given tokens matches the current lookahead.
|
||||
*
|
||||
* @param list<T> $types
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @psalm-assert-if-true !=null $this->lookahead
|
||||
*/
|
||||
public function isNextTokenAny(array $types)
|
||||
{
|
||||
return $this->lookahead !== null && $this->lookahead->isA(...$types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves to the next token in the input string.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @psalm-assert-if-true !null $this->lookahead
|
||||
*/
|
||||
public function moveNext()
|
||||
{
|
||||
$this->peek = 0;
|
||||
$this->token = $this->lookahead;
|
||||
$this->lookahead = isset($this->tokens[$this->position])
|
||||
? $this->tokens[$this->position++] : null;
|
||||
|
||||
return $this->lookahead !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the lexer to skip input tokens until it sees a token with the given value.
|
||||
*
|
||||
* @param T $type The token type to skip until.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function skipUntil($type)
|
||||
{
|
||||
while ($this->lookahead !== null && ! $this->lookahead->isA($type)) {
|
||||
$this->moveNext();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if given value is identical to the given token.
|
||||
*
|
||||
* @param string $value
|
||||
* @param int|string $token
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isA($value, $token)
|
||||
{
|
||||
return $this->getType($value) === $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the lookahead token forward.
|
||||
*
|
||||
* @return Token<T, V>|null The next token or NULL if there are no more tokens ahead.
|
||||
*/
|
||||
public function peek()
|
||||
{
|
||||
if (isset($this->tokens[$this->position + $this->peek])) {
|
||||
return $this->tokens[$this->position + $this->peek++];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Peeks at the next token, returns it and immediately resets the peek.
|
||||
*
|
||||
* @return Token<T, V>|null The next token or NULL if there are no more tokens ahead.
|
||||
*/
|
||||
public function glimpse()
|
||||
{
|
||||
$peek = $this->peek();
|
||||
$this->peek = 0;
|
||||
|
||||
return $peek;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the input string for tokens.
|
||||
*
|
||||
* @param string $input A query string.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function scan($input)
|
||||
{
|
||||
if (! isset($this->regex)) {
|
||||
$this->regex = sprintf(
|
||||
'/(%s)|%s/%s',
|
||||
implode(')|(', $this->getCatchablePatterns()),
|
||||
implode('|', $this->getNonCatchablePatterns()),
|
||||
$this->getModifiers()
|
||||
);
|
||||
}
|
||||
|
||||
$flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE;
|
||||
$matches = preg_split($this->regex, $input, -1, $flags);
|
||||
|
||||
if ($matches === false) {
|
||||
// Work around https://bugs.php.net/78122
|
||||
$matches = [[$input, 0]];
|
||||
}
|
||||
|
||||
foreach ($matches as $match) {
|
||||
// Must remain before 'value' assignment since it can change content
|
||||
$firstMatch = $match[0];
|
||||
$type = $this->getType($firstMatch);
|
||||
|
||||
$this->tokens[] = new Token(
|
||||
$firstMatch,
|
||||
$type,
|
||||
$match[1]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the literal for a given token.
|
||||
*
|
||||
* @param T $token
|
||||
*
|
||||
* @return int|string
|
||||
*/
|
||||
public function getLiteral($token)
|
||||
{
|
||||
if ($token instanceof UnitEnum) {
|
||||
return get_class($token) . '::' . $token->name;
|
||||
}
|
||||
|
||||
$className = static::class;
|
||||
|
||||
$reflClass = new ReflectionClass($className);
|
||||
$constants = $reflClass->getConstants();
|
||||
|
||||
foreach ($constants as $name => $value) {
|
||||
if ($value === $token) {
|
||||
return $className . '::' . $name;
|
||||
}
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Regex modifiers
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getModifiers()
|
||||
{
|
||||
return 'iu';
|
||||
}
|
||||
|
||||
/**
|
||||
* Lexical catchable patterns.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
abstract protected function getCatchablePatterns();
|
||||
|
||||
/**
|
||||
* Lexical non-catchable patterns.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
abstract protected function getNonCatchablePatterns();
|
||||
|
||||
/**
|
||||
* Retrieve token type. Also processes the token value if necessary.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return T|null
|
||||
*
|
||||
* @param-out V $value
|
||||
*/
|
||||
abstract protected function getType(&$value);
|
||||
}
|
||||
145
config/www/user/plugins/email/vendor/doctrine/lexer/src/Token.php
vendored
Normal file
145
config/www/user/plugins/email/vendor/doctrine/lexer/src/Token.php
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Common\Lexer;
|
||||
|
||||
use ArrayAccess;
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
use ReturnTypeWillChange;
|
||||
use UnitEnum;
|
||||
|
||||
use function in_array;
|
||||
|
||||
/**
|
||||
* @template T of UnitEnum|string|int
|
||||
* @template V of string|int
|
||||
* @implements ArrayAccess<string,mixed>
|
||||
*/
|
||||
final class Token implements ArrayAccess
|
||||
{
|
||||
/**
|
||||
* The string value of the token in the input string
|
||||
*
|
||||
* @readonly
|
||||
* @var V
|
||||
*/
|
||||
public $value;
|
||||
|
||||
/**
|
||||
* The type of the token (identifier, numeric, string, input parameter, none)
|
||||
*
|
||||
* @readonly
|
||||
* @var T|null
|
||||
*/
|
||||
public $type;
|
||||
|
||||
/**
|
||||
* The position of the token in the input string
|
||||
*
|
||||
* @readonly
|
||||
* @var int
|
||||
*/
|
||||
public $position;
|
||||
|
||||
/**
|
||||
* @param V $value
|
||||
* @param T|null $type
|
||||
*/
|
||||
public function __construct($value, $type, int $position)
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->type = $type;
|
||||
$this->position = $position;
|
||||
}
|
||||
|
||||
/** @param T ...$types */
|
||||
public function isA(...$types): bool
|
||||
{
|
||||
return in_array($this->type, $types, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the value, type or position property instead
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
Deprecation::trigger(
|
||||
'doctrine/lexer',
|
||||
'https://github.com/doctrine/lexer/pull/79',
|
||||
'Accessing %s properties via ArrayAccess is deprecated, use the value, type or position property instead',
|
||||
self::class
|
||||
);
|
||||
|
||||
return in_array($offset, ['value', 'type', 'position'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the value, type or position property instead
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param O $offset
|
||||
*
|
||||
* @return mixed
|
||||
* @psalm-return (
|
||||
* O is 'value'
|
||||
* ? V
|
||||
* : (
|
||||
* O is 'type'
|
||||
* ? T|null
|
||||
* : (
|
||||
* O is 'position'
|
||||
* ? int
|
||||
* : mixed
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @template O of array-key
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
Deprecation::trigger(
|
||||
'doctrine/lexer',
|
||||
'https://github.com/doctrine/lexer/pull/79',
|
||||
'Accessing %s properties via ArrayAccess is deprecated, use the value, type or position property instead',
|
||||
self::class
|
||||
);
|
||||
|
||||
return $this->$offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated no replacement planned
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
Deprecation::trigger(
|
||||
'doctrine/lexer',
|
||||
'https://github.com/doctrine/lexer/pull/79',
|
||||
'Setting %s properties via ArrayAccess is deprecated',
|
||||
self::class
|
||||
);
|
||||
|
||||
$this->$offset = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated no replacement planned
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function offsetUnset($offset): void
|
||||
{
|
||||
Deprecation::trigger(
|
||||
'doctrine/lexer',
|
||||
'https://github.com/doctrine/lexer/pull/79',
|
||||
'Setting %s properties via ArrayAccess is deprecated',
|
||||
self::class
|
||||
);
|
||||
|
||||
$this->$offset = null;
|
||||
}
|
||||
}
|
||||
33
config/www/user/plugins/email/vendor/egulias/email-validator/CHANGELOG.md
vendored
Normal file
33
config/www/user/plugins/email/vendor/egulias/email-validator/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# EmailValidator v3 Changelog
|
||||
|
||||
## New Features
|
||||
|
||||
* Access to local part and domain part from EmailParser
|
||||
* Validations outside of the scope of the RFC will be considered "extra" validations, thus opening the door for adding new; will live in their own folder "extra" (as requested in #248, #195, #183).
|
||||
|
||||
## Breaking changes
|
||||
|
||||
* PHP version upgraded to match Symfony's (as of 12/2020).
|
||||
* DNSCheckValidation now fails for missing MX records. While the RFC argues that the existence of only A records to be valid, starting in v3 they will be considered invalid.
|
||||
* Emails domain part are now intenteded to be RFC 1035 compliant, rendering previous valid emails (e.g example@examp&) invalid.
|
||||
|
||||
## PHP versions upgrade policy
|
||||
PHP version upgrade requirement will happen via MINOR (3.x) version upgrades of the library, following the adoption level by major frameworks.
|
||||
|
||||
## Changes
|
||||
* #235
|
||||
* #215
|
||||
* #130
|
||||
* #258
|
||||
* #188
|
||||
* #181
|
||||
* #217
|
||||
* #214
|
||||
* #249
|
||||
* #236
|
||||
* #257
|
||||
* #210
|
||||
|
||||
## Thanks
|
||||
To contributors, be it with PRs, reporting issues or supporting otherwise.
|
||||
|
||||
153
config/www/user/plugins/email/vendor/egulias/email-validator/CONTRIBUTING.md
vendored
Normal file
153
config/www/user/plugins/email/vendor/egulias/email-validator/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
# Contributing
|
||||
|
||||
When contributing to this repository make sure to follow the Pull request process below.
|
||||
Reduce to the minimum 3rd party dependencies.
|
||||
|
||||
Please note we have a [code of conduct](#Code of Conduct), please follow it in all your interactions with the project.
|
||||
|
||||
## Pull Request Process
|
||||
|
||||
When doing a PR to v2 remember that you also have to do the PR port to v3, or tests confirming the bug is not reproducible.
|
||||
|
||||
1. Supported version is v3. If you are fixing a bug in v2, please port to v3
|
||||
2. Use the title as a brief description of the changes
|
||||
3. Describe the changes you are proposing
|
||||
1. If adding an extra validation state the benefits of adding it and the problem is solving
|
||||
2. Document in the readme, by adding it to the list
|
||||
4. Provide appropriate tests for the code you are submitting: aim to keep the existing coverage percentage.
|
||||
5. Add your Twitter handle (if you have) so we can thank you there.
|
||||
|
||||
## License
|
||||
By contributing, you agree that your contributions will be licensed under its MIT License.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
### Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
### Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
### Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
### Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
### Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at <emailvalidatorrfc.ccreport@gmail.com>.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
#### Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
#### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
#### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
#### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
#### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
### Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
|
||||
|
||||
Community Impact Guidelines were inspired by
|
||||
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available
|
||||
at [https://www.contributor-covenant.org/translations][translations].
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
|
||||
[Mozilla CoC]: https://github.com/mozilla/diversity
|
||||
[FAQ]: https://www.contributor-covenant.org/faq
|
||||
[translations]: https://www.contributor-covenant.org/translations
|
||||
19
config/www/user/plugins/email/vendor/egulias/email-validator/LICENSE
vendored
Normal file
19
config/www/user/plugins/email/vendor/egulias/email-validator/LICENSE
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2013-2022 Eduardo Gulias Davis
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
37
config/www/user/plugins/email/vendor/egulias/email-validator/composer.json
vendored
Normal file
37
config/www/user/plugins/email/vendor/egulias/email-validator/composer.json
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "egulias/email-validator",
|
||||
"description": "A library for validating emails against several RFCs",
|
||||
"homepage": "https://github.com/egulias/EmailValidator",
|
||||
"keywords": ["email", "validation", "validator", "emailvalidation", "emailvalidator"],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{"name": "Eduardo Gulias Davis"}
|
||||
],
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0.x-dev"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"doctrine/lexer": "^1.2|^2",
|
||||
"symfony/polyfill-intl-idn": "^1.15"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.5.8|^9.3.3",
|
||||
"vimeo/psalm": "^4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Egulias\\EmailValidator\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Egulias\\EmailValidator\\Tests\\": "tests"
|
||||
}
|
||||
}
|
||||
}
|
||||
345
config/www/user/plugins/email/vendor/egulias/email-validator/src/EmailLexer.php
vendored
Normal file
345
config/www/user/plugins/email/vendor/egulias/email-validator/src/EmailLexer.php
vendored
Normal file
@@ -0,0 +1,345 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator;
|
||||
|
||||
use Doctrine\Common\Lexer\AbstractLexer;
|
||||
use Doctrine\Common\Lexer\Token;
|
||||
|
||||
/**
|
||||
* @extends AbstractLexer<int, string>
|
||||
*/
|
||||
class EmailLexer extends AbstractLexer
|
||||
{
|
||||
//ASCII values
|
||||
public const S_EMPTY = null;
|
||||
public const C_NUL = 0;
|
||||
public const S_HTAB = 9;
|
||||
public const S_LF = 10;
|
||||
public const S_CR = 13;
|
||||
public const S_SP = 32;
|
||||
public const EXCLAMATION = 33;
|
||||
public const S_DQUOTE = 34;
|
||||
public const NUMBER_SIGN = 35;
|
||||
public const DOLLAR = 36;
|
||||
public const PERCENTAGE = 37;
|
||||
public const AMPERSAND = 38;
|
||||
public const S_SQUOTE = 39;
|
||||
public const S_OPENPARENTHESIS = 40;
|
||||
public const S_CLOSEPARENTHESIS = 41;
|
||||
public const ASTERISK = 42;
|
||||
public const S_PLUS = 43;
|
||||
public const S_COMMA = 44;
|
||||
public const S_HYPHEN = 45;
|
||||
public const S_DOT = 46;
|
||||
public const S_SLASH = 47;
|
||||
public const S_COLON = 58;
|
||||
public const S_SEMICOLON = 59;
|
||||
public const S_LOWERTHAN = 60;
|
||||
public const S_EQUAL = 61;
|
||||
public const S_GREATERTHAN = 62;
|
||||
public const QUESTIONMARK = 63;
|
||||
public const S_AT = 64;
|
||||
public const S_OPENBRACKET = 91;
|
||||
public const S_BACKSLASH = 92;
|
||||
public const S_CLOSEBRACKET = 93;
|
||||
public const CARET = 94;
|
||||
public const S_UNDERSCORE = 95;
|
||||
public const S_BACKTICK = 96;
|
||||
public const S_OPENCURLYBRACES = 123;
|
||||
public const S_PIPE = 124;
|
||||
public const S_CLOSECURLYBRACES = 125;
|
||||
public const S_TILDE = 126;
|
||||
public const C_DEL = 127;
|
||||
public const INVERT_QUESTIONMARK= 168;
|
||||
public const INVERT_EXCLAMATION = 173;
|
||||
public const GENERIC = 300;
|
||||
public const S_IPV6TAG = 301;
|
||||
public const INVALID = 302;
|
||||
public const CRLF = 1310;
|
||||
public const S_DOUBLECOLON = 5858;
|
||||
public const ASCII_INVALID_FROM = 127;
|
||||
public const ASCII_INVALID_TO = 199;
|
||||
|
||||
/**
|
||||
* US-ASCII visible characters not valid for atext (@link http://tools.ietf.org/html/rfc5322#section-3.2.3)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $charValue = [
|
||||
'{' => self::S_OPENCURLYBRACES,
|
||||
'}' => self::S_CLOSECURLYBRACES,
|
||||
'(' => self::S_OPENPARENTHESIS,
|
||||
')' => self::S_CLOSEPARENTHESIS,
|
||||
'<' => self::S_LOWERTHAN,
|
||||
'>' => self::S_GREATERTHAN,
|
||||
'[' => self::S_OPENBRACKET,
|
||||
']' => self::S_CLOSEBRACKET,
|
||||
':' => self::S_COLON,
|
||||
';' => self::S_SEMICOLON,
|
||||
'@' => self::S_AT,
|
||||
'\\' => self::S_BACKSLASH,
|
||||
'/' => self::S_SLASH,
|
||||
',' => self::S_COMMA,
|
||||
'.' => self::S_DOT,
|
||||
"'" => self::S_SQUOTE,
|
||||
"`" => self::S_BACKTICK,
|
||||
'"' => self::S_DQUOTE,
|
||||
'-' => self::S_HYPHEN,
|
||||
'::' => self::S_DOUBLECOLON,
|
||||
' ' => self::S_SP,
|
||||
"\t" => self::S_HTAB,
|
||||
"\r" => self::S_CR,
|
||||
"\n" => self::S_LF,
|
||||
"\r\n" => self::CRLF,
|
||||
'IPv6' => self::S_IPV6TAG,
|
||||
'' => self::S_EMPTY,
|
||||
'\0' => self::C_NUL,
|
||||
'*' => self::ASTERISK,
|
||||
'!' => self::EXCLAMATION,
|
||||
'&' => self::AMPERSAND,
|
||||
'^' => self::CARET,
|
||||
'$' => self::DOLLAR,
|
||||
'%' => self::PERCENTAGE,
|
||||
'~' => self::S_TILDE,
|
||||
'|' => self::S_PIPE,
|
||||
'_' => self::S_UNDERSCORE,
|
||||
'=' => self::S_EQUAL,
|
||||
'+' => self::S_PLUS,
|
||||
'¿' => self::INVERT_QUESTIONMARK,
|
||||
'?' => self::QUESTIONMARK,
|
||||
'#' => self::NUMBER_SIGN,
|
||||
'¡' => self::INVERT_EXCLAMATION,
|
||||
];
|
||||
|
||||
public const INVALID_CHARS_REGEX = "/[^\p{S}\p{C}\p{Cc}]+/iu";
|
||||
|
||||
public const VALID_UTF8_REGEX = '/\p{Cc}+/u';
|
||||
|
||||
public const CATCHABLE_PATTERNS = [
|
||||
'[a-zA-Z]+[46]?', //ASCII and domain literal
|
||||
'[^\x00-\x7F]', //UTF-8
|
||||
'[0-9]+',
|
||||
'\r\n',
|
||||
'::',
|
||||
'\s+?',
|
||||
'.',
|
||||
];
|
||||
|
||||
public const NON_CATCHABLE_PATTERNS = [
|
||||
'[\xA0-\xff]+',
|
||||
];
|
||||
|
||||
public const MODIFIERS = 'iu';
|
||||
|
||||
/** @var bool */
|
||||
protected $hasInvalidTokens = false;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* @psalm-var array{value:string, type:null|int, position:int}|array<empty, empty>
|
||||
*/
|
||||
protected $previous = [];
|
||||
|
||||
/**
|
||||
* The last matched/seen token.
|
||||
*
|
||||
* @var array|Token
|
||||
*
|
||||
* @psalm-suppress NonInvariantDocblockPropertyType
|
||||
* @psalm-var array{value:string, type:null|int, position:int}|Token<int, string>
|
||||
*/
|
||||
public $token;
|
||||
|
||||
/**
|
||||
* The next token in the input.
|
||||
*
|
||||
* @var array|Token|null
|
||||
*
|
||||
* @psalm-suppress NonInvariantDocblockPropertyType
|
||||
* @psalm-var array{position: int, type: int|null|string, value: int|string}|Token<int, string>|null
|
||||
*/
|
||||
public $lookahead;
|
||||
|
||||
/** @psalm-var array{value:'', type:null, position:0} */
|
||||
private static $nullToken = [
|
||||
'value' => '',
|
||||
'type' => null,
|
||||
'position' => 0,
|
||||
];
|
||||
|
||||
/** @var string */
|
||||
private $accumulator = '';
|
||||
|
||||
/** @var bool */
|
||||
private $hasToRecord = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->previous = $this->token = self::$nullToken;
|
||||
$this->lookahead = null;
|
||||
}
|
||||
|
||||
public function reset() : void
|
||||
{
|
||||
$this->hasInvalidTokens = false;
|
||||
parent::reset();
|
||||
$this->previous = $this->token = self::$nullToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
* @throws \UnexpectedValueException
|
||||
* @return boolean
|
||||
*
|
||||
* @psalm-suppress InvalidScalarArgument
|
||||
*/
|
||||
public function find($type) : bool
|
||||
{
|
||||
$search = clone $this;
|
||||
$search->skipUntil($type);
|
||||
|
||||
if (!$search->lookahead) {
|
||||
throw new \UnexpectedValueException($type . ' not found');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* moveNext
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function moveNext() : bool
|
||||
{
|
||||
if ($this->hasToRecord && $this->previous === self::$nullToken) {
|
||||
$this->accumulator .= ((array) $this->token)['value'];
|
||||
}
|
||||
|
||||
$this->previous = (array) $this->token;
|
||||
|
||||
if($this->lookahead === null) {
|
||||
$this->lookahead = self::$nullToken;
|
||||
}
|
||||
|
||||
$hasNext = parent::moveNext();
|
||||
|
||||
if ($this->hasToRecord) {
|
||||
$this->accumulator .= ((array) $this->token)['value'];
|
||||
}
|
||||
|
||||
return $hasNext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve token type. Also processes the token value if necessary.
|
||||
*
|
||||
* @param string $value
|
||||
* @throws \InvalidArgumentException
|
||||
* @return integer
|
||||
*/
|
||||
protected function getType(&$value)
|
||||
{
|
||||
$encoded = $value;
|
||||
|
||||
if (mb_detect_encoding($value, 'auto', true) !== 'UTF-8') {
|
||||
$encoded = mb_convert_encoding($value, 'UTF-8', 'Windows-1252');
|
||||
}
|
||||
|
||||
if ($this->isValid($encoded)) {
|
||||
return $this->charValue[$encoded];
|
||||
}
|
||||
|
||||
if ($this->isNullType($encoded)) {
|
||||
return self::C_NUL;
|
||||
}
|
||||
|
||||
if ($this->isInvalidChar($encoded)) {
|
||||
$this->hasInvalidTokens = true;
|
||||
return self::INVALID;
|
||||
}
|
||||
|
||||
|
||||
return self::GENERIC;
|
||||
}
|
||||
|
||||
protected function isValid(string $value) : bool
|
||||
{
|
||||
return isset($this->charValue[$value]);
|
||||
}
|
||||
|
||||
protected function isNullType(string $value) : bool
|
||||
{
|
||||
return $value === "\0";
|
||||
}
|
||||
|
||||
protected function isInvalidChar(string $value) : bool
|
||||
{
|
||||
return !preg_match(self::INVALID_CHARS_REGEX, $value);
|
||||
}
|
||||
|
||||
protected function isUTF8Invalid(string $value) : bool
|
||||
{
|
||||
return preg_match(self::VALID_UTF8_REGEX, $value) !== false;
|
||||
}
|
||||
|
||||
public function hasInvalidTokens() : bool
|
||||
{
|
||||
return $this->hasInvalidTokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* getPrevious
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPrevious() : array
|
||||
{
|
||||
return $this->previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lexical catchable patterns.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getCatchablePatterns() : array
|
||||
{
|
||||
return self::CATCHABLE_PATTERNS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lexical non-catchable patterns.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getNonCatchablePatterns() : array
|
||||
{
|
||||
return self::NON_CATCHABLE_PATTERNS;
|
||||
}
|
||||
|
||||
protected function getModifiers() : string
|
||||
{
|
||||
return self::MODIFIERS;
|
||||
}
|
||||
|
||||
public function getAccumulatedValues() : string
|
||||
{
|
||||
return $this->accumulator;
|
||||
}
|
||||
|
||||
public function startRecording() : void
|
||||
{
|
||||
$this->hasToRecord = true;
|
||||
}
|
||||
|
||||
public function stopRecording() : void
|
||||
{
|
||||
$this->hasToRecord = false;
|
||||
}
|
||||
|
||||
public function clearRecorded() : void
|
||||
{
|
||||
$this->accumulator = '';
|
||||
}
|
||||
}
|
||||
90
config/www/user/plugins/email/vendor/egulias/email-validator/src/EmailParser.php
vendored
Normal file
90
config/www/user/plugins/email/vendor/egulias/email-validator/src/EmailParser.php
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator;
|
||||
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Parser\LocalPart;
|
||||
use Egulias\EmailValidator\Parser\DomainPart;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Warning\EmailTooLong;
|
||||
use Egulias\EmailValidator\Result\Reason\NoLocalPart;
|
||||
|
||||
class EmailParser extends Parser
|
||||
{
|
||||
public const EMAIL_MAX_LENGTH = 254;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $domainPart = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $localPart = '';
|
||||
|
||||
public function parse(string $str) : Result
|
||||
{
|
||||
$result = parent::parse($str);
|
||||
|
||||
$this->addLongEmailWarning($this->localPart, $this->domainPart);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function preLeftParsing(): Result
|
||||
{
|
||||
if (!$this->hasAtToken()) {
|
||||
return new InvalidEmail(new NoLocalPart(), $this->lexer->token["value"]);
|
||||
}
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
protected function parseLeftFromAt(): Result
|
||||
{
|
||||
return $this->processLocalPart();
|
||||
}
|
||||
|
||||
protected function parseRightFromAt(): Result
|
||||
{
|
||||
return $this->processDomainPart();
|
||||
}
|
||||
|
||||
private function processLocalPart() : Result
|
||||
{
|
||||
$localPartParser = new LocalPart($this->lexer);
|
||||
$localPartResult = $localPartParser->parse();
|
||||
$this->localPart = $localPartParser->localPart();
|
||||
$this->warnings = array_merge($localPartParser->getWarnings(), $this->warnings);
|
||||
|
||||
return $localPartResult;
|
||||
}
|
||||
|
||||
private function processDomainPart() : Result
|
||||
{
|
||||
$domainPartParser = new DomainPart($this->lexer);
|
||||
$domainPartResult = $domainPartParser->parse();
|
||||
$this->domainPart = $domainPartParser->domainPart();
|
||||
$this->warnings = array_merge($domainPartParser->getWarnings(), $this->warnings);
|
||||
|
||||
return $domainPartResult;
|
||||
}
|
||||
|
||||
public function getDomainPart() : string
|
||||
{
|
||||
return $this->domainPart;
|
||||
}
|
||||
|
||||
public function getLocalPart() : string
|
||||
{
|
||||
return $this->localPart;
|
||||
}
|
||||
|
||||
private function addLongEmailWarning(string $localPart, string $parsedDomainPart) : void
|
||||
{
|
||||
if (strlen($localPart . '@' . $parsedDomainPart) > self::EMAIL_MAX_LENGTH) {
|
||||
$this->warnings[EmailTooLong::CODE] = new EmailTooLong();
|
||||
}
|
||||
}
|
||||
}
|
||||
67
config/www/user/plugins/email/vendor/egulias/email-validator/src/EmailValidator.php
vendored
Normal file
67
config/www/user/plugins/email/vendor/egulias/email-validator/src/EmailValidator.php
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator;
|
||||
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Validation\EmailValidation;
|
||||
|
||||
class EmailValidator
|
||||
{
|
||||
/**
|
||||
* @var EmailLexer
|
||||
*/
|
||||
private $lexer;
|
||||
|
||||
/**
|
||||
* @var Warning\Warning[]
|
||||
*/
|
||||
private $warnings = [];
|
||||
|
||||
/**
|
||||
* @var ?InvalidEmail
|
||||
*/
|
||||
private $error;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->lexer = new EmailLexer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $email
|
||||
* @param EmailValidation $emailValidation
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid(string $email, EmailValidation $emailValidation)
|
||||
{
|
||||
$isValid = $emailValidation->isValid($email, $this->lexer);
|
||||
$this->warnings = $emailValidation->getWarnings();
|
||||
$this->error = $emailValidation->getError();
|
||||
|
||||
return $isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasWarnings()
|
||||
{
|
||||
return !empty($this->warnings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getWarnings()
|
||||
{
|
||||
return $this->warnings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InvalidEmail|null
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
}
|
||||
91
config/www/user/plugins/email/vendor/egulias/email-validator/src/MessageIDParser.php
vendored
Normal file
91
config/www/user/plugins/email/vendor/egulias/email-validator/src/MessageIDParser.php
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator;
|
||||
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Parser\IDLeftPart;
|
||||
use Egulias\EmailValidator\Parser\IDRightPart;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Warning\EmailTooLong;
|
||||
use Egulias\EmailValidator\Result\Reason\NoLocalPart;
|
||||
|
||||
class MessageIDParser extends Parser
|
||||
{
|
||||
|
||||
public const EMAILID_MAX_LENGTH = 254;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $idLeft = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $idRight = '';
|
||||
|
||||
public function parse(string $str) : Result
|
||||
{
|
||||
$result = parent::parse($str);
|
||||
|
||||
$this->addLongEmailWarning($this->idLeft, $this->idRight);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function preLeftParsing(): Result
|
||||
{
|
||||
if (!$this->hasAtToken()) {
|
||||
return new InvalidEmail(new NoLocalPart(), $this->lexer->token["value"]);
|
||||
}
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
protected function parseLeftFromAt(): Result
|
||||
{
|
||||
return $this->processIDLeft();
|
||||
}
|
||||
|
||||
protected function parseRightFromAt(): Result
|
||||
{
|
||||
return $this->processIDRight();
|
||||
}
|
||||
|
||||
private function processIDLeft() : Result
|
||||
{
|
||||
$localPartParser = new IDLeftPart($this->lexer);
|
||||
$localPartResult = $localPartParser->parse();
|
||||
$this->idLeft = $localPartParser->localPart();
|
||||
$this->warnings = array_merge($localPartParser->getWarnings(), $this->warnings);
|
||||
|
||||
return $localPartResult;
|
||||
}
|
||||
|
||||
private function processIDRight() : Result
|
||||
{
|
||||
$domainPartParser = new IDRightPart($this->lexer);
|
||||
$domainPartResult = $domainPartParser->parse();
|
||||
$this->idRight = $domainPartParser->domainPart();
|
||||
$this->warnings = array_merge($domainPartParser->getWarnings(), $this->warnings);
|
||||
|
||||
return $domainPartResult;
|
||||
}
|
||||
|
||||
public function getLeftPart() : string
|
||||
{
|
||||
return $this->idLeft;
|
||||
}
|
||||
|
||||
public function getRightPart() : string
|
||||
{
|
||||
return $this->idRight;
|
||||
}
|
||||
|
||||
private function addLongEmailWarning(string $localPart, string $parsedDomainPart) : void
|
||||
{
|
||||
if (strlen($localPart . '@' . $parsedDomainPart) > self::EMAILID_MAX_LENGTH) {
|
||||
$this->warnings[EmailTooLong::CODE] = new EmailTooLong();
|
||||
}
|
||||
}
|
||||
}
|
||||
78
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser.php
vendored
Normal file
78
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser.php
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator;
|
||||
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Result\Reason\ExpectingATEXT;
|
||||
|
||||
abstract class Parser
|
||||
{
|
||||
/**
|
||||
* @var Warning\Warning[]
|
||||
*/
|
||||
protected $warnings = [];
|
||||
|
||||
/**
|
||||
* @var EmailLexer
|
||||
*/
|
||||
protected $lexer;
|
||||
|
||||
/**
|
||||
* id-left "@" id-right
|
||||
*/
|
||||
abstract protected function parseRightFromAt() : Result;
|
||||
abstract protected function parseLeftFromAt() : Result;
|
||||
abstract protected function preLeftParsing() : Result;
|
||||
|
||||
|
||||
public function __construct(EmailLexer $lexer)
|
||||
{
|
||||
$this->lexer = $lexer;
|
||||
}
|
||||
|
||||
public function parse(string $str) : Result
|
||||
{
|
||||
$this->lexer->setInput($str);
|
||||
|
||||
if ($this->lexer->hasInvalidTokens()) {
|
||||
return new InvalidEmail(new ExpectingATEXT("Invalid tokens found"), $this->lexer->token["value"]);
|
||||
}
|
||||
|
||||
$preParsingResult = $this->preLeftParsing();
|
||||
if ($preParsingResult->isInvalid()) {
|
||||
return $preParsingResult;
|
||||
}
|
||||
|
||||
$localPartResult = $this->parseLeftFromAt();
|
||||
|
||||
if ($localPartResult->isInvalid()) {
|
||||
return $localPartResult;
|
||||
}
|
||||
|
||||
$domainPartResult = $this->parseRightFromAt();
|
||||
|
||||
if ($domainPartResult->isInvalid()) {
|
||||
return $domainPartResult;
|
||||
}
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Warning\Warning[]
|
||||
*/
|
||||
public function getWarnings() : array
|
||||
{
|
||||
return $this->warnings;
|
||||
}
|
||||
|
||||
protected function hasAtToken() : bool
|
||||
{
|
||||
$this->lexer->moveNext();
|
||||
$this->lexer->moveNext();
|
||||
|
||||
return ((array) $this->lexer->token)['type'] !== EmailLexer::S_AT;
|
||||
}
|
||||
}
|
||||
104
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/Comment.php
vendored
Normal file
104
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/Comment.php
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Warning\QuotedPart;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Parser\CommentStrategy\CommentStrategy;
|
||||
use Egulias\EmailValidator\Result\Reason\UnclosedComment;
|
||||
use Egulias\EmailValidator\Result\Reason\UnOpenedComment;
|
||||
use Egulias\EmailValidator\Warning\Comment as WarningComment;
|
||||
|
||||
class Comment extends PartParser
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $openedParenthesis = 0;
|
||||
|
||||
/**
|
||||
* @var CommentStrategy
|
||||
*/
|
||||
private $commentStrategy;
|
||||
|
||||
public function __construct(EmailLexer $lexer, CommentStrategy $commentStrategy)
|
||||
{
|
||||
$this->lexer = $lexer;
|
||||
$this->commentStrategy = $commentStrategy;
|
||||
}
|
||||
|
||||
public function parse() : Result
|
||||
{
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_OPENPARENTHESIS) {
|
||||
$this->openedParenthesis++;
|
||||
if($this->noClosingParenthesis()) {
|
||||
return new InvalidEmail(new UnclosedComment(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_CLOSEPARENTHESIS) {
|
||||
return new InvalidEmail(new UnOpenedComment(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
$this->warnings[WarningComment::CODE] = new WarningComment();
|
||||
|
||||
$moreTokens = true;
|
||||
while ($this->commentStrategy->exitCondition($this->lexer, $this->openedParenthesis) && $moreTokens){
|
||||
|
||||
if ($this->lexer->isNextToken(EmailLexer::S_OPENPARENTHESIS)) {
|
||||
$this->openedParenthesis++;
|
||||
}
|
||||
$this->warnEscaping();
|
||||
if($this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) {
|
||||
$this->openedParenthesis--;
|
||||
}
|
||||
$moreTokens = $this->lexer->moveNext();
|
||||
}
|
||||
|
||||
if($this->openedParenthesis >= 1) {
|
||||
return new InvalidEmail(new UnclosedComment(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
if ($this->openedParenthesis < 0) {
|
||||
return new InvalidEmail(new UnOpenedComment(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
$finalValidations = $this->commentStrategy->endOfLoopValidations($this->lexer);
|
||||
|
||||
$this->warnings = array_merge($this->warnings, $this->commentStrategy->getWarnings());
|
||||
|
||||
return $finalValidations;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function warnEscaping() : bool
|
||||
{
|
||||
//Backslash found
|
||||
if (((array) $this->lexer->token)['type'] !== EmailLexer::S_BACKSLASH) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB, EmailLexer::C_DEL))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->warnings[QuotedPart::CODE] =
|
||||
new QuotedPart($this->lexer->getPrevious()['type'], ((array) $this->lexer->token)['type']);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private function noClosingParenthesis() : bool
|
||||
{
|
||||
try {
|
||||
$this->lexer->find(EmailLexer::S_CLOSEPARENTHESIS);
|
||||
return false;
|
||||
} catch (\RuntimeException $e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Parser\CommentStrategy;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
|
||||
interface CommentStrategy
|
||||
{
|
||||
/**
|
||||
* Return "true" to continue, "false" to exit
|
||||
*/
|
||||
public function exitCondition(EmailLexer $lexer, int $openedParenthesis) : bool;
|
||||
|
||||
public function endOfLoopValidations(EmailLexer $lexer) : Result;
|
||||
|
||||
public function getWarnings() : array;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Parser\CommentStrategy;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Result\Reason\ExpectingATEXT;
|
||||
|
||||
class DomainComment implements CommentStrategy
|
||||
{
|
||||
public function exitCondition(EmailLexer $lexer, int $openedParenthesis) : bool
|
||||
{
|
||||
if (($openedParenthesis === 0 && $lexer->isNextToken(EmailLexer::S_DOT))){ // || !$internalLexer->moveNext()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function endOfLoopValidations(EmailLexer $lexer) : Result
|
||||
{
|
||||
//test for end of string
|
||||
if (!$lexer->isNextToken(EmailLexer::S_DOT)) {
|
||||
return new InvalidEmail(new ExpectingATEXT('DOT not found near CLOSEPARENTHESIS'), ((array) $lexer->token)['value']);
|
||||
}
|
||||
//add warning
|
||||
//Address is valid within the message but cannot be used unmodified for the envelope
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
public function getWarnings(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Parser\CommentStrategy;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
use Egulias\EmailValidator\Warning\CFWSNearAt;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Result\Reason\ExpectingATEXT;
|
||||
|
||||
class LocalComment implements CommentStrategy
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $warnings = [];
|
||||
|
||||
public function exitCondition(EmailLexer $lexer, int $openedParenthesis) : bool
|
||||
{
|
||||
return !$lexer->isNextToken(EmailLexer::S_AT);
|
||||
}
|
||||
|
||||
public function endOfLoopValidations(EmailLexer $lexer) : Result
|
||||
{
|
||||
if (!$lexer->isNextToken(EmailLexer::S_AT)) {
|
||||
return new InvalidEmail(new ExpectingATEXT('ATEX is not expected after closing comments'), ((array) $lexer->token)['value']);
|
||||
}
|
||||
$this->warnings[CFWSNearAt::CODE] = new CFWSNearAt();
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
public function getWarnings(): array
|
||||
{
|
||||
return $this->warnings;
|
||||
}
|
||||
}
|
||||
211
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/DomainLiteral.php
vendored
Normal file
211
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/DomainLiteral.php
vendored
Normal file
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Warning\CFWSWithFWS;
|
||||
use Egulias\EmailValidator\Warning\IPV6BadChar;
|
||||
use Egulias\EmailValidator\Result\Reason\CRNoLF;
|
||||
use Egulias\EmailValidator\Warning\IPV6ColonEnd;
|
||||
use Egulias\EmailValidator\Warning\IPV6MaxGroups;
|
||||
use Egulias\EmailValidator\Warning\ObsoleteDTEXT;
|
||||
use Egulias\EmailValidator\Warning\AddressLiteral;
|
||||
use Egulias\EmailValidator\Warning\IPV6ColonStart;
|
||||
use Egulias\EmailValidator\Warning\IPV6Deprecated;
|
||||
use Egulias\EmailValidator\Warning\IPV6GroupCount;
|
||||
use Egulias\EmailValidator\Warning\IPV6DoubleColon;
|
||||
use Egulias\EmailValidator\Result\Reason\ExpectingDTEXT;
|
||||
use Egulias\EmailValidator\Result\Reason\UnusualElements;
|
||||
use Egulias\EmailValidator\Warning\DomainLiteral as WarningDomainLiteral;
|
||||
|
||||
class DomainLiteral extends PartParser
|
||||
{
|
||||
public const IPV4_REGEX = '/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/';
|
||||
|
||||
public const OBSOLETE_WARNINGS = [
|
||||
EmailLexer::INVALID,
|
||||
EmailLexer::C_DEL,
|
||||
EmailLexer::S_LF,
|
||||
EmailLexer::S_BACKSLASH
|
||||
];
|
||||
|
||||
public function parse() : Result
|
||||
{
|
||||
$this->addTagWarnings();
|
||||
|
||||
$IPv6TAG = false;
|
||||
$addressLiteral = '';
|
||||
|
||||
do {
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::C_NUL) {
|
||||
return new InvalidEmail(new ExpectingDTEXT(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
$this->addObsoleteWarnings();
|
||||
|
||||
if ($this->lexer->isNextTokenAny(array(EmailLexer::S_OPENBRACKET, EmailLexer::S_OPENBRACKET))) {
|
||||
return new InvalidEmail(new ExpectingDTEXT(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
if ($this->lexer->isNextTokenAny(
|
||||
array(EmailLexer::S_HTAB, EmailLexer::S_SP, EmailLexer::CRLF)
|
||||
)) {
|
||||
$this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS();
|
||||
$this->parseFWS();
|
||||
}
|
||||
|
||||
if ($this->lexer->isNextToken(EmailLexer::S_CR)) {
|
||||
return new InvalidEmail(new CRNoLF(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_BACKSLASH) {
|
||||
return new InvalidEmail(new UnusualElements(((array) $this->lexer->token)['value']), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_IPV6TAG) {
|
||||
$IPv6TAG = true;
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_CLOSEBRACKET) {
|
||||
break;
|
||||
}
|
||||
|
||||
$addressLiteral .= ((array) $this->lexer->token)['value'];
|
||||
|
||||
} while ($this->lexer->moveNext());
|
||||
|
||||
|
||||
//Encapsulate
|
||||
$addressLiteral = str_replace('[', '', $addressLiteral);
|
||||
$isAddressLiteralIPv4 = $this->checkIPV4Tag($addressLiteral);
|
||||
|
||||
if (!$isAddressLiteralIPv4) {
|
||||
return new ValidEmail();
|
||||
} else {
|
||||
$addressLiteral = $this->convertIPv4ToIPv6($addressLiteral);
|
||||
}
|
||||
|
||||
if (!$IPv6TAG) {
|
||||
$this->warnings[WarningDomainLiteral::CODE] = new WarningDomainLiteral();
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
$this->warnings[AddressLiteral::CODE] = new AddressLiteral();
|
||||
|
||||
$this->checkIPV6Tag($addressLiteral);
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $addressLiteral
|
||||
* @param int $maxGroups
|
||||
*/
|
||||
public function checkIPV6Tag($addressLiteral, $maxGroups = 8) : void
|
||||
{
|
||||
$prev = $this->lexer->getPrevious();
|
||||
if ($prev['type'] === EmailLexer::S_COLON) {
|
||||
$this->warnings[IPV6ColonEnd::CODE] = new IPV6ColonEnd();
|
||||
}
|
||||
|
||||
$IPv6 = substr($addressLiteral, 5);
|
||||
//Daniel Marschall's new IPv6 testing strategy
|
||||
$matchesIP = explode(':', $IPv6);
|
||||
$groupCount = count($matchesIP);
|
||||
$colons = strpos($IPv6, '::');
|
||||
|
||||
if (count(preg_grep('/^[0-9A-Fa-f]{0,4}$/', $matchesIP, PREG_GREP_INVERT)) !== 0) {
|
||||
$this->warnings[IPV6BadChar::CODE] = new IPV6BadChar();
|
||||
}
|
||||
|
||||
if ($colons === false) {
|
||||
// We need exactly the right number of groups
|
||||
if ($groupCount !== $maxGroups) {
|
||||
$this->warnings[IPV6GroupCount::CODE] = new IPV6GroupCount();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ($colons !== strrpos($IPv6, '::')) {
|
||||
$this->warnings[IPV6DoubleColon::CODE] = new IPV6DoubleColon();
|
||||
return;
|
||||
}
|
||||
|
||||
if ($colons === 0 || $colons === (strlen($IPv6) - 2)) {
|
||||
// RFC 4291 allows :: at the start or end of an address
|
||||
//with 7 other groups in addition
|
||||
++$maxGroups;
|
||||
}
|
||||
|
||||
if ($groupCount > $maxGroups) {
|
||||
$this->warnings[IPV6MaxGroups::CODE] = new IPV6MaxGroups();
|
||||
} elseif ($groupCount === $maxGroups) {
|
||||
$this->warnings[IPV6Deprecated::CODE] = new IPV6Deprecated();
|
||||
}
|
||||
}
|
||||
|
||||
public function convertIPv4ToIPv6(string $addressLiteralIPv4) : string
|
||||
{
|
||||
$matchesIP = [];
|
||||
$IPv4Match = preg_match(self::IPV4_REGEX, $addressLiteralIPv4, $matchesIP);
|
||||
|
||||
// Extract IPv4 part from the end of the address-literal (if there is one)
|
||||
if ($IPv4Match > 0) {
|
||||
$index = (int) strrpos($addressLiteralIPv4, $matchesIP[0]);
|
||||
//There's a match but it is at the start
|
||||
if ($index > 0) {
|
||||
// Convert IPv4 part to IPv6 format for further testing
|
||||
return substr($addressLiteralIPv4, 0, $index) . '0:0';
|
||||
}
|
||||
}
|
||||
|
||||
return $addressLiteralIPv4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $addressLiteral
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkIPV4Tag($addressLiteral) : bool
|
||||
{
|
||||
$matchesIP = [];
|
||||
$IPv4Match = preg_match(self::IPV4_REGEX, $addressLiteral, $matchesIP);
|
||||
|
||||
// Extract IPv4 part from the end of the address-literal (if there is one)
|
||||
|
||||
if ($IPv4Match > 0) {
|
||||
$index = strrpos($addressLiteral, $matchesIP[0]);
|
||||
//There's a match but it is at the start
|
||||
if ($index === 0) {
|
||||
$this->warnings[AddressLiteral::CODE] = new AddressLiteral();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function addObsoleteWarnings() : void
|
||||
{
|
||||
if(in_array(((array) $this->lexer->token)['type'], self::OBSOLETE_WARNINGS)) {
|
||||
$this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT();
|
||||
}
|
||||
}
|
||||
|
||||
private function addTagWarnings() : void
|
||||
{
|
||||
if ($this->lexer->isNextToken(EmailLexer::S_COLON)) {
|
||||
$this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart();
|
||||
}
|
||||
if ($this->lexer->isNextToken(EmailLexer::S_IPV6TAG)) {
|
||||
$lexer = clone $this->lexer;
|
||||
$lexer->moveNext();
|
||||
if ($lexer->isNextToken(EmailLexer::S_DOUBLECOLON)) {
|
||||
$this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
316
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/DomainPart.php
vendored
Normal file
316
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/DomainPart.php
vendored
Normal file
@@ -0,0 +1,316 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Doctrine\Common\Lexer\Token;
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Warning\TLD;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Result\Reason\DotAtEnd;
|
||||
use Egulias\EmailValidator\Result\Reason\DotAtStart;
|
||||
use Egulias\EmailValidator\Warning\DeprecatedComment;
|
||||
use Egulias\EmailValidator\Result\Reason\CRLFAtTheEnd;
|
||||
use Egulias\EmailValidator\Result\Reason\LabelTooLong;
|
||||
use Egulias\EmailValidator\Result\Reason\NoDomainPart;
|
||||
use Egulias\EmailValidator\Result\Reason\ConsecutiveAt;
|
||||
use Egulias\EmailValidator\Result\Reason\DomainTooLong;
|
||||
use Egulias\EmailValidator\Result\Reason\CharNotAllowed;
|
||||
use Egulias\EmailValidator\Result\Reason\DomainHyphened;
|
||||
use Egulias\EmailValidator\Result\Reason\ExpectingATEXT;
|
||||
use Egulias\EmailValidator\Parser\CommentStrategy\DomainComment;
|
||||
use Egulias\EmailValidator\Result\Reason\ExpectingDomainLiteralClose;
|
||||
use Egulias\EmailValidator\Parser\DomainLiteral as DomainLiteralParser;
|
||||
|
||||
class DomainPart extends PartParser
|
||||
{
|
||||
public const DOMAIN_MAX_LENGTH = 253;
|
||||
public const LABEL_MAX_LENGTH = 63;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $domainPart = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $label = '';
|
||||
|
||||
public function parse() : Result
|
||||
{
|
||||
$this->lexer->clearRecorded();
|
||||
$this->lexer->startRecording();
|
||||
|
||||
$this->lexer->moveNext();
|
||||
|
||||
$domainChecks = $this->performDomainStartChecks();
|
||||
if ($domainChecks->isInvalid()) {
|
||||
return $domainChecks;
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_AT) {
|
||||
return new InvalidEmail(new ConsecutiveAt(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
$result = $this->doParseDomainPart();
|
||||
if ($result->isInvalid()) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$end = $this->checkEndOfDomain();
|
||||
if ($end->isInvalid()) {
|
||||
return $end;
|
||||
}
|
||||
|
||||
$this->lexer->stopRecording();
|
||||
$this->domainPart = $this->lexer->getAccumulatedValues();
|
||||
|
||||
$length = strlen($this->domainPart);
|
||||
if ($length > self::DOMAIN_MAX_LENGTH) {
|
||||
return new InvalidEmail(new DomainTooLong(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
private function checkEndOfDomain() : Result
|
||||
{
|
||||
$prev = $this->lexer->getPrevious();
|
||||
if ($prev['type'] === EmailLexer::S_DOT) {
|
||||
return new InvalidEmail(new DotAtEnd(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
if ($prev['type'] === EmailLexer::S_HYPHEN) {
|
||||
return new InvalidEmail(new DomainHyphened('Hypen found at the end of the domain'), $prev['value']);
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_SP) {
|
||||
return new InvalidEmail(new CRLFAtTheEnd(), $prev['value']);
|
||||
}
|
||||
return new ValidEmail();
|
||||
|
||||
}
|
||||
|
||||
private function performDomainStartChecks() : Result
|
||||
{
|
||||
$invalidTokens = $this->checkInvalidTokensAfterAT();
|
||||
if ($invalidTokens->isInvalid()) {
|
||||
return $invalidTokens;
|
||||
}
|
||||
|
||||
$missingDomain = $this->checkEmptyDomain();
|
||||
if ($missingDomain->isInvalid()) {
|
||||
return $missingDomain;
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_OPENPARENTHESIS) {
|
||||
$this->warnings[DeprecatedComment::CODE] = new DeprecatedComment();
|
||||
}
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
private function checkEmptyDomain() : Result
|
||||
{
|
||||
$thereIsNoDomain = ((array) $this->lexer->token)['type'] === EmailLexer::S_EMPTY ||
|
||||
(((array) $this->lexer->token)['type'] === EmailLexer::S_SP &&
|
||||
!$this->lexer->isNextToken(EmailLexer::GENERIC));
|
||||
|
||||
if ($thereIsNoDomain) {
|
||||
return new InvalidEmail(new NoDomainPart(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
private function checkInvalidTokensAfterAT() : Result
|
||||
{
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_DOT) {
|
||||
return new InvalidEmail(new DotAtStart(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_HYPHEN) {
|
||||
return new InvalidEmail(new DomainHyphened('After AT'), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
protected function parseComments(): Result
|
||||
{
|
||||
$commentParser = new Comment($this->lexer, new DomainComment());
|
||||
$result = $commentParser->parse();
|
||||
$this->warnings = array_merge($this->warnings, $commentParser->getWarnings());
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function doParseDomainPart() : Result
|
||||
{
|
||||
$tldMissing = true;
|
||||
$hasComments = false;
|
||||
$domain = '';
|
||||
do {
|
||||
$prev = $this->lexer->getPrevious();
|
||||
|
||||
$notAllowedChars = $this->checkNotAllowedChars($this->lexer->token);
|
||||
if ($notAllowedChars->isInvalid()) {
|
||||
return $notAllowedChars;
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_OPENPARENTHESIS ||
|
||||
((array) $this->lexer->token)['type'] === EmailLexer::S_CLOSEPARENTHESIS ) {
|
||||
$hasComments = true;
|
||||
$commentsResult = $this->parseComments();
|
||||
|
||||
//Invalid comment parsing
|
||||
if($commentsResult->isInvalid()) {
|
||||
return $commentsResult;
|
||||
}
|
||||
}
|
||||
|
||||
$dotsResult = $this->checkConsecutiveDots();
|
||||
if ($dotsResult->isInvalid()) {
|
||||
return $dotsResult;
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_OPENBRACKET) {
|
||||
$literalResult = $this->parseDomainLiteral();
|
||||
|
||||
$this->addTLDWarnings($tldMissing);
|
||||
return $literalResult;
|
||||
}
|
||||
|
||||
$labelCheck = $this->checkLabelLength();
|
||||
if ($labelCheck->isInvalid()) {
|
||||
return $labelCheck;
|
||||
}
|
||||
|
||||
$FwsResult = $this->parseFWS();
|
||||
if($FwsResult->isInvalid()) {
|
||||
return $FwsResult;
|
||||
}
|
||||
|
||||
$domain .= ((array) $this->lexer->token)['value'];
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_DOT && $this->lexer->isNextToken(EmailLexer::GENERIC)) {
|
||||
$tldMissing = false;
|
||||
}
|
||||
|
||||
$exceptionsResult = $this->checkDomainPartExceptions($prev, $hasComments);
|
||||
if ($exceptionsResult->isInvalid()) {
|
||||
return $exceptionsResult;
|
||||
}
|
||||
$this->lexer->moveNext();
|
||||
|
||||
} while (null !== ((array) $this->lexer->token)['type']);
|
||||
|
||||
$labelCheck = $this->checkLabelLength(true);
|
||||
if ($labelCheck->isInvalid()) {
|
||||
return $labelCheck;
|
||||
}
|
||||
$this->addTLDWarnings($tldMissing);
|
||||
|
||||
$this->domainPart = $domain;
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-param array|Token<int, string> $token
|
||||
*/
|
||||
private function checkNotAllowedChars($token) : Result
|
||||
{
|
||||
$notAllowed = [EmailLexer::S_BACKSLASH => true, EmailLexer::S_SLASH=> true];
|
||||
if (isset($notAllowed[((array) $token)['type']])) {
|
||||
return new InvalidEmail(new CharNotAllowed(), ((array) $token)['value']);
|
||||
}
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Result
|
||||
*/
|
||||
protected function parseDomainLiteral() : Result
|
||||
{
|
||||
try {
|
||||
$this->lexer->find(EmailLexer::S_CLOSEBRACKET);
|
||||
} catch (\RuntimeException $e) {
|
||||
return new InvalidEmail(new ExpectingDomainLiteralClose(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
$domainLiteralParser = new DomainLiteralParser($this->lexer);
|
||||
$result = $domainLiteralParser->parse();
|
||||
$this->warnings = array_merge($this->warnings, $domainLiteralParser->getWarnings());
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function checkDomainPartExceptions(array $prev, bool $hasComments) : Result
|
||||
{
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_OPENBRACKET && $prev['type'] !== EmailLexer::S_AT) {
|
||||
return new InvalidEmail(new ExpectingATEXT('OPENBRACKET not after AT'), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_HYPHEN && $this->lexer->isNextToken(EmailLexer::S_DOT)) {
|
||||
return new InvalidEmail(new DomainHyphened('Hypen found near DOT'), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_BACKSLASH
|
||||
&& $this->lexer->isNextToken(EmailLexer::GENERIC)) {
|
||||
return new InvalidEmail(new ExpectingATEXT('Escaping following "ATOM"'), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
return $this->validateTokens($hasComments);
|
||||
}
|
||||
|
||||
protected function validateTokens(bool $hasComments) : Result
|
||||
{
|
||||
$validDomainTokens = array(
|
||||
EmailLexer::GENERIC => true,
|
||||
EmailLexer::S_HYPHEN => true,
|
||||
EmailLexer::S_DOT => true,
|
||||
);
|
||||
|
||||
if ($hasComments) {
|
||||
$validDomainTokens[EmailLexer::S_OPENPARENTHESIS] = true;
|
||||
$validDomainTokens[EmailLexer::S_CLOSEPARENTHESIS] = true;
|
||||
}
|
||||
|
||||
if (!isset($validDomainTokens[((array) $this->lexer->token)['type']])) {
|
||||
return new InvalidEmail(new ExpectingATEXT('Invalid token in domain: ' . ((array) $this->lexer->token)['value']), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
private function checkLabelLength(bool $isEndOfDomain = false) : Result
|
||||
{
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_DOT || $isEndOfDomain) {
|
||||
if ($this->isLabelTooLong($this->label)) {
|
||||
return new InvalidEmail(new LabelTooLong(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
$this->label = '';
|
||||
}
|
||||
$this->label .= ((array) $this->lexer->token)['value'];
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
|
||||
private function isLabelTooLong(string $label) : bool
|
||||
{
|
||||
if (preg_match('/[^\x00-\x7F]/', $label)) {
|
||||
idn_to_ascii($label, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46, $idnaInfo);
|
||||
return (bool) ($idnaInfo['errors'] & IDNA_ERROR_LABEL_TOO_LONG);
|
||||
}
|
||||
return strlen($label) > self::LABEL_MAX_LENGTH;
|
||||
}
|
||||
|
||||
private function addTLDWarnings(bool $isTLDMissing) : void
|
||||
{
|
||||
if ($isTLDMissing) {
|
||||
$this->warnings[TLD::CODE] = new TLD();
|
||||
}
|
||||
}
|
||||
|
||||
public function domainPart() : string
|
||||
{
|
||||
return $this->domainPart;
|
||||
}
|
||||
}
|
||||
87
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/DoubleQuote.php
vendored
Normal file
87
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/DoubleQuote.php
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Warning\CFWSWithFWS;
|
||||
use Egulias\EmailValidator\Warning\QuotedString;
|
||||
use Egulias\EmailValidator\Result\Reason\ExpectingATEXT;
|
||||
use Egulias\EmailValidator\Result\Reason\UnclosedQuotedString;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
|
||||
class DoubleQuote extends PartParser
|
||||
{
|
||||
public function parse() : Result
|
||||
{
|
||||
|
||||
$validQuotedString = $this->checkDQUOTE();
|
||||
if($validQuotedString->isInvalid()) return $validQuotedString;
|
||||
|
||||
$special = [
|
||||
EmailLexer::S_CR => true,
|
||||
EmailLexer::S_HTAB => true,
|
||||
EmailLexer::S_LF => true
|
||||
];
|
||||
|
||||
$invalid = [
|
||||
EmailLexer::C_NUL => true,
|
||||
EmailLexer::S_HTAB => true,
|
||||
EmailLexer::S_CR => true,
|
||||
EmailLexer::S_LF => true
|
||||
];
|
||||
|
||||
$setSpecialsWarning = true;
|
||||
|
||||
$this->lexer->moveNext();
|
||||
|
||||
while (((array) $this->lexer->token)['type'] !== EmailLexer::S_DQUOTE && null !== ((array) $this->lexer->token)['type']) {
|
||||
if (isset($special[((array) $this->lexer->token)['type']]) && $setSpecialsWarning) {
|
||||
$this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS();
|
||||
$setSpecialsWarning = false;
|
||||
}
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_BACKSLASH && $this->lexer->isNextToken(EmailLexer::S_DQUOTE)) {
|
||||
$this->lexer->moveNext();
|
||||
}
|
||||
|
||||
$this->lexer->moveNext();
|
||||
|
||||
if (!$this->escaped() && isset($invalid[((array) $this->lexer->token)['type']])) {
|
||||
return new InvalidEmail(new ExpectingATEXT("Expecting ATEXT between DQUOTE"), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
}
|
||||
|
||||
$prev = $this->lexer->getPrevious();
|
||||
|
||||
if ($prev['type'] === EmailLexer::S_BACKSLASH) {
|
||||
$validQuotedString = $this->checkDQUOTE();
|
||||
if($validQuotedString->isInvalid()) return $validQuotedString;
|
||||
}
|
||||
|
||||
if (!$this->lexer->isNextToken(EmailLexer::S_AT) && $prev['type'] !== EmailLexer::S_BACKSLASH) {
|
||||
return new InvalidEmail(new ExpectingATEXT("Expecting ATEXT between DQUOTE"), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
protected function checkDQUOTE() : Result
|
||||
{
|
||||
$previous = $this->lexer->getPrevious();
|
||||
|
||||
if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] === EmailLexer::GENERIC) {
|
||||
$description = 'https://tools.ietf.org/html/rfc5322#section-3.2.4 - quoted string should be a unit';
|
||||
return new InvalidEmail(new ExpectingATEXT($description), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->lexer->find(EmailLexer::S_DQUOTE);
|
||||
} catch (\Exception $e) {
|
||||
return new InvalidEmail(new UnclosedQuotedString(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
$this->warnings[QuotedString::CODE] = new QuotedString($previous['value'], ((array) $this->lexer->token)['value']);
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
}
|
||||
86
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/FoldingWhiteSpace.php
vendored
Normal file
86
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/FoldingWhiteSpace.php
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Warning\CFWSNearAt;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Warning\CFWSWithFWS;
|
||||
use Egulias\EmailValidator\Result\Reason\CRNoLF;
|
||||
use Egulias\EmailValidator\Result\Reason\AtextAfterCFWS;
|
||||
use Egulias\EmailValidator\Result\Reason\CRLFAtTheEnd;
|
||||
use Egulias\EmailValidator\Result\Reason\CRLFX2;
|
||||
use Egulias\EmailValidator\Result\Reason\ExpectingCTEXT;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
|
||||
class FoldingWhiteSpace extends PartParser
|
||||
{
|
||||
public const FWS_TYPES = [
|
||||
EmailLexer::S_SP,
|
||||
EmailLexer::S_HTAB,
|
||||
EmailLexer::S_CR,
|
||||
EmailLexer::S_LF,
|
||||
EmailLexer::CRLF
|
||||
];
|
||||
|
||||
public function parse() : Result
|
||||
{
|
||||
if (!$this->isFWS()) {
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
$previous = $this->lexer->getPrevious();
|
||||
|
||||
$resultCRLF = $this->checkCRLFInFWS();
|
||||
if ($resultCRLF->isInvalid()) {
|
||||
return $resultCRLF;
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_CR) {
|
||||
return new InvalidEmail(new CRNoLF(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] !== EmailLexer::S_AT) {
|
||||
return new InvalidEmail(new AtextAfterCFWS(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_LF || ((array) $this->lexer->token)['type'] === EmailLexer::C_NUL) {
|
||||
return new InvalidEmail(new ExpectingCTEXT(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
if ($this->lexer->isNextToken(EmailLexer::S_AT) || $previous['type'] === EmailLexer::S_AT) {
|
||||
$this->warnings[CFWSNearAt::CODE] = new CFWSNearAt();
|
||||
} else {
|
||||
$this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS();
|
||||
}
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
protected function checkCRLFInFWS() : Result
|
||||
{
|
||||
if (((array) $this->lexer->token)['type'] !== EmailLexer::CRLF) {
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) {
|
||||
return new InvalidEmail(new CRLFX2(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
//this has no coverage. Condition is repeated from above one
|
||||
if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) {
|
||||
return new InvalidEmail(new CRLFAtTheEnd(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
protected function isFWS() : bool
|
||||
{
|
||||
if ($this->escaped()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array(((array) $this->lexer->token)['type'], self::FWS_TYPES);
|
||||
}
|
||||
}
|
||||
15
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/IDLeftPart.php
vendored
Normal file
15
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/IDLeftPart.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Result\Reason\CommentsInIDRight;
|
||||
|
||||
class IDLeftPart extends LocalPart
|
||||
{
|
||||
protected function parseComments(): Result
|
||||
{
|
||||
return new InvalidEmail(new CommentsInIDRight(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
}
|
||||
29
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/IDRightPart.php
vendored
Normal file
29
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/IDRightPart.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Result\Reason\ExpectingATEXT;
|
||||
|
||||
class IDRightPart extends DomainPart
|
||||
{
|
||||
protected function validateTokens(bool $hasComments) : Result
|
||||
{
|
||||
$invalidDomainTokens = [
|
||||
EmailLexer::S_DQUOTE => true,
|
||||
EmailLexer::S_SQUOTE => true,
|
||||
EmailLexer::S_BACKTICK => true,
|
||||
EmailLexer::S_SEMICOLON => true,
|
||||
EmailLexer::S_GREATERTHAN => true,
|
||||
EmailLexer::S_LOWERTHAN => true,
|
||||
];
|
||||
|
||||
if (isset($invalidDomainTokens[((array) $this->lexer->token)['type']])) {
|
||||
return new InvalidEmail(new ExpectingATEXT('Invalid token in domain: ' . ((array) $this->lexer->token)['value']), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
return new ValidEmail();
|
||||
}
|
||||
}
|
||||
165
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/LocalPart.php
vendored
Normal file
165
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/LocalPart.php
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Warning\LocalTooLong;
|
||||
use Egulias\EmailValidator\Result\Reason\DotAtEnd;
|
||||
use Egulias\EmailValidator\Result\Reason\DotAtStart;
|
||||
use Egulias\EmailValidator\Result\Reason\ConsecutiveDot;
|
||||
use Egulias\EmailValidator\Result\Reason\ExpectingATEXT;
|
||||
use Egulias\EmailValidator\Parser\CommentStrategy\LocalComment;
|
||||
|
||||
class LocalPart extends PartParser
|
||||
{
|
||||
public const INVALID_TOKENS = [
|
||||
EmailLexer::S_COMMA => EmailLexer::S_COMMA,
|
||||
EmailLexer::S_CLOSEBRACKET => EmailLexer::S_CLOSEBRACKET,
|
||||
EmailLexer::S_OPENBRACKET => EmailLexer::S_OPENBRACKET,
|
||||
EmailLexer::S_GREATERTHAN => EmailLexer::S_GREATERTHAN,
|
||||
EmailLexer::S_LOWERTHAN => EmailLexer::S_LOWERTHAN,
|
||||
EmailLexer::S_COLON => EmailLexer::S_COLON,
|
||||
EmailLexer::S_SEMICOLON => EmailLexer::S_SEMICOLON,
|
||||
EmailLexer::INVALID => EmailLexer::INVALID
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $localPart = '';
|
||||
|
||||
|
||||
public function parse() : Result
|
||||
{
|
||||
$this->lexer->startRecording();
|
||||
|
||||
while (((array) $this->lexer->token)['type'] !== EmailLexer::S_AT && null !== ((array) $this->lexer->token)['type']) {
|
||||
if ($this->hasDotAtStart()) {
|
||||
return new InvalidEmail(new DotAtStart(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_DQUOTE) {
|
||||
$dquoteParsingResult = $this->parseDoubleQuote();
|
||||
|
||||
//Invalid double quote parsing
|
||||
if($dquoteParsingResult->isInvalid()) {
|
||||
return $dquoteParsingResult;
|
||||
}
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_OPENPARENTHESIS ||
|
||||
((array) $this->lexer->token)['type'] === EmailLexer::S_CLOSEPARENTHESIS ) {
|
||||
$commentsResult = $this->parseComments();
|
||||
|
||||
//Invalid comment parsing
|
||||
if($commentsResult->isInvalid()) {
|
||||
return $commentsResult;
|
||||
}
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_DOT && $this->lexer->isNextToken(EmailLexer::S_DOT)) {
|
||||
return new InvalidEmail(new ConsecutiveDot(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_DOT &&
|
||||
$this->lexer->isNextToken(EmailLexer::S_AT)
|
||||
) {
|
||||
return new InvalidEmail(new DotAtEnd(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
$resultEscaping = $this->validateEscaping();
|
||||
if ($resultEscaping->isInvalid()) {
|
||||
return $resultEscaping;
|
||||
}
|
||||
|
||||
$resultToken = $this->validateTokens(false);
|
||||
if ($resultToken->isInvalid()) {
|
||||
return $resultToken;
|
||||
}
|
||||
|
||||
$resultFWS = $this->parseLocalFWS();
|
||||
if($resultFWS->isInvalid()) {
|
||||
return $resultFWS;
|
||||
}
|
||||
|
||||
$this->lexer->moveNext();
|
||||
}
|
||||
|
||||
$this->lexer->stopRecording();
|
||||
$this->localPart = rtrim($this->lexer->getAccumulatedValues(), '@');
|
||||
if (strlen($this->localPart) > LocalTooLong::LOCAL_PART_LENGTH) {
|
||||
$this->warnings[LocalTooLong::CODE] = new LocalTooLong();
|
||||
}
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
protected function validateTokens(bool $hasComments) : Result
|
||||
{
|
||||
if (isset(self::INVALID_TOKENS[((array) $this->lexer->token)['type']])) {
|
||||
return new InvalidEmail(new ExpectingATEXT('Invalid token found'), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
public function localPart() : string
|
||||
{
|
||||
return $this->localPart;
|
||||
}
|
||||
|
||||
private function parseLocalFWS() : Result
|
||||
{
|
||||
$foldingWS = new FoldingWhiteSpace($this->lexer);
|
||||
$resultFWS = $foldingWS->parse();
|
||||
if ($resultFWS->isValid()) {
|
||||
$this->warnings = array_merge($this->warnings, $foldingWS->getWarnings());
|
||||
}
|
||||
return $resultFWS;
|
||||
}
|
||||
|
||||
private function hasDotAtStart() : bool
|
||||
{
|
||||
return ((array) $this->lexer->token)['type'] === EmailLexer::S_DOT && null === $this->lexer->getPrevious()['type'];
|
||||
}
|
||||
|
||||
private function parseDoubleQuote() : Result
|
||||
{
|
||||
$dquoteParser = new DoubleQuote($this->lexer);
|
||||
$parseAgain = $dquoteParser->parse();
|
||||
$this->warnings = array_merge($this->warnings, $dquoteParser->getWarnings());
|
||||
|
||||
return $parseAgain;
|
||||
}
|
||||
|
||||
protected function parseComments(): Result
|
||||
{
|
||||
$commentParser = new Comment($this->lexer, new LocalComment());
|
||||
$result = $commentParser->parse();
|
||||
$this->warnings = array_merge($this->warnings, $commentParser->getWarnings());
|
||||
if($result->isInvalid()) {
|
||||
return $result;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function validateEscaping() : Result
|
||||
{
|
||||
//Backslash found
|
||||
if (((array) $this->lexer->token)['type'] !== EmailLexer::S_BACKSLASH) {
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
if ($this->lexer->isNextToken(EmailLexer::GENERIC)) {
|
||||
return new InvalidEmail(new ExpectingATEXT('Found ATOM after escaping'), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB, EmailLexer::C_DEL))) {
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
}
|
||||
63
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/PartParser.php
vendored
Normal file
63
config/www/user/plugins/email/vendor/egulias/email-validator/src/Parser/PartParser.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Result\Reason\ConsecutiveDot;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
|
||||
abstract class PartParser
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $warnings = [];
|
||||
|
||||
/**
|
||||
* @var EmailLexer
|
||||
*/
|
||||
protected $lexer;
|
||||
|
||||
public function __construct(EmailLexer $lexer)
|
||||
{
|
||||
$this->lexer = $lexer;
|
||||
}
|
||||
|
||||
abstract public function parse() : Result;
|
||||
|
||||
/**
|
||||
* @return \Egulias\EmailValidator\Warning\Warning[]
|
||||
*/
|
||||
public function getWarnings()
|
||||
{
|
||||
return $this->warnings;
|
||||
}
|
||||
|
||||
protected function parseFWS() : Result
|
||||
{
|
||||
$foldingWS = new FoldingWhiteSpace($this->lexer);
|
||||
$resultFWS = $foldingWS->parse();
|
||||
$this->warnings = array_merge($this->warnings, $foldingWS->getWarnings());
|
||||
return $resultFWS;
|
||||
}
|
||||
|
||||
protected function checkConsecutiveDots() : Result
|
||||
{
|
||||
if (((array) $this->lexer->token)['type'] === EmailLexer::S_DOT && $this->lexer->isNextToken(EmailLexer::S_DOT)) {
|
||||
return new InvalidEmail(new ConsecutiveDot(), ((array) $this->lexer->token)['value']);
|
||||
}
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
protected function escaped() : bool
|
||||
{
|
||||
$previous = $this->lexer->getPrevious();
|
||||
|
||||
return $previous && $previous['type'] === EmailLexer::S_BACKSLASH
|
||||
&&
|
||||
((array) $this->lexer->token)['type'] !== EmailLexer::GENERIC;
|
||||
}
|
||||
}
|
||||
46
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/InvalidEmail.php
vendored
Normal file
46
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/InvalidEmail.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result;
|
||||
|
||||
use Egulias\EmailValidator\Result\Reason\Reason;
|
||||
|
||||
class InvalidEmail implements Result
|
||||
{
|
||||
private $token;
|
||||
/**
|
||||
* @var Reason
|
||||
*/
|
||||
protected $reason;
|
||||
|
||||
public function __construct(Reason $reason, string $token)
|
||||
{
|
||||
$this->token = $token;
|
||||
$this->reason = $reason;
|
||||
}
|
||||
|
||||
public function isValid(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isInvalid(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function description(): string
|
||||
{
|
||||
return $this->reason->description() . " in char " . $this->token;
|
||||
}
|
||||
|
||||
public function code(): int
|
||||
{
|
||||
return $this->reason->code();
|
||||
}
|
||||
|
||||
public function reason() : Reason
|
||||
{
|
||||
return $this->reason;
|
||||
}
|
||||
|
||||
}
|
||||
56
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/MultipleErrors.php
vendored
Normal file
56
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/MultipleErrors.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result;
|
||||
|
||||
use Egulias\EmailValidator\Result\Reason\EmptyReason;
|
||||
use Egulias\EmailValidator\Result\Reason\Reason;
|
||||
|
||||
/**
|
||||
* @psalm-suppress PropertyNotSetInConstructor
|
||||
*/
|
||||
class MultipleErrors extends InvalidEmail
|
||||
{
|
||||
/**
|
||||
* @var Reason[]
|
||||
*/
|
||||
private $reasons = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function addReason(Reason $reason) : void
|
||||
{
|
||||
$this->reasons[$reason->code()] = $reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Reason[]
|
||||
*/
|
||||
public function getReasons() : array
|
||||
{
|
||||
return $this->reasons;
|
||||
}
|
||||
|
||||
public function reason() : Reason
|
||||
{
|
||||
return 0 !== count($this->reasons)
|
||||
? current($this->reasons)
|
||||
: new EmptyReason();
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
$description = '';
|
||||
foreach($this->reasons as $reason) {
|
||||
$description .= $reason->description() . PHP_EOL;
|
||||
}
|
||||
|
||||
return $description;
|
||||
}
|
||||
|
||||
public function code() : int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class AtextAfterCFWS implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 133;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'ATEXT found after CFWS';
|
||||
}
|
||||
}
|
||||
19
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/CRLFAtTheEnd.php
vendored
Normal file
19
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/CRLFAtTheEnd.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class CRLFAtTheEnd implements Reason
|
||||
{
|
||||
public const CODE = 149;
|
||||
public const REASON = "CRLF at the end";
|
||||
|
||||
public function code() : int
|
||||
{
|
||||
return 149;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'CRLF at the end';
|
||||
}
|
||||
}
|
||||
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/CRLFX2.php
vendored
Normal file
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/CRLFX2.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class CRLFX2 implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 148;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'CR LF tokens found twice';
|
||||
}
|
||||
}
|
||||
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/CRNoLF.php
vendored
Normal file
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/CRNoLF.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class CRNoLF implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 150;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'Missing LF after CR';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class CharNotAllowed implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return "Character not allowed";
|
||||
}
|
||||
}
|
||||
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/CommaInDomain.php
vendored
Normal file
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/CommaInDomain.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class CommaInDomain implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 200;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return "Comma ',' is not allowed in domain part";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class CommentsInIDRight implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 400;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'Comments are not allowed in IDRight for message-id';
|
||||
}
|
||||
}
|
||||
17
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/ConsecutiveAt.php
vendored
Normal file
17
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/ConsecutiveAt.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class ConsecutiveAt implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 128;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return '@ found after another @';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class ConsecutiveDot implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 132;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'Concecutive DOT found';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
abstract class DetailedReason implements Reason
|
||||
{
|
||||
protected $detailedDescription;
|
||||
|
||||
public function __construct(string $details)
|
||||
{
|
||||
$this->detailedDescription = $details;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class DomainAcceptsNoMail implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 154;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'Domain accepts no mail (Null MX, RFC7505)';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class DomainHyphened extends DetailedReason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 144;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'S_HYPHEN found in domain';
|
||||
}
|
||||
}
|
||||
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/DomainTooLong.php
vendored
Normal file
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/DomainTooLong.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class DomainTooLong implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 244;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'Domain is longer than 253 characters';
|
||||
}
|
||||
}
|
||||
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/DotAtEnd.php
vendored
Normal file
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/DotAtEnd.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class DotAtEnd implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 142;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'Dot at the end';
|
||||
}
|
||||
}
|
||||
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/DotAtStart.php
vendored
Normal file
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/DotAtStart.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class DotAtStart implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 141;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return "Starts with a DOT";
|
||||
}
|
||||
}
|
||||
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/EmptyReason.php
vendored
Normal file
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/EmptyReason.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class EmptyReason implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'Empty reason';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class ExceptionFound implements Reason
|
||||
{
|
||||
/**
|
||||
* @var \Exception
|
||||
*/
|
||||
private $exception;
|
||||
|
||||
public function __construct(\Exception $exception)
|
||||
{
|
||||
$this->exception = $exception;
|
||||
|
||||
}
|
||||
public function code() : int
|
||||
{
|
||||
return 999;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return $this->exception->getMessage();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class ExpectingATEXT extends DetailedReason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 137;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return "Expecting ATEXT (Printable US-ASCII). Extended: " . $this->detailedDescription;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class ExpectingCTEXT implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 139;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'Expecting CTEXT';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class ExpectingDTEXT implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 129;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'Expecting DTEXT';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class ExpectingDomainLiteralClose implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 137;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return "Closing bracket ']' for domain literal not found";
|
||||
}
|
||||
}
|
||||
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/LabelTooLong.php
vendored
Normal file
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/LabelTooLong.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class LabelTooLong implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 245;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'Domain "label" is longer than 63 characters';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class LocalOrReservedDomain implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 153;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'Local, mDNS or reserved domain (RFC2606, RFC6762)';
|
||||
}
|
||||
}
|
||||
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/NoDNSRecord.php
vendored
Normal file
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/NoDNSRecord.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class NoDNSRecord implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'No MX or A DSN record was found for this email';
|
||||
}
|
||||
}
|
||||
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/NoDomainPart.php
vendored
Normal file
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/NoDomainPart.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class NoDomainPart implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 131;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'No domain part found';
|
||||
}
|
||||
}
|
||||
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/NoLocalPart.php
vendored
Normal file
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/NoLocalPart.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class NoLocalPart implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 130;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return "No local part";
|
||||
}
|
||||
}
|
||||
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/RFCWarnings.php
vendored
Normal file
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/RFCWarnings.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class RFCWarnings implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 997;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'Warnings found after validating';
|
||||
}
|
||||
}
|
||||
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/Reason.php
vendored
Normal file
16
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/Reason.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
interface Reason
|
||||
{
|
||||
/**
|
||||
* Code for user land to act upon;
|
||||
*/
|
||||
public function code() : int;
|
||||
|
||||
/**
|
||||
* Short description of the result, human readable.
|
||||
*/
|
||||
public function description() : string;
|
||||
}
|
||||
17
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/SpoofEmail.php
vendored
Normal file
17
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Reason/SpoofEmail.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class SpoofEmail implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 298;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'The email contains mixed UTF8 chars that makes it suspicious';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class UnOpenedComment implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 152;
|
||||
}
|
||||
|
||||
public function description(): string
|
||||
{
|
||||
return 'Missing opening comment parentheses - https://tools.ietf.org/html/rfc5322#section-3.2.2';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
/**
|
||||
* Used on SERVFAIL, TIMEOUT or other runtime and network errors
|
||||
*/
|
||||
class UnableToGetDNSRecord extends NoDNSRecord
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'Unable to get DNS records for the host';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class UnclosedComment implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 146;
|
||||
}
|
||||
|
||||
public function description(): string
|
||||
{
|
||||
return 'No closing comment token found';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class UnclosedQuotedString implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 145;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return "Unclosed quoted string";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class UnusualElements implements Reason
|
||||
{
|
||||
/**
|
||||
* @var string $element
|
||||
*/
|
||||
private $element = '';
|
||||
|
||||
public function __construct(string $element)
|
||||
{
|
||||
$this->element = $element;
|
||||
}
|
||||
|
||||
public function code() : int
|
||||
{
|
||||
return 201;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'Unusual element found, wourld render invalid in majority of cases. Element found: ' . $this->element;
|
||||
}
|
||||
}
|
||||
27
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Result.php
vendored
Normal file
27
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/Result.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result;
|
||||
|
||||
interface Result
|
||||
{
|
||||
/**
|
||||
* Is validation result valid?
|
||||
*/
|
||||
public function isValid() : bool;
|
||||
|
||||
/**
|
||||
* Is validation result invalid?
|
||||
* Usually the inverse of isValid()
|
||||
*/
|
||||
public function isInvalid() : bool;
|
||||
|
||||
/**
|
||||
* Short description of the result, human readable.
|
||||
*/
|
||||
public function description() : string;
|
||||
|
||||
/**
|
||||
* Code for user land to act upon.
|
||||
*/
|
||||
public function code() : int;
|
||||
}
|
||||
13
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/SpoofEmail.php
vendored
Normal file
13
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/SpoofEmail.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
namespace Egulias\EmailValidator\Result;
|
||||
|
||||
use Egulias\EmailValidator\Result\Reason\SpoofEmail as ReasonSpoofEmail;
|
||||
|
||||
class SpoofEmail extends InvalidEmail
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->reason = new ReasonSpoofEmail();
|
||||
parent::__construct($this->reason, '');
|
||||
}
|
||||
}
|
||||
27
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/ValidEmail.php
vendored
Normal file
27
config/www/user/plugins/email/vendor/egulias/email-validator/src/Result/ValidEmail.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result;
|
||||
|
||||
class ValidEmail implements Result
|
||||
{
|
||||
public function isValid(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isInvalid(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function description(): string
|
||||
{
|
||||
return "Valid email";
|
||||
}
|
||||
|
||||
public function code(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
191
config/www/user/plugins/email/vendor/egulias/email-validator/src/Validation/DNSCheckValidation.php
vendored
Normal file
191
config/www/user/plugins/email/vendor/egulias/email-validator/src/Validation/DNSCheckValidation.php
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Validation;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Result\Reason\DomainAcceptsNoMail;
|
||||
use Egulias\EmailValidator\Result\Reason\LocalOrReservedDomain;
|
||||
use Egulias\EmailValidator\Result\Reason\NoDNSRecord as ReasonNoDNSRecord;
|
||||
use Egulias\EmailValidator\Result\Reason\UnableToGetDNSRecord;
|
||||
use Egulias\EmailValidator\Warning\NoDNSMXRecord;
|
||||
|
||||
class DNSCheckValidation implements EmailValidation
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected const DNS_RECORD_TYPES_TO_CHECK = DNS_MX + DNS_A + DNS_AAAA;
|
||||
|
||||
/**
|
||||
* Reserved Top Level DNS Names (https://tools.ietf.org/html/rfc2606#section-2),
|
||||
* mDNS and private DNS Namespaces (https://tools.ietf.org/html/rfc6762#appendix-G)
|
||||
*/
|
||||
public const RESERVED_DNS_TOP_LEVEL_NAMES = [
|
||||
// Reserved Top Level DNS Names
|
||||
'test',
|
||||
'example',
|
||||
'invalid',
|
||||
'localhost',
|
||||
|
||||
// mDNS
|
||||
'local',
|
||||
|
||||
// Private DNS Namespaces
|
||||
'intranet',
|
||||
'internal',
|
||||
'private',
|
||||
'corp',
|
||||
'home',
|
||||
'lan',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $warnings = [];
|
||||
|
||||
/**
|
||||
* @var InvalidEmail|null
|
||||
*/
|
||||
private $error;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $mxRecords = [];
|
||||
|
||||
/**
|
||||
* @var DNSGetRecordWrapper
|
||||
*/
|
||||
private $dnsGetRecord;
|
||||
|
||||
public function __construct(?DNSGetRecordWrapper $dnsGetRecord = null)
|
||||
{
|
||||
if (!function_exists('idn_to_ascii')) {
|
||||
throw new \LogicException(sprintf('The %s class requires the Intl extension.', __CLASS__));
|
||||
}
|
||||
|
||||
if ($dnsGetRecord == null) {
|
||||
$dnsGetRecord = new DNSGetRecordWrapper();
|
||||
}
|
||||
|
||||
$this->dnsGetRecord = $dnsGetRecord;
|
||||
}
|
||||
|
||||
public function isValid(string $email, EmailLexer $emailLexer) : bool
|
||||
{
|
||||
// use the input to check DNS if we cannot extract something similar to a domain
|
||||
$host = $email;
|
||||
|
||||
// Arguable pattern to extract the domain. Not aiming to validate the domain nor the email
|
||||
if (false !== $lastAtPos = strrpos($email, '@')) {
|
||||
$host = substr($email, $lastAtPos + 1);
|
||||
}
|
||||
|
||||
// Get the domain parts
|
||||
$hostParts = explode('.', $host);
|
||||
|
||||
$isLocalDomain = count($hostParts) <= 1;
|
||||
$isReservedTopLevel = in_array($hostParts[(count($hostParts) - 1)], self::RESERVED_DNS_TOP_LEVEL_NAMES, true);
|
||||
|
||||
// Exclude reserved top level DNS names
|
||||
if ($isLocalDomain || $isReservedTopLevel) {
|
||||
$this->error = new InvalidEmail(new LocalOrReservedDomain(), $host);
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->checkDns($host);
|
||||
}
|
||||
|
||||
public function getError() : ?InvalidEmail
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
public function getWarnings() : array
|
||||
{
|
||||
return $this->warnings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $host
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkDns($host)
|
||||
{
|
||||
$variant = INTL_IDNA_VARIANT_UTS46;
|
||||
|
||||
$host = rtrim(idn_to_ascii($host, IDNA_DEFAULT, $variant), '.') . '.';
|
||||
|
||||
return $this->validateDnsRecords($host);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate the DNS records for given host.
|
||||
*
|
||||
* @param string $host A set of DNS records in the format returned by dns_get_record.
|
||||
*
|
||||
* @return bool True on success.
|
||||
*/
|
||||
private function validateDnsRecords($host) : bool
|
||||
{
|
||||
$dnsRecordsResult = $this->dnsGetRecord->getRecords($host, static::DNS_RECORD_TYPES_TO_CHECK);
|
||||
|
||||
if ($dnsRecordsResult->withError()) {
|
||||
$this->error = new InvalidEmail(new UnableToGetDNSRecord(), '');
|
||||
return false;
|
||||
}
|
||||
|
||||
$dnsRecords = $dnsRecordsResult->getRecords();
|
||||
|
||||
// No MX, A or AAAA DNS records
|
||||
if ($dnsRecords === []) {
|
||||
$this->error = new InvalidEmail(new ReasonNoDNSRecord(), '');
|
||||
return false;
|
||||
}
|
||||
|
||||
// For each DNS record
|
||||
foreach ($dnsRecords as $dnsRecord) {
|
||||
if (!$this->validateMXRecord($dnsRecord)) {
|
||||
// No MX records (fallback to A or AAAA records)
|
||||
if (empty($this->mxRecords)) {
|
||||
$this->warnings[NoDNSMXRecord::CODE] = new NoDNSMXRecord();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an MX record
|
||||
*
|
||||
* @param array $dnsRecord Given DNS record.
|
||||
*
|
||||
* @return bool True if valid.
|
||||
*/
|
||||
private function validateMxRecord($dnsRecord) : bool
|
||||
{
|
||||
if (!isset($dnsRecord['type'])) {
|
||||
$this->error = new InvalidEmail(new ReasonNoDNSRecord(), '');
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($dnsRecord['type'] !== 'MX') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// "Null MX" record indicates the domain accepts no mail (https://tools.ietf.org/html/rfc7505)
|
||||
if (empty($dnsRecord['target']) || $dnsRecord['target'] === '.') {
|
||||
$this->error = new InvalidEmail(new DomainAcceptsNoMail(), "");
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->mxRecords[] = $dnsRecord;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
namespace Egulias\EmailValidator\Validation;
|
||||
|
||||
class DNSGetRecordWrapper
|
||||
{
|
||||
/**
|
||||
* @param string $host
|
||||
* @param int $type
|
||||
*/
|
||||
public function getRecords(string $host, int $type) : DNSRecords
|
||||
{
|
||||
// A workaround to fix https://bugs.php.net/bug.php?id=73149
|
||||
/** @psalm-suppress InvalidArgument */
|
||||
set_error_handler(
|
||||
static function (int $errorLevel, string $errorMessage): ?bool {
|
||||
throw new \RuntimeException("Unable to get DNS record for the host: $errorMessage");
|
||||
}
|
||||
);
|
||||
try {
|
||||
// Get all MX, A and AAAA DNS records for host
|
||||
return new DNSRecords(dns_get_record($host, $type));
|
||||
} catch (\RuntimeException $exception) {
|
||||
return new DNSRecords([], true);
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
}
|
||||
}
|
||||
}
|
||||
35
config/www/user/plugins/email/vendor/egulias/email-validator/src/Validation/DNSRecords.php
vendored
Normal file
35
config/www/user/plugins/email/vendor/egulias/email-validator/src/Validation/DNSRecords.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Validation;
|
||||
|
||||
class DNSRecords
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array $records
|
||||
*/
|
||||
private $records = [];
|
||||
|
||||
/**
|
||||
* @var bool $error
|
||||
*/
|
||||
private $error = false;
|
||||
|
||||
public function __construct(array $records, bool $error = false)
|
||||
{
|
||||
$this->records = $records;
|
||||
$this->error = $error;
|
||||
}
|
||||
|
||||
public function getRecords() : array
|
||||
{
|
||||
return $this->records;
|
||||
}
|
||||
|
||||
public function withError() : bool
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
34
config/www/user/plugins/email/vendor/egulias/email-validator/src/Validation/EmailValidation.php
vendored
Normal file
34
config/www/user/plugins/email/vendor/egulias/email-validator/src/Validation/EmailValidation.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Validation;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Warning\Warning;
|
||||
|
||||
interface EmailValidation
|
||||
{
|
||||
/**
|
||||
* Returns true if the given email is valid.
|
||||
*
|
||||
* @param string $email The email you want to validate.
|
||||
* @param EmailLexer $emailLexer The email lexer.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid(string $email, EmailLexer $emailLexer) : bool;
|
||||
|
||||
/**
|
||||
* Returns the validation error.
|
||||
*
|
||||
* @return InvalidEmail|null
|
||||
*/
|
||||
public function getError() : ?InvalidEmail;
|
||||
|
||||
/**
|
||||
* Returns the validation warnings.
|
||||
*
|
||||
* @return Warning[]
|
||||
*/
|
||||
public function getWarnings() : array;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Validation\Exception;
|
||||
|
||||
use Exception;
|
||||
|
||||
class EmptyValidationList extends \InvalidArgumentException
|
||||
{
|
||||
/**
|
||||
* @param int $code
|
||||
*/
|
||||
public function __construct($code = 0, ?Exception $previous = null)
|
||||
{
|
||||
parent::__construct("Empty validation list is not allowed", $code, $previous);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Validation\Extra;
|
||||
|
||||
use \Spoofchecker;
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\SpoofEmail;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Validation\EmailValidation;
|
||||
|
||||
class SpoofCheckValidation implements EmailValidation
|
||||
{
|
||||
/**
|
||||
* @var InvalidEmail|null
|
||||
*/
|
||||
private $error;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('intl')) {
|
||||
throw new \LogicException(sprintf('The %s class requires the Intl extension.', __CLASS__));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress InvalidArgument
|
||||
*/
|
||||
public function isValid(string $email, EmailLexer $emailLexer) : bool
|
||||
{
|
||||
$checker = new Spoofchecker();
|
||||
$checker->setChecks(Spoofchecker::SINGLE_SCRIPT);
|
||||
|
||||
if ($checker->isSuspicious($email)) {
|
||||
$this->error = new SpoofEmail();
|
||||
}
|
||||
|
||||
return $this->error === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InvalidEmail
|
||||
*/
|
||||
public function getError() : ?InvalidEmail
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
public function getWarnings() : array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Validation;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\MessageIDParser;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Result\Reason\ExceptionFound;
|
||||
|
||||
class MessageIDValidation implements EmailValidation
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $warnings = [];
|
||||
|
||||
/**
|
||||
* @var ?InvalidEmail
|
||||
*/
|
||||
private $error;
|
||||
|
||||
public function isValid(string $email, EmailLexer $emailLexer): bool
|
||||
{
|
||||
$parser = new MessageIDParser($emailLexer);
|
||||
try {
|
||||
$result = $parser->parse($email);
|
||||
$this->warnings = $parser->getWarnings();
|
||||
if ($result->isInvalid()) {
|
||||
/** @psalm-suppress PropertyTypeCoercion */
|
||||
$this->error = $result;
|
||||
return false;
|
||||
}
|
||||
} catch (\Exception $invalid) {
|
||||
$this->error = new InvalidEmail(new ExceptionFound($invalid), '');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getWarnings(): array
|
||||
{
|
||||
return $this->warnings;
|
||||
}
|
||||
|
||||
public function getError(): ?InvalidEmail
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Validation;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Validation\Exception\EmptyValidationList;
|
||||
use Egulias\EmailValidator\Result\MultipleErrors;
|
||||
|
||||
class MultipleValidationWithAnd implements EmailValidation
|
||||
{
|
||||
/**
|
||||
* If one of validations fails, the remaining validations will be skipped.
|
||||
* This means MultipleErrors will only contain a single error, the first found.
|
||||
*/
|
||||
public const STOP_ON_ERROR = 0;
|
||||
|
||||
/**
|
||||
* All of validations will be invoked even if one of them got failure.
|
||||
* So MultipleErrors will contain all causes.
|
||||
*/
|
||||
public const ALLOW_ALL_ERRORS = 1;
|
||||
|
||||
/**
|
||||
* @var EmailValidation[]
|
||||
*/
|
||||
private $validations = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $warnings = [];
|
||||
|
||||
/**
|
||||
* @var MultipleErrors|null
|
||||
*/
|
||||
private $error;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $mode;
|
||||
|
||||
/**
|
||||
* @param EmailValidation[] $validations The validations.
|
||||
* @param int $mode The validation mode (one of the constants).
|
||||
*/
|
||||
public function __construct(array $validations, $mode = self::ALLOW_ALL_ERRORS)
|
||||
{
|
||||
if (count($validations) == 0) {
|
||||
throw new EmptyValidationList();
|
||||
}
|
||||
|
||||
$this->validations = $validations;
|
||||
$this->mode = $mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isValid(string $email, EmailLexer $emailLexer) : bool
|
||||
{
|
||||
$result = true;
|
||||
foreach ($this->validations as $validation) {
|
||||
$emailLexer->reset();
|
||||
$validationResult = $validation->isValid($email, $emailLexer);
|
||||
$result = $result && $validationResult;
|
||||
$this->warnings = array_merge($this->warnings, $validation->getWarnings());
|
||||
if (!$validationResult) {
|
||||
$this->processError($validation);
|
||||
}
|
||||
|
||||
if ($this->shouldStop($result)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function initErrorStorage() : void
|
||||
{
|
||||
if (null === $this->error) {
|
||||
$this->error = new MultipleErrors();
|
||||
}
|
||||
}
|
||||
|
||||
private function processError(EmailValidation $validation) : void
|
||||
{
|
||||
if (null !== $validation->getError()) {
|
||||
$this->initErrorStorage();
|
||||
/** @psalm-suppress PossiblyNullReference */
|
||||
$this->error->addReason($validation->getError()->reason());
|
||||
}
|
||||
}
|
||||
|
||||
private function shouldStop(bool $result) : bool
|
||||
{
|
||||
return !$result && $this->mode === self::STOP_ON_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the validation errors.
|
||||
*/
|
||||
public function getError() : ?InvalidEmail
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getWarnings() : array
|
||||
{
|
||||
return $this->warnings;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Validation;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Result\Reason\RFCWarnings;
|
||||
|
||||
class NoRFCWarningsValidation extends RFCValidation
|
||||
{
|
||||
/**
|
||||
* @var InvalidEmail|null
|
||||
*/
|
||||
private $error;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isValid(string $email, EmailLexer $emailLexer) : bool
|
||||
{
|
||||
if (!parent::isValid($email, $emailLexer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($this->getWarnings())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->error = new InvalidEmail(new RFCWarnings(), '');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getError() : ?InvalidEmail
|
||||
{
|
||||
return $this->error ?: parent::getError();
|
||||
}
|
||||
}
|
||||
55
config/www/user/plugins/email/vendor/egulias/email-validator/src/Validation/RFCValidation.php
vendored
Normal file
55
config/www/user/plugins/email/vendor/egulias/email-validator/src/Validation/RFCValidation.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Validation;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\EmailParser;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Result\Reason\ExceptionFound;
|
||||
|
||||
class RFCValidation implements EmailValidation
|
||||
{
|
||||
/**
|
||||
* @var EmailParser|null
|
||||
*/
|
||||
private $parser;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $warnings = [];
|
||||
|
||||
/**
|
||||
* @var ?InvalidEmail
|
||||
*/
|
||||
private $error;
|
||||
|
||||
public function isValid(string $email, EmailLexer $emailLexer) : bool
|
||||
{
|
||||
$this->parser = new EmailParser($emailLexer);
|
||||
try {
|
||||
$result = $this->parser->parse($email);
|
||||
$this->warnings = $this->parser->getWarnings();
|
||||
if ($result->isInvalid()) {
|
||||
/** @psalm-suppress PropertyTypeCoercion */
|
||||
$this->error = $result;
|
||||
return false;
|
||||
}
|
||||
} catch (\Exception $invalid) {
|
||||
$this->error = new InvalidEmail(new ExceptionFound($invalid), '');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getError() : ?InvalidEmail
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
public function getWarnings() : array
|
||||
{
|
||||
return $this->warnings;
|
||||
}
|
||||
}
|
||||
14
config/www/user/plugins/email/vendor/egulias/email-validator/src/Warning/AddressLiteral.php
vendored
Normal file
14
config/www/user/plugins/email/vendor/egulias/email-validator/src/Warning/AddressLiteral.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Warning;
|
||||
|
||||
class AddressLiteral extends Warning
|
||||
{
|
||||
public const CODE = 12;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->message = 'Address literal in domain part';
|
||||
$this->rfcNumber = 5321;
|
||||
}
|
||||
}
|
||||
13
config/www/user/plugins/email/vendor/egulias/email-validator/src/Warning/CFWSNearAt.php
vendored
Normal file
13
config/www/user/plugins/email/vendor/egulias/email-validator/src/Warning/CFWSNearAt.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Warning;
|
||||
|
||||
class CFWSNearAt extends Warning
|
||||
{
|
||||
public const CODE = 49;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->message = "Deprecated folding white space near @";
|
||||
}
|
||||
}
|
||||
13
config/www/user/plugins/email/vendor/egulias/email-validator/src/Warning/CFWSWithFWS.php
vendored
Normal file
13
config/www/user/plugins/email/vendor/egulias/email-validator/src/Warning/CFWSWithFWS.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Warning;
|
||||
|
||||
class CFWSWithFWS extends Warning
|
||||
{
|
||||
public const CODE = 18;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->message = 'Folding whites space followed by folding white space';
|
||||
}
|
||||
}
|
||||
13
config/www/user/plugins/email/vendor/egulias/email-validator/src/Warning/Comment.php
vendored
Normal file
13
config/www/user/plugins/email/vendor/egulias/email-validator/src/Warning/Comment.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Warning;
|
||||
|
||||
class Comment extends Warning
|
||||
{
|
||||
public const CODE = 17;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->message = "Comments found in this email";
|
||||
}
|
||||
}
|
||||
13
config/www/user/plugins/email/vendor/egulias/email-validator/src/Warning/DeprecatedComment.php
vendored
Normal file
13
config/www/user/plugins/email/vendor/egulias/email-validator/src/Warning/DeprecatedComment.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Warning;
|
||||
|
||||
class DeprecatedComment extends Warning
|
||||
{
|
||||
public const CODE = 37;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->message = 'Deprecated comments';
|
||||
}
|
||||
}
|
||||
14
config/www/user/plugins/email/vendor/egulias/email-validator/src/Warning/DomainLiteral.php
vendored
Normal file
14
config/www/user/plugins/email/vendor/egulias/email-validator/src/Warning/DomainLiteral.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Warning;
|
||||
|
||||
class DomainLiteral extends Warning
|
||||
{
|
||||
public const CODE = 70;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->message = 'Domain Literal';
|
||||
$this->rfcNumber = 5322;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user