N°4307 Replace SwiftMailer with Laminas-mail

This commit is contained in:
Stephen Abello
2022-04-22 10:58:28 +02:00
parent c47f224566
commit 178ba60973
518 changed files with 51346 additions and 23096 deletions

View File

@@ -11,11 +11,12 @@
"ext-mysqli": "*",
"ext-soap": "*",
"combodo/tcpdf": "6.3.5",
"laminas/laminas-mail": "^2.12",
"laminas/laminas-servicemanager": "^3.5",
"nikic/php-parser": "^4.12.0",
"pear/archive_tar": "1.4.14",
"pelago/emogrifier": "3.1.0",
"scssphp/scssphp": "1.0.6",
"swiftmailer/swiftmailer": "5.4.12",
"symfony/console": "~3.4.47",
"symfony/dotenv": "~3.4.47",
"symfony/framework-bundle": "~3.4.47",

632
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "4c5cdd1e0feb4abaab8f86959ffc7a64",
"content-hash": "932a981993f694ebe4e382219fb40008",
"packages": [
{
"name": "combodo/tcpdf",
@@ -66,6 +66,530 @@
"homepage": "https://github.com/combodo-itop-libs/TCPDF",
"time": "2020-09-28T12:19:09+00:00"
},
{
"name": "container-interop/container-interop",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/container-interop/container-interop.git",
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
"shasum": ""
},
"require": {
"psr/container": "^1.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Interop\\Container\\": "src/Interop/Container/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
"homepage": "https://github.com/container-interop/container-interop",
"support": {
"issues": "https://github.com/container-interop/container-interop/issues",
"source": "https://github.com/container-interop/container-interop/tree/master"
},
"abandoned": "psr/container",
"time": "2017-02-14T19:40:03+00:00"
},
{
"name": "laminas/laminas-loader",
"version": "2.6.1",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-loader.git",
"reference": "5d01c2c237ae9e68bec262f339947e2ea18979bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-loader/zipball/5d01c2c237ae9e68bec262f339947e2ea18979bc",
"reference": "5d01c2c237ae9e68bec262f339947e2ea18979bc",
"shasum": ""
},
"require": {
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^5.6 || ^7.0"
},
"replace": {
"zendframework/zend-loader": "self.version"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.6.x-dev",
"dev-develop": "2.7.x-dev"
}
},
"autoload": {
"psr-4": {
"Laminas\\Loader\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Autoloading and plugin loading strategies",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"loader"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-loader/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-loader/issues",
"rss": "https://github.com/laminas/laminas-loader/releases.atom",
"source": "https://github.com/laminas/laminas-loader"
},
"time": "2019-12-31T17:18:27+00:00"
},
{
"name": "laminas/laminas-mail",
"version": "2.12.5",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-mail.git",
"reference": "ed5b36a0deef4ffafe6138c2ae9cafcffafab856"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-mail/zipball/ed5b36a0deef4ffafe6138c2ae9cafcffafab856",
"reference": "ed5b36a0deef4ffafe6138c2ae9cafcffafab856",
"shasum": ""
},
"require": {
"ext-iconv": "*",
"laminas/laminas-loader": "^2.5",
"laminas/laminas-mime": "^2.5",
"laminas/laminas-stdlib": "^2.7 || ^3.0",
"laminas/laminas-validator": "^2.10.2",
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^7.1",
"true/punycode": "^2.1"
},
"replace": {
"zendframework/zend-mail": "^2.10.0"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"laminas/laminas-config": "^2.6",
"laminas/laminas-crypt": "^2.6 || ^3.0",
"laminas/laminas-servicemanager": "^3.2.1",
"phpunit/phpunit": "^7.5.20"
},
"suggest": {
"laminas/laminas-crypt": "Crammd5 support in SMTP Auth",
"laminas/laminas-servicemanager": "^2.7.10 || ^3.3.1 when using SMTP to deliver messages"
},
"type": "library",
"extra": {
"laminas": {
"component": "Laminas\\Mail",
"config-provider": "Laminas\\Mail\\ConfigProvider"
}
},
"autoload": {
"psr-4": {
"Laminas\\Mail\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Provides generalized functionality to compose and send both text and MIME-compliant multipart e-mail messages",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"mail"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-mail/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-mail/issues",
"rss": "https://github.com/laminas/laminas-mail/releases.atom",
"source": "https://github.com/laminas/laminas-mail"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2020-12-31T11:41:57+00:00"
},
{
"name": "laminas/laminas-mime",
"version": "2.7.4",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-mime.git",
"reference": "e45a7d856bf7b4a7b5bd00d6371f9961dc233add"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-mime/zipball/e45a7d856bf7b4a7b5bd00d6371f9961dc233add",
"reference": "e45a7d856bf7b4a7b5bd00d6371f9961dc233add",
"shasum": ""
},
"require": {
"laminas/laminas-stdlib": "^2.7 || ^3.0",
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^5.6 || ^7.0"
},
"replace": {
"zendframework/zend-mime": "^2.7.2"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"laminas/laminas-mail": "^2.6",
"phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.20"
},
"suggest": {
"laminas/laminas-mail": "Laminas\\Mail component"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.7.x-dev",
"dev-develop": "2.8.x-dev"
}
},
"autoload": {
"psr-4": {
"Laminas\\Mime\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Create and parse MIME messages and parts",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"mime"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-mime/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-mime/issues",
"rss": "https://github.com/laminas/laminas-mime/releases.atom",
"source": "https://github.com/laminas/laminas-mime"
},
"time": "2020-03-29T13:12:07+00:00"
},
{
"name": "laminas/laminas-servicemanager",
"version": "3.5.2",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-servicemanager.git",
"reference": "0669e1eec8d9f61e35a5bc5012796d49f418b259"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/0669e1eec8d9f61e35a5bc5012796d49f418b259",
"reference": "0669e1eec8d9f61e35a5bc5012796d49f418b259",
"shasum": ""
},
"require": {
"container-interop/container-interop": "^1.2",
"laminas/laminas-stdlib": "^3.2.1",
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^5.6 || ^7.0",
"psr/container": "^1.0"
},
"provide": {
"container-interop/container-interop-implementation": "^1.2",
"psr/container-implementation": "^1.0"
},
"replace": {
"zendframework/zend-servicemanager": "^3.4.0"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"mikey179/vfsstream": "^1.6.5",
"ocramius/proxy-manager": "^1.0 || ^2.0",
"phpbench/phpbench": "^0.13.0",
"phpunit/phpunit": "^5.7.25 || ^6.4.4"
},
"suggest": {
"laminas/laminas-stdlib": "laminas-stdlib ^2.5 if you wish to use the MergeReplaceKey or MergeRemoveKey features in Config instances",
"ocramius/proxy-manager": "ProxyManager 1.* to handle lazy initialization of services"
},
"bin": [
"bin/generate-deps-for-config-factory",
"bin/generate-factory-for-class"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.3-dev",
"dev-develop": "4.0-dev"
}
},
"autoload": {
"psr-4": {
"Laminas\\ServiceManager\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Factory-Driven Dependency Injection Container",
"homepage": "https://laminas.dev",
"keywords": [
"PSR-11",
"dependency-injection",
"di",
"dic",
"laminas",
"service-manager",
"servicemanager"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-servicemanager/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-servicemanager/issues",
"rss": "https://github.com/laminas/laminas-servicemanager/releases.atom",
"source": "https://github.com/laminas/laminas-servicemanager"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2021-01-17T16:54:43+00:00"
},
{
"name": "laminas/laminas-stdlib",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-stdlib.git",
"reference": "2b18347625a2f06a1a485acfbc870f699dbe51c6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/2b18347625a2f06a1a485acfbc870f699dbe51c6",
"reference": "2b18347625a2f06a1a485acfbc870f699dbe51c6",
"shasum": ""
},
"require": {
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^5.6 || ^7.0"
},
"replace": {
"zendframework/zend-stdlib": "self.version"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"phpbench/phpbench": "^0.13",
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2.x-dev",
"dev-develop": "3.3.x-dev"
}
},
"autoload": {
"psr-4": {
"Laminas\\Stdlib\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "SPL extensions, array utilities, error handlers, and more",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"stdlib"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-stdlib/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-stdlib/issues",
"rss": "https://github.com/laminas/laminas-stdlib/releases.atom",
"source": "https://github.com/laminas/laminas-stdlib"
},
"time": "2019-12-31T17:51:15+00:00"
},
{
"name": "laminas/laminas-validator",
"version": "2.13.5",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-validator.git",
"reference": "d334dddda43af263d6a7e5024fd2b013cb6981f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-validator/zipball/d334dddda43af263d6a7e5024fd2b013cb6981f7",
"reference": "d334dddda43af263d6a7e5024fd2b013cb6981f7",
"shasum": ""
},
"require": {
"container-interop/container-interop": "^1.1",
"laminas/laminas-stdlib": "^3.2.1",
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^7.1"
},
"replace": {
"zendframework/zend-validator": "^2.13.0"
},
"require-dev": {
"laminas/laminas-cache": "^2.6.1",
"laminas/laminas-coding-standard": "~1.0.0",
"laminas/laminas-config": "^2.6",
"laminas/laminas-db": "^2.7",
"laminas/laminas-filter": "^2.6",
"laminas/laminas-http": "^2.5.4",
"laminas/laminas-i18n": "^2.6",
"laminas/laminas-math": "^2.6",
"laminas/laminas-servicemanager": "^2.7.5 || ^3.0.3",
"laminas/laminas-session": "^2.8",
"laminas/laminas-uri": "^2.5",
"phpunit/phpunit": "^7.5.20 || ^8.5.2",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.0"
},
"suggest": {
"laminas/laminas-db": "Laminas\\Db component, required by the (No)RecordExists validator",
"laminas/laminas-filter": "Laminas\\Filter component, required by the Digits validator",
"laminas/laminas-i18n": "Laminas\\I18n component to allow translation of validation error messages",
"laminas/laminas-i18n-resources": "Translations of validator messages",
"laminas/laminas-math": "Laminas\\Math component, required by the Csrf validator",
"laminas/laminas-servicemanager": "Laminas\\ServiceManager component to allow using the ValidatorPluginManager and validator chains",
"laminas/laminas-session": "Laminas\\Session component, ^2.8; required by the Csrf validator",
"laminas/laminas-uri": "Laminas\\Uri component, required by the Uri and Sitemap\\Loc validators",
"psr/http-message": "psr/http-message, required when validating PSR-7 UploadedFileInterface instances via the Upload and UploadFile validators"
},
"type": "library",
"extra": {
"laminas": {
"component": "Laminas\\Validator",
"config-provider": "Laminas\\Validator\\ConfigProvider"
}
},
"autoload": {
"psr-4": {
"Laminas\\Validator\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Validation classes for a wide range of domains, and the ability to chain validators to create complex validation criteria",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"validator"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-validator/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-validator/issues",
"rss": "https://github.com/laminas/laminas-validator/releases.atom",
"source": "https://github.com/laminas/laminas-validator"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2021-01-06T15:05:04+00:00"
},
{
"name": "laminas/laminas-zendframework-bridge",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-zendframework-bridge.git",
"reference": "6ede70583e101030bcace4dcddd648f760ddf642"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/6ede70583e101030bcace4dcddd648f760ddf642",
"reference": "6ede70583e101030bcace4dcddd648f760ddf642",
"shasum": ""
},
"require": {
"php": "^5.6 || ^7.0 || ^8.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1 || ^9.3",
"squizlabs/php_codesniffer": "^3.5"
},
"type": "library",
"extra": {
"laminas": {
"module": "Laminas\\ZendFrameworkBridge"
}
},
"autoload": {
"files": [
"src/autoload.php"
],
"psr-4": {
"Laminas\\ZendFrameworkBridge\\": "src//"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Alias legacy ZF class names to Laminas Project equivalents.",
"keywords": [
"ZendFramework",
"autoloading",
"laminas",
"zf"
],
"support": {
"forum": "https://discourse.laminas.dev/",
"issues": "https://github.com/laminas/laminas-zendframework-bridge/issues",
"rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom",
"source": "https://github.com/laminas/laminas-zendframework-bridge"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2020-09-14T14:23:00+00:00"
},
{
"name": "nikic/php-parser",
"version": "v4.12.0",
@@ -738,60 +1262,6 @@
],
"time": "2019-12-12T05:00:52+00:00"
},
{
"name": "swiftmailer/swiftmailer",
"version": "v5.4.12",
"source": {
"type": "git",
"url": "https://github.com/swiftmailer/swiftmailer.git",
"reference": "181b89f18a90f8925ef805f950d47a7190e9b950"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/181b89f18a90f8925ef805f950d47a7190e9b950",
"reference": "181b89f18a90f8925ef805f950d47a7190e9b950",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"mockery/mockery": "~0.9.1",
"symfony/phpunit-bridge": "~3.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.4-dev"
}
},
"autoload": {
"files": [
"lib/swift_required.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Chris Corbyn"
},
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Swiftmailer, free feature-rich PHP mailer",
"homepage": "https://swiftmailer.symfony.com",
"keywords": [
"email",
"mail",
"mailer"
],
"time": "2018-07-31T09:26:32+00:00"
},
{
"name": "symfony/cache",
"version": "v3.4.47",
@@ -2696,6 +3166,56 @@
],
"time": "2020-10-24T10:57:07+00:00"
},
{
"name": "true/punycode",
"version": "v2.1.1",
"source": {
"type": "git",
"url": "https://github.com/true/php-punycode.git",
"reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/true/php-punycode/zipball/a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
"reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"symfony/polyfill-mbstring": "^1.3"
},
"require-dev": {
"phpunit/phpunit": "~4.7",
"squizlabs/php_codesniffer": "~2.0"
},
"type": "library",
"autoload": {
"psr-4": {
"TrueBV\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Renan Gonçalves",
"email": "renan.saddam@gmail.com"
}
],
"description": "A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)",
"homepage": "https://github.com/true/php-punycode",
"keywords": [
"idna",
"punycode"
],
"support": {
"issues": "https://github.com/true/php-punycode/issues",
"source": "https://github.com/true/php-punycode/tree/master"
},
"time": "2016-11-16T10:37:54+00:00"
},
{
"name": "twig/twig",
"version": "v1.42.4",
@@ -3007,5 +3527,5 @@
"platform-overrides": {
"php": "7.1.3"
},
"plugin-api-version": "2.1.0"
"plugin-api-version": "2.2.0"
}

View File

@@ -409,8 +409,6 @@ class AsyncSendEmail extends AsyncTask
$oNew->Set('to', $oEMail->GetRecipientTO(true /* string */));
$oNew->Set('subject', $oEMail->GetSubject());
// $oNew->Set('version', 1);
// $sMessage = serialize($oEMail);
$oNew->Set('version', 2);
$sMessage = $oEMail->SerializeV2();
$oNew->Set('message', $sMessage);

View File

@@ -24,13 +24,18 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
use Laminas\Mail\Header\ContentType;
use Laminas\Mail\Message;
use Laminas\Mail\Transport\File;
use Laminas\Mail\Transport\FileOptions;
use Laminas\Mail\Transport\SmtpOptions;
use Laminas\Mail\Transport\Smtp;
use Laminas\Mime\Mime;
use Laminas\Mime\Part;
use Pelago\Emogrifier\CssInliner;
use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter;
use Pelago\Emogrifier\HtmlProcessor\HtmlPruner;
Swift_Preferences::getInstance()->setCharset('UTF-8');
define ('EMAIL_SEND_OK', 0);
define ('EMAIL_SEND_PENDING', 1);
define ('EMAIL_SEND_ERROR', 2);
@@ -58,7 +63,8 @@ class EMail
public function __construct()
{
$this->m_aData = array();
$this->m_oMessage = Swift_Message::newInstance();
$this->m_oMessage = new Message();
$this->m_oMessage->setEncoding('UTF-8');
$this->SetRecipientFrom(MetaModel::GetConfig()->Get('email_default_sender_address'), MetaModel::GetConfig()->Get('email_default_sender_label'));
}
@@ -75,9 +81,15 @@ class EMail
/**
* Custom de-serialization method
*
* @param string $sSerializedMessage The serialized representation of the message
*
* @return \EMail
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \Symfony\Component\CssSelector\Exception\SyntaxErrorException
*/
static public function UnSerializeV2($sSerializedMessage)
public static function UnSerializeV2($sSerializedMessage)
{
$aData = unserialize($sSerializedMessage);
$oMessage = new Email();
@@ -115,7 +127,6 @@ class EMail
$oMessage->SetSubject($aData['subject']);
}
if (array_key_exists('headers', $aData))
{
foreach($aData['headers'] as $sKey => $sValue)
@@ -155,10 +166,11 @@ class EMail
return EMAIL_SEND_PENDING;
}
/**
* @throws \Exception
*/
protected function SendSynchronous(&$aIssues, $oLog = null)
{
// If the body of the message is in HTML, embed all images based on attachments
$this->EmbedInlineImages();
$this->LoadConfig();
@@ -172,50 +184,54 @@ class EMail
$sUserName = self::$m_oConfig->Get('email_transport_smtp.username');
$sPassword = self::$m_oConfig->Get('email_transport_smtp.password');
$oTransport = Swift_SmtpTransport::newInstance($sHost, $sPort, $sEncryption);
$oTransport = new Smtp();
$aOptions= [
'host' => $sHost,
'port' => $sPort,
'connection_class' => 'login',
'connection_config' => [
'ssl' => $sEncryption,
],
];
if (strlen($sUserName) > 0)
{
$oTransport->setUsername($sUserName);
$oTransport->setPassword($sPassword);
$aOptions['connection_config']['username'] = $sUserName;
$aOptions['connection_config']['password'] = $sPassword;
}
$oOptions = new SmtpOptions($aOptions);
$oTransport->setOptions($oOptions);
break;
case 'Null':
$oTransport = Swift_NullTransport::newInstance();
$oTransport = new Smtp();
break;
case 'LogFile':
$oTransport = Swift_LogFileTransport::newInstance();
$oTransport->setLogFile(APPROOT.'log/mail.log');
$oTransport = new File();
$aOptions = new FileOptions([
'path' => APPROOT.'log/mail.log',
]);
$oTransport->setOptions($aOptions);
break;
case 'PHPMail':
default:
$oTransport = Swift_MailTransport::newInstance();
$oTransport = new Smtp();
}
$oMailer = Swift_Mailer::newInstance($oTransport);
$aFailedRecipients = array();
$this->m_oMessage->setMaxLineLength(0);
$oKPI = new ExecutionKPI();
try
{
$iSent = $oMailer->send($this->m_oMessage, $aFailedRecipients);
if ($iSent === 0)
{
// Beware: it seems that $aFailedRecipients sometimes contains the recipients that actually received the message !!!
IssueLog::Warning('Email sending failed: Some recipients were invalid, aFailedRecipients contains: '.implode(', ', $aFailedRecipients));
$aIssues = array('Some recipients were invalid.');
$oKPI->ComputeStats('Email Sent', 'Error received');
return EMAIL_SEND_ERROR;
}
else
{
$aIssues = array();
$oKPI->ComputeStats('Email Sent', 'Succeded');
return EMAIL_SEND_OK;
}
$oTransport->send($this->m_oMessage);
$aIssues = array();
$oKPI->ComputeStats('Email Sent', 'Succeded');
return EMAIL_SEND_OK;
}
catch(Laminas\Mail\Transport\Exception\RuntimeException $e){
IssueLog::Warning('Email sending failed: Some recipients were invalid');
$aIssues = array('Some recipients were invalid.');
$oKPI->ComputeStats('Email Sent', 'Error received');
return EMAIL_SEND_ERROR;
}
catch (Exception $e)
{
@@ -227,47 +243,61 @@ class EMail
/**
* Reprocess the body of the message (if it is an HTML message)
* to replace the URL of images based on attachments by a link
* to an embedded image (i.e. cid:....)
* to an embedded image (i.e. cid:....) and returns images to be attached as an array
*
* @param string $sBody Email body to process/alter
*
* @return array Array of Part that needs to be added as inline attachment later to render as embed
* @throws \ArchivedObjectException
* @throws \CoreException
*/
protected function EmbedInlineImages()
protected function EmbedInlineImages(string &$sBody)
{
if ($this->m_aData['body']['mimeType'] == 'text/html')
$oDOMDoc = new DOMDocument();
$oDOMDoc->preserveWhitespace = true;
@$oDOMDoc->loadHTML('<?xml encoding="UTF-8"?>'.$sBody); // For loading HTML chunks where the character set is not specified
$oXPath = new DOMXPath($oDOMDoc);
$sXPath = '//img[@'.InlineImage::DOM_ATTR_ID.']';
$oImagesList = $oXPath->query($sXPath);
$oImagesContent = new \Laminas\Mime\Message();
$aImagesParts = [];
if ($oImagesList->length != 0)
{
$oDOMDoc = new DOMDocument();
$oDOMDoc->preserveWhitespace = true;
@$oDOMDoc->loadHTML('<?xml encoding="UTF-8"?>'.$this->m_aData['body']['body']); // For loading HTML chunks where the character set is not specified
$oXPath = new DOMXPath($oDOMDoc);
$sXPath = '//img[@'.InlineImage::DOM_ATTR_ID.']';
$oImagesList = $oXPath->query($sXPath);
if ($oImagesList->length != 0)
foreach($oImagesList as $oImg)
{
foreach($oImagesList as $oImg)
$iAttId = $oImg->getAttribute(InlineImage::DOM_ATTR_ID);
$oAttachment = MetaModel::GetObject('InlineImage', $iAttId, false, true /* Allow All Data */);
if ($oAttachment)
{
$iAttId = $oImg->getAttribute(InlineImage::DOM_ATTR_ID);
$oAttachment = MetaModel::GetObject('InlineImage', $iAttId, false, true /* Allow All Data */);
if ($oAttachment)
$sImageSecret = $oImg->getAttribute('data-img-secret');
$sAttachmentSecret = $oAttachment->Get('secret');
if ($sImageSecret !== $sAttachmentSecret)
{
$sImageSecret = $oImg->getAttribute('data-img-secret');
$sAttachmentSecret = $oAttachment->Get('secret');
if ($sImageSecret !== $sAttachmentSecret)
{
// @see N°1921
// If copying from another iTop we could get an IMG pointing to an InlineImage with wrong secret
continue;
}
$oDoc = $oAttachment->Get('contents');
$oSwiftImage = new Swift_Image($oDoc->GetData(), $oDoc->GetFileName(), $oDoc->GetMimeType());
$sCid = $this->m_oMessage->embed($oSwiftImage);
$oImg->setAttribute('src', $sCid);
// @see N°1921
// If copying from another iTop we could get an IMG pointing to an InlineImage with wrong secret
continue;
}
$oDoc = $oAttachment->Get('contents');
$sCid = uniqid('', true);
$oNewAttachment = new Part($oDoc->GetData());
$oNewAttachment->id = $sCid;
$oNewAttachment->type = $oDoc->GetMimeType();
$oNewAttachment->filename = $oDoc->GetFileName();
$oNewAttachment->disposition = Mime::DISPOSITION_INLINE;
$oNewAttachment->encoding = Mime::ENCODING_BASE64;
$oImagesContent->addPart($oNewAttachment);
$oImg->setAttribute('src', 'cid:'.$sCid);
$aImagesParts[] = $oNewAttachment;
}
}
$sHtmlBody = $oDOMDoc->saveHTML();
$this->m_oMessage->setBody($sHtmlBody, 'text/html', 'UTF-8');
}
$sBody = $oDOMDoc->saveHTML();
return $aImagesParts;
}
public function Send(&$aIssues, $bForceSynchronous = false, $oLog = null)
@@ -313,7 +343,7 @@ class EMail
break;
default:
$oHeaders->addTextHeader($sKey, $sValue);
$oHeaders->addHeaderLine($sKey, $sValue);
}
}
}
@@ -326,8 +356,7 @@ class EMail
// so let's remove the angle brackets if present, for historical reasons
$sId = str_replace(array('<', '>'), '', $sId);
$oMsgId = $this->m_oMessage->getHeaders()->get('Message-ID');
$oMsgId->SetId($sId);
$this->m_oMessage->getHeaders()->addHeaderLine('Message-ID', $sId);
}
public function SetReferences($sReferences)
@@ -349,35 +378,123 @@ class EMail
$this->AddToHeader('In-Reply-To', $sMessageId);
}
public function SetBody($sBody, $sMimeType = 'text/html', $sCustomStyles = null)
/**
* Set current Email body and process inline images.
*
* @param $sBody
* @param string $sMimeType
* @param $sCustomStyles
*
* @return void
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \Symfony\Component\CssSelector\Exception\SyntaxErrorException
*/
public function SetBody($sBody, string $sMimeType = Mime::TYPE_HTML, $sCustomStyles = null)
{
if (($sMimeType === 'text/html') && ($sCustomStyles !== null)) {
$oBody = new Laminas\Mime\Message();
$aAdditionalParts = [];
if (($sMimeType === Mime::TYPE_HTML) && ($sCustomStyles !== null)) {
$oDomDocument = CssInliner::fromHtml($sBody)->inlineCss($sCustomStyles)->getDomDocument();
HtmlPruner::fromDomDocument($oDomDocument)->removeElementsWithDisplayNone();
$sBody = CssToAttributeConverter::fromDomDocument($oDomDocument)->convertCssToVisualAttributes()->render(); // Adds html/body tags if not already present
}
$this->m_aData['body'] = array('body' => $sBody, 'mimeType' => $sMimeType);
$this->m_oMessage->setBody($sBody, $sMimeType);
// We don't want these modifications in m_aData['body'], otherwise it'll ruin asynchronous mail as they go through this method twice
if ($sMimeType === Mime::TYPE_HTML){
$aAdditionalParts = $this->EmbedInlineImages($sBody);
}
// Add body content to as a new part
$oNewPart = new Part($sBody);
$oNewPart->encoding = Mime::ENCODING_8BIT;
$oNewPart->type = $sMimeType;
$oBody->addPart($oNewPart);
// Add additional images as new body parts
foreach ($aAdditionalParts as $oAdditionalPart) {
$oBody->addPart($oAdditionalPart);
}
if($oBody->isMultiPart()){
$oContentTypeHeader = $this->m_oMessage->getHeaders();
foreach ($oContentTypeHeader as $oHeader) {
if (!$oHeader instanceof ContentType) {
continue;
}
$oHeader->setType(Mime::MULTIPART_MIXED);
$oHeader->addParameter('boundary', $oBody->getMime()->boundary());
break;
}
}
$this->m_oMessage->setBody($oBody);
}
public function AddPart($sText, $sMimeType = 'text/html')
/**
* Add a new part to the existing body
* @param $sText
* @param string $sMimeType
*
* @return void
*/
public function AddPart($sText, string $sMimeType = Mime::TYPE_HTML)
{
if (!array_key_exists('parts', $this->m_aData))
{
$this->m_aData['parts'] = array();
}
$this->m_aData['parts'][] = array('text' => $sText, 'mimeType' => $sMimeType);
$this->m_oMessage->addPart($sText, $sMimeType);
$oNewPart = new Part($sText);
$oNewPart->encoding = Mime::ENCODING_8BIT;
$oNewPart->type = $sMimeType;
$this->m_oMessage->getBody()->addPart($oNewPart);
}
public function AddAttachment($data, $sFileName, $sMimeType)
{
$oBody = $this->m_oMessage->getBody();
if(!$oBody->isMultiPart()){
$multipart_content = new Part($oBody->generateMessage());
$multipart_content->setType($oBody->getParts()[0]->getType());
$multipart_content->setBoundary($oBody->getMime()->boundary());
$oBody = new Laminas\Mime\Message();
$oBody->addPart($multipart_content);
}
if (!array_key_exists('attachments', $this->m_aData))
{
$this->m_aData['attachments'] = array();
}
$this->m_aData['attachments'][] = array('data' => base64_encode($data), 'filename' => $sFileName, 'mimeType' => $sMimeType);
$this->m_oMessage->attach(Swift_Attachment::newInstance($data, $sFileName, $sMimeType));
$oNewAttachment = new Part($data);
$oNewAttachment->type = $sMimeType;
$oNewAttachment->filename = $sFileName;
$oNewAttachment->disposition = Mime::DISPOSITION_ATTACHMENT;
$oNewAttachment->encoding = Mime::ENCODING_BASE64;
$oBody->addPart($oNewAttachment);
if($oBody->isMultiPart()){
$oContentTypeHeader = $this->m_oMessage->getHeaders();
foreach ($oContentTypeHeader as $oHeader) {
if (!$oHeader instanceof ContentType) {
continue;
}
$oHeader->setType(Mime::MULTIPART_MIXED);
$oHeader->addParameter('boundary', $oBody->getMime()->boundary());
break;
}
}
$this->m_oMessage->setBody($oBody);
}
public function SetSubject($sSubject)
@@ -422,7 +539,7 @@ class EMail
public function GetRecipientTO($bAsString = false)
{
$aRes = $this->m_oMessage->getTo();
if ($aRes === null)
if ($aRes === null || $aRes->count() === 0)
{
// There is no "To" header field
$aRes = array();
@@ -430,8 +547,10 @@ class EMail
if ($bAsString)
{
$aStrings = array();
foreach ($aRes as $sEmail => $sName)
foreach ($aRes as $oEmail)
{
$sName = $oEmail->getName();
$sEmail = $oEmail->getEmail();
if (is_null($sName))
{
$aStrings[] = $sEmail;
@@ -497,76 +616,3 @@ class EMail
}
}
/////////////////////////////////////////////////////////////////////////////////////
/**
* Extension to SwiftMailer: "debug" transport that pretends messages have been sent,
* but just log them to a file.
*
* @package Swift
* @author Denis Flaven
*/
class Swift_Transport_LogFileTransport extends Swift_Transport_NullTransport
{
protected $sLogFile;
/**
* Sends the given message.
*
* @param Swift_Mime_Message $message
* @param string[] $failedRecipients An array of failures by-reference
*
* @return int The number of sent emails
*/
public function send(Swift_Mime_Message $message, &$failedRecipients = null)
{
$hFile = @fopen($this->sLogFile, 'a');
if ($hFile)
{
$sTxt = "================== ".date('Y-m-d H:i:s')." ==================\n";
$sTxt .= $message->toString()."\n";
@fwrite($hFile, $sTxt);
@fclose($hFile);
}
return parent::send($message, $failedRecipients);
}
public function setLogFile($sFilename)
{
$this->sLogFile = $sFilename;
}
}
/**
* Pretends messages have been sent, but just log them to a file.
*
* @package Swift
* @author Denis Flaven
*/
class Swift_LogFileTransport extends Swift_Transport_LogFileTransport
{
/**
* Create a new LogFileTransport.
*/
public function __construct()
{
call_user_func_array(
array($this, 'Swift_Transport_LogFileTransport::__construct'),
Swift_DependencyContainer::getInstance()
->createDependenciesFor('transport.null')
);
}
/**
* Create a new LogFileTransport instance.
*
* @return Swift_LogFileTransport
*/
public static function newInstance()
{
return new self();
}
}

View File

@@ -149,7 +149,7 @@ class ClassLoader
/**
* @return string[] Array of classname => path
* @psalm-var array<string, string>
* @psalm-return array<string, string>
*/
public function getClassMap()
{

View File

@@ -24,8 +24,21 @@ use Composer\Semver\VersionParser;
*/
class InstalledVersions
{
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
*/
private static $installed;
/**
* @var bool|null
*/
private static $canGetVendors;
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
*/
private static $installedByVendor = array();
/**

View File

@@ -487,6 +487,9 @@ return array(
'InlineImage' => $baseDir . '/core/inlineimage.class.inc.php',
'InlineImageGC' => $baseDir . '/core/inlineimage.class.inc.php',
'InputOutputTask' => $baseDir . '/application/iotask.class.inc.php',
'Interop\\Container\\ContainerInterface' => $vendorDir . '/container-interop/container-interop/src/Interop/Container/ContainerInterface.php',
'Interop\\Container\\Exception\\ContainerException' => $vendorDir . '/container-interop/container-interop/src/Interop/Container/Exception/ContainerException.php',
'Interop\\Container\\Exception\\NotFoundException' => $vendorDir . '/container-interop/container-interop/src/Interop/Container/Exception/NotFoundException.php',
'IntervalExpression' => $baseDir . '/core/oql/expression.class.inc.php',
'IntervalOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php',
'Introspection' => $baseDir . '/core/introspection.class.inc.php',
@@ -498,6 +501,322 @@ return array(
'JSPopupMenuItem' => $baseDir . '/application/applicationextension.inc.php',
'JsonPage' => $baseDir . '/sources/Application/WebPage/JsonPage.php',
'KeyValueStore' => $baseDir . '/core/counter.class.inc.php',
'Laminas\\Loader\\AutoloaderFactory' => $vendorDir . '/laminas/laminas-loader/src/AutoloaderFactory.php',
'Laminas\\Loader\\ClassMapAutoloader' => $vendorDir . '/laminas/laminas-loader/src/ClassMapAutoloader.php',
'Laminas\\Loader\\Exception\\BadMethodCallException' => $vendorDir . '/laminas/laminas-loader/src/Exception/BadMethodCallException.php',
'Laminas\\Loader\\Exception\\DomainException' => $vendorDir . '/laminas/laminas-loader/src/Exception/DomainException.php',
'Laminas\\Loader\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-loader/src/Exception/ExceptionInterface.php',
'Laminas\\Loader\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-loader/src/Exception/InvalidArgumentException.php',
'Laminas\\Loader\\Exception\\InvalidPathException' => $vendorDir . '/laminas/laminas-loader/src/Exception/InvalidPathException.php',
'Laminas\\Loader\\Exception\\MissingResourceNamespaceException' => $vendorDir . '/laminas/laminas-loader/src/Exception/MissingResourceNamespaceException.php',
'Laminas\\Loader\\Exception\\PluginLoaderException' => $vendorDir . '/laminas/laminas-loader/src/Exception/PluginLoaderException.php',
'Laminas\\Loader\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-loader/src/Exception/RuntimeException.php',
'Laminas\\Loader\\Exception\\SecurityException' => $vendorDir . '/laminas/laminas-loader/src/Exception/SecurityException.php',
'Laminas\\Loader\\ModuleAutoloader' => $vendorDir . '/laminas/laminas-loader/src/ModuleAutoloader.php',
'Laminas\\Loader\\PluginClassLoader' => $vendorDir . '/laminas/laminas-loader/src/PluginClassLoader.php',
'Laminas\\Loader\\PluginClassLocator' => $vendorDir . '/laminas/laminas-loader/src/PluginClassLocator.php',
'Laminas\\Loader\\ShortNameLocator' => $vendorDir . '/laminas/laminas-loader/src/ShortNameLocator.php',
'Laminas\\Loader\\SplAutoloader' => $vendorDir . '/laminas/laminas-loader/src/SplAutoloader.php',
'Laminas\\Loader\\StandardAutoloader' => $vendorDir . '/laminas/laminas-loader/src/StandardAutoloader.php',
'Laminas\\Mail\\Address' => $vendorDir . '/laminas/laminas-mail/src/Address.php',
'Laminas\\Mail\\AddressList' => $vendorDir . '/laminas/laminas-mail/src/AddressList.php',
'Laminas\\Mail\\Address\\AddressInterface' => $vendorDir . '/laminas/laminas-mail/src/Address/AddressInterface.php',
'Laminas\\Mail\\ConfigProvider' => $vendorDir . '/laminas/laminas-mail/src/ConfigProvider.php',
'Laminas\\Mail\\Exception\\BadMethodCallException' => $vendorDir . '/laminas/laminas-mail/src/Exception/BadMethodCallException.php',
'Laminas\\Mail\\Exception\\DomainException' => $vendorDir . '/laminas/laminas-mail/src/Exception/DomainException.php',
'Laminas\\Mail\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-mail/src/Exception/ExceptionInterface.php',
'Laminas\\Mail\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-mail/src/Exception/InvalidArgumentException.php',
'Laminas\\Mail\\Exception\\OutOfBoundsException' => $vendorDir . '/laminas/laminas-mail/src/Exception/OutOfBoundsException.php',
'Laminas\\Mail\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-mail/src/Exception/RuntimeException.php',
'Laminas\\Mail\\Header\\AbstractAddressList' => $vendorDir . '/laminas/laminas-mail/src/Header/AbstractAddressList.php',
'Laminas\\Mail\\Header\\Bcc' => $vendorDir . '/laminas/laminas-mail/src/Header/Bcc.php',
'Laminas\\Mail\\Header\\Cc' => $vendorDir . '/laminas/laminas-mail/src/Header/Cc.php',
'Laminas\\Mail\\Header\\ContentDisposition' => $vendorDir . '/laminas/laminas-mail/src/Header/ContentDisposition.php',
'Laminas\\Mail\\Header\\ContentTransferEncoding' => $vendorDir . '/laminas/laminas-mail/src/Header/ContentTransferEncoding.php',
'Laminas\\Mail\\Header\\ContentType' => $vendorDir . '/laminas/laminas-mail/src/Header/ContentType.php',
'Laminas\\Mail\\Header\\Date' => $vendorDir . '/laminas/laminas-mail/src/Header/Date.php',
'Laminas\\Mail\\Header\\Exception\\BadMethodCallException' => $vendorDir . '/laminas/laminas-mail/src/Header/Exception/BadMethodCallException.php',
'Laminas\\Mail\\Header\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-mail/src/Header/Exception/ExceptionInterface.php',
'Laminas\\Mail\\Header\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-mail/src/Header/Exception/InvalidArgumentException.php',
'Laminas\\Mail\\Header\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-mail/src/Header/Exception/RuntimeException.php',
'Laminas\\Mail\\Header\\From' => $vendorDir . '/laminas/laminas-mail/src/Header/From.php',
'Laminas\\Mail\\Header\\GenericHeader' => $vendorDir . '/laminas/laminas-mail/src/Header/GenericHeader.php',
'Laminas\\Mail\\Header\\GenericMultiHeader' => $vendorDir . '/laminas/laminas-mail/src/Header/GenericMultiHeader.php',
'Laminas\\Mail\\Header\\HeaderInterface' => $vendorDir . '/laminas/laminas-mail/src/Header/HeaderInterface.php',
'Laminas\\Mail\\Header\\HeaderLoader' => $vendorDir . '/laminas/laminas-mail/src/Header/HeaderLoader.php',
'Laminas\\Mail\\Header\\HeaderLocator' => $vendorDir . '/laminas/laminas-mail/src/Header/HeaderLocator.php',
'Laminas\\Mail\\Header\\HeaderLocatorInterface' => $vendorDir . '/laminas/laminas-mail/src/Header/HeaderLocatorInterface.php',
'Laminas\\Mail\\Header\\HeaderName' => $vendorDir . '/laminas/laminas-mail/src/Header/HeaderName.php',
'Laminas\\Mail\\Header\\HeaderValue' => $vendorDir . '/laminas/laminas-mail/src/Header/HeaderValue.php',
'Laminas\\Mail\\Header\\HeaderWrap' => $vendorDir . '/laminas/laminas-mail/src/Header/HeaderWrap.php',
'Laminas\\Mail\\Header\\IdentificationField' => $vendorDir . '/laminas/laminas-mail/src/Header/IdentificationField.php',
'Laminas\\Mail\\Header\\InReplyTo' => $vendorDir . '/laminas/laminas-mail/src/Header/InReplyTo.php',
'Laminas\\Mail\\Header\\ListParser' => $vendorDir . '/laminas/laminas-mail/src/Header/ListParser.php',
'Laminas\\Mail\\Header\\MessageId' => $vendorDir . '/laminas/laminas-mail/src/Header/MessageId.php',
'Laminas\\Mail\\Header\\MimeVersion' => $vendorDir . '/laminas/laminas-mail/src/Header/MimeVersion.php',
'Laminas\\Mail\\Header\\MultipleHeadersInterface' => $vendorDir . '/laminas/laminas-mail/src/Header/MultipleHeadersInterface.php',
'Laminas\\Mail\\Header\\Received' => $vendorDir . '/laminas/laminas-mail/src/Header/Received.php',
'Laminas\\Mail\\Header\\References' => $vendorDir . '/laminas/laminas-mail/src/Header/References.php',
'Laminas\\Mail\\Header\\ReplyTo' => $vendorDir . '/laminas/laminas-mail/src/Header/ReplyTo.php',
'Laminas\\Mail\\Header\\Sender' => $vendorDir . '/laminas/laminas-mail/src/Header/Sender.php',
'Laminas\\Mail\\Header\\StructuredInterface' => $vendorDir . '/laminas/laminas-mail/src/Header/StructuredInterface.php',
'Laminas\\Mail\\Header\\Subject' => $vendorDir . '/laminas/laminas-mail/src/Header/Subject.php',
'Laminas\\Mail\\Header\\To' => $vendorDir . '/laminas/laminas-mail/src/Header/To.php',
'Laminas\\Mail\\Header\\UnstructuredInterface' => $vendorDir . '/laminas/laminas-mail/src/Header/UnstructuredInterface.php',
'Laminas\\Mail\\Headers' => $vendorDir . '/laminas/laminas-mail/src/Headers.php',
'Laminas\\Mail\\Message' => $vendorDir . '/laminas/laminas-mail/src/Message.php',
'Laminas\\Mail\\MessageFactory' => $vendorDir . '/laminas/laminas-mail/src/MessageFactory.php',
'Laminas\\Mail\\Module' => $vendorDir . '/laminas/laminas-mail/src/Module.php',
'Laminas\\Mail\\Protocol\\AbstractProtocol' => $vendorDir . '/laminas/laminas-mail/src/Protocol/AbstractProtocol.php',
'Laminas\\Mail\\Protocol\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Exception/ExceptionInterface.php',
'Laminas\\Mail\\Protocol\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Exception/InvalidArgumentException.php',
'Laminas\\Mail\\Protocol\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Exception/RuntimeException.php',
'Laminas\\Mail\\Protocol\\Imap' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Imap.php',
'Laminas\\Mail\\Protocol\\Pop3' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Pop3.php',
'Laminas\\Mail\\Protocol\\ProtocolTrait' => $vendorDir . '/laminas/laminas-mail/src/Protocol/ProtocolTrait.php',
'Laminas\\Mail\\Protocol\\Smtp' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Smtp.php',
'Laminas\\Mail\\Protocol\\SmtpPluginManager' => $vendorDir . '/laminas/laminas-mail/src/Protocol/SmtpPluginManager.php',
'Laminas\\Mail\\Protocol\\SmtpPluginManagerFactory' => $vendorDir . '/laminas/laminas-mail/src/Protocol/SmtpPluginManagerFactory.php',
'Laminas\\Mail\\Protocol\\Smtp\\Auth\\Crammd5' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Smtp/Auth/Crammd5.php',
'Laminas\\Mail\\Protocol\\Smtp\\Auth\\Login' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Smtp/Auth/Login.php',
'Laminas\\Mail\\Protocol\\Smtp\\Auth\\Plain' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Smtp/Auth/Plain.php',
'Laminas\\Mail\\Storage' => $vendorDir . '/laminas/laminas-mail/src/Storage.php',
'Laminas\\Mail\\Storage\\AbstractStorage' => $vendorDir . '/laminas/laminas-mail/src/Storage/AbstractStorage.php',
'Laminas\\Mail\\Storage\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-mail/src/Storage/Exception/ExceptionInterface.php',
'Laminas\\Mail\\Storage\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-mail/src/Storage/Exception/InvalidArgumentException.php',
'Laminas\\Mail\\Storage\\Exception\\OutOfBoundsException' => $vendorDir . '/laminas/laminas-mail/src/Storage/Exception/OutOfBoundsException.php',
'Laminas\\Mail\\Storage\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-mail/src/Storage/Exception/RuntimeException.php',
'Laminas\\Mail\\Storage\\Folder' => $vendorDir . '/laminas/laminas-mail/src/Storage/Folder.php',
'Laminas\\Mail\\Storage\\Folder\\FolderInterface' => $vendorDir . '/laminas/laminas-mail/src/Storage/Folder/FolderInterface.php',
'Laminas\\Mail\\Storage\\Folder\\Maildir' => $vendorDir . '/laminas/laminas-mail/src/Storage/Folder/Maildir.php',
'Laminas\\Mail\\Storage\\Folder\\Mbox' => $vendorDir . '/laminas/laminas-mail/src/Storage/Folder/Mbox.php',
'Laminas\\Mail\\Storage\\Imap' => $vendorDir . '/laminas/laminas-mail/src/Storage/Imap.php',
'Laminas\\Mail\\Storage\\Maildir' => $vendorDir . '/laminas/laminas-mail/src/Storage/Maildir.php',
'Laminas\\Mail\\Storage\\Mbox' => $vendorDir . '/laminas/laminas-mail/src/Storage/Mbox.php',
'Laminas\\Mail\\Storage\\Message' => $vendorDir . '/laminas/laminas-mail/src/Storage/Message.php',
'Laminas\\Mail\\Storage\\Message\\File' => $vendorDir . '/laminas/laminas-mail/src/Storage/Message/File.php',
'Laminas\\Mail\\Storage\\Message\\MessageInterface' => $vendorDir . '/laminas/laminas-mail/src/Storage/Message/MessageInterface.php',
'Laminas\\Mail\\Storage\\Part' => $vendorDir . '/laminas/laminas-mail/src/Storage/Part.php',
'Laminas\\Mail\\Storage\\Part\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-mail/src/Storage/Part/Exception/ExceptionInterface.php',
'Laminas\\Mail\\Storage\\Part\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-mail/src/Storage/Part/Exception/InvalidArgumentException.php',
'Laminas\\Mail\\Storage\\Part\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-mail/src/Storage/Part/Exception/RuntimeException.php',
'Laminas\\Mail\\Storage\\Part\\File' => $vendorDir . '/laminas/laminas-mail/src/Storage/Part/File.php',
'Laminas\\Mail\\Storage\\Part\\PartInterface' => $vendorDir . '/laminas/laminas-mail/src/Storage/Part/PartInterface.php',
'Laminas\\Mail\\Storage\\Pop3' => $vendorDir . '/laminas/laminas-mail/src/Storage/Pop3.php',
'Laminas\\Mail\\Storage\\Writable\\Maildir' => $vendorDir . '/laminas/laminas-mail/src/Storage/Writable/Maildir.php',
'Laminas\\Mail\\Storage\\Writable\\WritableInterface' => $vendorDir . '/laminas/laminas-mail/src/Storage/Writable/WritableInterface.php',
'Laminas\\Mail\\Transport\\Envelope' => $vendorDir . '/laminas/laminas-mail/src/Transport/Envelope.php',
'Laminas\\Mail\\Transport\\Exception\\DomainException' => $vendorDir . '/laminas/laminas-mail/src/Transport/Exception/DomainException.php',
'Laminas\\Mail\\Transport\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-mail/src/Transport/Exception/ExceptionInterface.php',
'Laminas\\Mail\\Transport\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-mail/src/Transport/Exception/InvalidArgumentException.php',
'Laminas\\Mail\\Transport\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-mail/src/Transport/Exception/RuntimeException.php',
'Laminas\\Mail\\Transport\\Factory' => $vendorDir . '/laminas/laminas-mail/src/Transport/Factory.php',
'Laminas\\Mail\\Transport\\File' => $vendorDir . '/laminas/laminas-mail/src/Transport/File.php',
'Laminas\\Mail\\Transport\\FileOptions' => $vendorDir . '/laminas/laminas-mail/src/Transport/FileOptions.php',
'Laminas\\Mail\\Transport\\InMemory' => $vendorDir . '/laminas/laminas-mail/src/Transport/InMemory.php',
'Laminas\\Mail\\Transport\\Sendmail' => $vendorDir . '/laminas/laminas-mail/src/Transport/Sendmail.php',
'Laminas\\Mail\\Transport\\Smtp' => $vendorDir . '/laminas/laminas-mail/src/Transport/Smtp.php',
'Laminas\\Mail\\Transport\\SmtpOptions' => $vendorDir . '/laminas/laminas-mail/src/Transport/SmtpOptions.php',
'Laminas\\Mail\\Transport\\TransportInterface' => $vendorDir . '/laminas/laminas-mail/src/Transport/TransportInterface.php',
'Laminas\\Mime\\Decode' => $vendorDir . '/laminas/laminas-mime/src/Decode.php',
'Laminas\\Mime\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-mime/src/Exception/ExceptionInterface.php',
'Laminas\\Mime\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-mime/src/Exception/InvalidArgumentException.php',
'Laminas\\Mime\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-mime/src/Exception/RuntimeException.php',
'Laminas\\Mime\\Message' => $vendorDir . '/laminas/laminas-mime/src/Message.php',
'Laminas\\Mime\\Mime' => $vendorDir . '/laminas/laminas-mime/src/Mime.php',
'Laminas\\Mime\\Part' => $vendorDir . '/laminas/laminas-mime/src/Part.php',
'Laminas\\ServiceManager\\AbstractFactoryInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/AbstractFactoryInterface.php',
'Laminas\\ServiceManager\\AbstractFactory\\ConfigAbstractFactory' => $vendorDir . '/laminas/laminas-servicemanager/src/AbstractFactory/ConfigAbstractFactory.php',
'Laminas\\ServiceManager\\AbstractFactory\\ReflectionBasedAbstractFactory' => $vendorDir . '/laminas/laminas-servicemanager/src/AbstractFactory/ReflectionBasedAbstractFactory.php',
'Laminas\\ServiceManager\\AbstractPluginManager' => $vendorDir . '/laminas/laminas-servicemanager/src/AbstractPluginManager.php',
'Laminas\\ServiceManager\\Config' => $vendorDir . '/laminas/laminas-servicemanager/src/Config.php',
'Laminas\\ServiceManager\\ConfigInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/ConfigInterface.php',
'Laminas\\ServiceManager\\DelegatorFactoryInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/DelegatorFactoryInterface.php',
'Laminas\\ServiceManager\\Exception\\ContainerModificationsNotAllowedException' => $vendorDir . '/laminas/laminas-servicemanager/src/Exception/ContainerModificationsNotAllowedException.php',
'Laminas\\ServiceManager\\Exception\\CyclicAliasException' => $vendorDir . '/laminas/laminas-servicemanager/src/Exception/CyclicAliasException.php',
'Laminas\\ServiceManager\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/Exception/ExceptionInterface.php',
'Laminas\\ServiceManager\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-servicemanager/src/Exception/InvalidArgumentException.php',
'Laminas\\ServiceManager\\Exception\\InvalidServiceException' => $vendorDir . '/laminas/laminas-servicemanager/src/Exception/InvalidServiceException.php',
'Laminas\\ServiceManager\\Exception\\ServiceNotCreatedException' => $vendorDir . '/laminas/laminas-servicemanager/src/Exception/ServiceNotCreatedException.php',
'Laminas\\ServiceManager\\Exception\\ServiceNotFoundException' => $vendorDir . '/laminas/laminas-servicemanager/src/Exception/ServiceNotFoundException.php',
'Laminas\\ServiceManager\\FactoryInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/FactoryInterface.php',
'Laminas\\ServiceManager\\Factory\\AbstractFactoryInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/Factory/AbstractFactoryInterface.php',
'Laminas\\ServiceManager\\Factory\\DelegatorFactoryInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/Factory/DelegatorFactoryInterface.php',
'Laminas\\ServiceManager\\Factory\\FactoryInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/Factory/FactoryInterface.php',
'Laminas\\ServiceManager\\Factory\\InvokableFactory' => $vendorDir . '/laminas/laminas-servicemanager/src/Factory/InvokableFactory.php',
'Laminas\\ServiceManager\\InitializerInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/InitializerInterface.php',
'Laminas\\ServiceManager\\Initializer\\InitializerInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/Initializer/InitializerInterface.php',
'Laminas\\ServiceManager\\PluginManagerInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/PluginManagerInterface.php',
'Laminas\\ServiceManager\\Proxy\\LazyServiceFactory' => $vendorDir . '/laminas/laminas-servicemanager/src/Proxy/LazyServiceFactory.php',
'Laminas\\ServiceManager\\PsrContainerDecorator' => $vendorDir . '/laminas/laminas-servicemanager/src/PsrContainerDecorator.php',
'Laminas\\ServiceManager\\ServiceLocatorInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/ServiceLocatorInterface.php',
'Laminas\\ServiceManager\\ServiceManager' => $vendorDir . '/laminas/laminas-servicemanager/src/ServiceManager.php',
'Laminas\\ServiceManager\\Test\\CommonPluginManagerTrait' => $vendorDir . '/laminas/laminas-servicemanager/src/Test/CommonPluginManagerTrait.php',
'Laminas\\ServiceManager\\Tool\\ConfigDumper' => $vendorDir . '/laminas/laminas-servicemanager/src/Tool/ConfigDumper.php',
'Laminas\\ServiceManager\\Tool\\ConfigDumperCommand' => $vendorDir . '/laminas/laminas-servicemanager/src/Tool/ConfigDumperCommand.php',
'Laminas\\ServiceManager\\Tool\\FactoryCreator' => $vendorDir . '/laminas/laminas-servicemanager/src/Tool/FactoryCreator.php',
'Laminas\\ServiceManager\\Tool\\FactoryCreatorCommand' => $vendorDir . '/laminas/laminas-servicemanager/src/Tool/FactoryCreatorCommand.php',
'Laminas\\Stdlib\\AbstractOptions' => $vendorDir . '/laminas/laminas-stdlib/src/AbstractOptions.php',
'Laminas\\Stdlib\\ArrayObject' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayObject.php',
'Laminas\\Stdlib\\ArraySerializableInterface' => $vendorDir . '/laminas/laminas-stdlib/src/ArraySerializableInterface.php',
'Laminas\\Stdlib\\ArrayStack' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayStack.php',
'Laminas\\Stdlib\\ArrayUtils' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayUtils.php',
'Laminas\\Stdlib\\ArrayUtils\\MergeRemoveKey' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayUtils/MergeRemoveKey.php',
'Laminas\\Stdlib\\ArrayUtils\\MergeReplaceKey' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKey.php',
'Laminas\\Stdlib\\ArrayUtils\\MergeReplaceKeyInterface' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKeyInterface.php',
'Laminas\\Stdlib\\ConsoleHelper' => $vendorDir . '/laminas/laminas-stdlib/src/ConsoleHelper.php',
'Laminas\\Stdlib\\DispatchableInterface' => $vendorDir . '/laminas/laminas-stdlib/src/DispatchableInterface.php',
'Laminas\\Stdlib\\ErrorHandler' => $vendorDir . '/laminas/laminas-stdlib/src/ErrorHandler.php',
'Laminas\\Stdlib\\Exception\\BadMethodCallException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/BadMethodCallException.php',
'Laminas\\Stdlib\\Exception\\DomainException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/DomainException.php',
'Laminas\\Stdlib\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/ExceptionInterface.php',
'Laminas\\Stdlib\\Exception\\ExtensionNotLoadedException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/ExtensionNotLoadedException.php',
'Laminas\\Stdlib\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/InvalidArgumentException.php',
'Laminas\\Stdlib\\Exception\\LogicException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/LogicException.php',
'Laminas\\Stdlib\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/RuntimeException.php',
'Laminas\\Stdlib\\FastPriorityQueue' => $vendorDir . '/laminas/laminas-stdlib/src/FastPriorityQueue.php',
'Laminas\\Stdlib\\Glob' => $vendorDir . '/laminas/laminas-stdlib/src/Glob.php',
'Laminas\\Stdlib\\Guard\\AllGuardsTrait' => $vendorDir . '/laminas/laminas-stdlib/src/Guard/AllGuardsTrait.php',
'Laminas\\Stdlib\\Guard\\ArrayOrTraversableGuardTrait' => $vendorDir . '/laminas/laminas-stdlib/src/Guard/ArrayOrTraversableGuardTrait.php',
'Laminas\\Stdlib\\Guard\\EmptyGuardTrait' => $vendorDir . '/laminas/laminas-stdlib/src/Guard/EmptyGuardTrait.php',
'Laminas\\Stdlib\\Guard\\NullGuardTrait' => $vendorDir . '/laminas/laminas-stdlib/src/Guard/NullGuardTrait.php',
'Laminas\\Stdlib\\InitializableInterface' => $vendorDir . '/laminas/laminas-stdlib/src/InitializableInterface.php',
'Laminas\\Stdlib\\JsonSerializable' => $vendorDir . '/laminas/laminas-stdlib/src/JsonSerializable.php',
'Laminas\\Stdlib\\Message' => $vendorDir . '/laminas/laminas-stdlib/src/Message.php',
'Laminas\\Stdlib\\MessageInterface' => $vendorDir . '/laminas/laminas-stdlib/src/MessageInterface.php',
'Laminas\\Stdlib\\ParameterObjectInterface' => $vendorDir . '/laminas/laminas-stdlib/src/ParameterObjectInterface.php',
'Laminas\\Stdlib\\Parameters' => $vendorDir . '/laminas/laminas-stdlib/src/Parameters.php',
'Laminas\\Stdlib\\ParametersInterface' => $vendorDir . '/laminas/laminas-stdlib/src/ParametersInterface.php',
'Laminas\\Stdlib\\PriorityList' => $vendorDir . '/laminas/laminas-stdlib/src/PriorityList.php',
'Laminas\\Stdlib\\PriorityQueue' => $vendorDir . '/laminas/laminas-stdlib/src/PriorityQueue.php',
'Laminas\\Stdlib\\Request' => $vendorDir . '/laminas/laminas-stdlib/src/Request.php',
'Laminas\\Stdlib\\RequestInterface' => $vendorDir . '/laminas/laminas-stdlib/src/RequestInterface.php',
'Laminas\\Stdlib\\Response' => $vendorDir . '/laminas/laminas-stdlib/src/Response.php',
'Laminas\\Stdlib\\ResponseInterface' => $vendorDir . '/laminas/laminas-stdlib/src/ResponseInterface.php',
'Laminas\\Stdlib\\SplPriorityQueue' => $vendorDir . '/laminas/laminas-stdlib/src/SplPriorityQueue.php',
'Laminas\\Stdlib\\SplQueue' => $vendorDir . '/laminas/laminas-stdlib/src/SplQueue.php',
'Laminas\\Stdlib\\SplStack' => $vendorDir . '/laminas/laminas-stdlib/src/SplStack.php',
'Laminas\\Stdlib\\StringUtils' => $vendorDir . '/laminas/laminas-stdlib/src/StringUtils.php',
'Laminas\\Stdlib\\StringWrapper\\AbstractStringWrapper' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/AbstractStringWrapper.php',
'Laminas\\Stdlib\\StringWrapper\\Iconv' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/Iconv.php',
'Laminas\\Stdlib\\StringWrapper\\Intl' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/Intl.php',
'Laminas\\Stdlib\\StringWrapper\\MbString' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/MbString.php',
'Laminas\\Stdlib\\StringWrapper\\Native' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/Native.php',
'Laminas\\Stdlib\\StringWrapper\\StringWrapperInterface' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/StringWrapperInterface.php',
'Laminas\\Validator\\AbstractValidator' => $vendorDir . '/laminas/laminas-validator/src/AbstractValidator.php',
'Laminas\\Validator\\Barcode' => $vendorDir . '/laminas/laminas-validator/src/Barcode.php',
'Laminas\\Validator\\Barcode\\AbstractAdapter' => $vendorDir . '/laminas/laminas-validator/src/Barcode/AbstractAdapter.php',
'Laminas\\Validator\\Barcode\\AdapterInterface' => $vendorDir . '/laminas/laminas-validator/src/Barcode/AdapterInterface.php',
'Laminas\\Validator\\Barcode\\Codabar' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Codabar.php',
'Laminas\\Validator\\Barcode\\Code128' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Code128.php',
'Laminas\\Validator\\Barcode\\Code25' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Code25.php',
'Laminas\\Validator\\Barcode\\Code25interleaved' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Code25interleaved.php',
'Laminas\\Validator\\Barcode\\Code39' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Code39.php',
'Laminas\\Validator\\Barcode\\Code39ext' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Code39ext.php',
'Laminas\\Validator\\Barcode\\Code93' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Code93.php',
'Laminas\\Validator\\Barcode\\Code93ext' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Code93ext.php',
'Laminas\\Validator\\Barcode\\Ean12' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Ean12.php',
'Laminas\\Validator\\Barcode\\Ean13' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Ean13.php',
'Laminas\\Validator\\Barcode\\Ean14' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Ean14.php',
'Laminas\\Validator\\Barcode\\Ean18' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Ean18.php',
'Laminas\\Validator\\Barcode\\Ean2' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Ean2.php',
'Laminas\\Validator\\Barcode\\Ean5' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Ean5.php',
'Laminas\\Validator\\Barcode\\Ean8' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Ean8.php',
'Laminas\\Validator\\Barcode\\Gtin12' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Gtin12.php',
'Laminas\\Validator\\Barcode\\Gtin13' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Gtin13.php',
'Laminas\\Validator\\Barcode\\Gtin14' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Gtin14.php',
'Laminas\\Validator\\Barcode\\Identcode' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Identcode.php',
'Laminas\\Validator\\Barcode\\Intelligentmail' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Intelligentmail.php',
'Laminas\\Validator\\Barcode\\Issn' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Issn.php',
'Laminas\\Validator\\Barcode\\Itf14' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Itf14.php',
'Laminas\\Validator\\Barcode\\Leitcode' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Leitcode.php',
'Laminas\\Validator\\Barcode\\Planet' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Planet.php',
'Laminas\\Validator\\Barcode\\Postnet' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Postnet.php',
'Laminas\\Validator\\Barcode\\Royalmail' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Royalmail.php',
'Laminas\\Validator\\Barcode\\Sscc' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Sscc.php',
'Laminas\\Validator\\Barcode\\Upca' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Upca.php',
'Laminas\\Validator\\Barcode\\Upce' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Upce.php',
'Laminas\\Validator\\Between' => $vendorDir . '/laminas/laminas-validator/src/Between.php',
'Laminas\\Validator\\Bitwise' => $vendorDir . '/laminas/laminas-validator/src/Bitwise.php',
'Laminas\\Validator\\Callback' => $vendorDir . '/laminas/laminas-validator/src/Callback.php',
'Laminas\\Validator\\ConfigProvider' => $vendorDir . '/laminas/laminas-validator/src/ConfigProvider.php',
'Laminas\\Validator\\CreditCard' => $vendorDir . '/laminas/laminas-validator/src/CreditCard.php',
'Laminas\\Validator\\Csrf' => $vendorDir . '/laminas/laminas-validator/src/Csrf.php',
'Laminas\\Validator\\Date' => $vendorDir . '/laminas/laminas-validator/src/Date.php',
'Laminas\\Validator\\DateStep' => $vendorDir . '/laminas/laminas-validator/src/DateStep.php',
'Laminas\\Validator\\Db\\AbstractDb' => $vendorDir . '/laminas/laminas-validator/src/Db/AbstractDb.php',
'Laminas\\Validator\\Db\\NoRecordExists' => $vendorDir . '/laminas/laminas-validator/src/Db/NoRecordExists.php',
'Laminas\\Validator\\Db\\RecordExists' => $vendorDir . '/laminas/laminas-validator/src/Db/RecordExists.php',
'Laminas\\Validator\\Digits' => $vendorDir . '/laminas/laminas-validator/src/Digits.php',
'Laminas\\Validator\\EmailAddress' => $vendorDir . '/laminas/laminas-validator/src/EmailAddress.php',
'Laminas\\Validator\\Exception\\BadMethodCallException' => $vendorDir . '/laminas/laminas-validator/src/Exception/BadMethodCallException.php',
'Laminas\\Validator\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-validator/src/Exception/ExceptionInterface.php',
'Laminas\\Validator\\Exception\\ExtensionNotLoadedException' => $vendorDir . '/laminas/laminas-validator/src/Exception/ExtensionNotLoadedException.php',
'Laminas\\Validator\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-validator/src/Exception/InvalidArgumentException.php',
'Laminas\\Validator\\Exception\\InvalidMagicMimeFileException' => $vendorDir . '/laminas/laminas-validator/src/Exception/InvalidMagicMimeFileException.php',
'Laminas\\Validator\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-validator/src/Exception/RuntimeException.php',
'Laminas\\Validator\\Explode' => $vendorDir . '/laminas/laminas-validator/src/Explode.php',
'Laminas\\Validator\\File\\Count' => $vendorDir . '/laminas/laminas-validator/src/File/Count.php',
'Laminas\\Validator\\File\\Crc32' => $vendorDir . '/laminas/laminas-validator/src/File/Crc32.php',
'Laminas\\Validator\\File\\ExcludeExtension' => $vendorDir . '/laminas/laminas-validator/src/File/ExcludeExtension.php',
'Laminas\\Validator\\File\\ExcludeMimeType' => $vendorDir . '/laminas/laminas-validator/src/File/ExcludeMimeType.php',
'Laminas\\Validator\\File\\Exists' => $vendorDir . '/laminas/laminas-validator/src/File/Exists.php',
'Laminas\\Validator\\File\\Extension' => $vendorDir . '/laminas/laminas-validator/src/File/Extension.php',
'Laminas\\Validator\\File\\FileInformationTrait' => $vendorDir . '/laminas/laminas-validator/src/File/FileInformationTrait.php',
'Laminas\\Validator\\File\\FilesSize' => $vendorDir . '/laminas/laminas-validator/src/File/FilesSize.php',
'Laminas\\Validator\\File\\Hash' => $vendorDir . '/laminas/laminas-validator/src/File/Hash.php',
'Laminas\\Validator\\File\\ImageSize' => $vendorDir . '/laminas/laminas-validator/src/File/ImageSize.php',
'Laminas\\Validator\\File\\IsCompressed' => $vendorDir . '/laminas/laminas-validator/src/File/IsCompressed.php',
'Laminas\\Validator\\File\\IsImage' => $vendorDir . '/laminas/laminas-validator/src/File/IsImage.php',
'Laminas\\Validator\\File\\Md5' => $vendorDir . '/laminas/laminas-validator/src/File/Md5.php',
'Laminas\\Validator\\File\\MimeType' => $vendorDir . '/laminas/laminas-validator/src/File/MimeType.php',
'Laminas\\Validator\\File\\NotExists' => $vendorDir . '/laminas/laminas-validator/src/File/NotExists.php',
'Laminas\\Validator\\File\\Sha1' => $vendorDir . '/laminas/laminas-validator/src/File/Sha1.php',
'Laminas\\Validator\\File\\Size' => $vendorDir . '/laminas/laminas-validator/src/File/Size.php',
'Laminas\\Validator\\File\\Upload' => $vendorDir . '/laminas/laminas-validator/src/File/Upload.php',
'Laminas\\Validator\\File\\UploadFile' => $vendorDir . '/laminas/laminas-validator/src/File/UploadFile.php',
'Laminas\\Validator\\File\\WordCount' => $vendorDir . '/laminas/laminas-validator/src/File/WordCount.php',
'Laminas\\Validator\\GpsPoint' => $vendorDir . '/laminas/laminas-validator/src/GpsPoint.php',
'Laminas\\Validator\\GreaterThan' => $vendorDir . '/laminas/laminas-validator/src/GreaterThan.php',
'Laminas\\Validator\\Hex' => $vendorDir . '/laminas/laminas-validator/src/Hex.php',
'Laminas\\Validator\\Hostname' => $vendorDir . '/laminas/laminas-validator/src/Hostname.php',
'Laminas\\Validator\\Iban' => $vendorDir . '/laminas/laminas-validator/src/Iban.php',
'Laminas\\Validator\\Identical' => $vendorDir . '/laminas/laminas-validator/src/Identical.php',
'Laminas\\Validator\\InArray' => $vendorDir . '/laminas/laminas-validator/src/InArray.php',
'Laminas\\Validator\\Ip' => $vendorDir . '/laminas/laminas-validator/src/Ip.php',
'Laminas\\Validator\\IsCountable' => $vendorDir . '/laminas/laminas-validator/src/IsCountable.php',
'Laminas\\Validator\\IsInstanceOf' => $vendorDir . '/laminas/laminas-validator/src/IsInstanceOf.php',
'Laminas\\Validator\\Isbn' => $vendorDir . '/laminas/laminas-validator/src/Isbn.php',
'Laminas\\Validator\\Isbn\\Isbn10' => $vendorDir . '/laminas/laminas-validator/src/Isbn/Isbn10.php',
'Laminas\\Validator\\Isbn\\Isbn13' => $vendorDir . '/laminas/laminas-validator/src/Isbn/Isbn13.php',
'Laminas\\Validator\\LessThan' => $vendorDir . '/laminas/laminas-validator/src/LessThan.php',
'Laminas\\Validator\\Module' => $vendorDir . '/laminas/laminas-validator/src/Module.php',
'Laminas\\Validator\\NotEmpty' => $vendorDir . '/laminas/laminas-validator/src/NotEmpty.php',
'Laminas\\Validator\\Regex' => $vendorDir . '/laminas/laminas-validator/src/Regex.php',
'Laminas\\Validator\\Sitemap\\Changefreq' => $vendorDir . '/laminas/laminas-validator/src/Sitemap/Changefreq.php',
'Laminas\\Validator\\Sitemap\\Lastmod' => $vendorDir . '/laminas/laminas-validator/src/Sitemap/Lastmod.php',
'Laminas\\Validator\\Sitemap\\Loc' => $vendorDir . '/laminas/laminas-validator/src/Sitemap/Loc.php',
'Laminas\\Validator\\Sitemap\\Priority' => $vendorDir . '/laminas/laminas-validator/src/Sitemap/Priority.php',
'Laminas\\Validator\\StaticValidator' => $vendorDir . '/laminas/laminas-validator/src/StaticValidator.php',
'Laminas\\Validator\\Step' => $vendorDir . '/laminas/laminas-validator/src/Step.php',
'Laminas\\Validator\\StringLength' => $vendorDir . '/laminas/laminas-validator/src/StringLength.php',
'Laminas\\Validator\\Timezone' => $vendorDir . '/laminas/laminas-validator/src/Timezone.php',
'Laminas\\Validator\\Translator\\TranslatorAwareInterface' => $vendorDir . '/laminas/laminas-validator/src/Translator/TranslatorAwareInterface.php',
'Laminas\\Validator\\Translator\\TranslatorInterface' => $vendorDir . '/laminas/laminas-validator/src/Translator/TranslatorInterface.php',
'Laminas\\Validator\\UndisclosedPassword' => $vendorDir . '/laminas/laminas-validator/src/UndisclosedPassword.php',
'Laminas\\Validator\\Uri' => $vendorDir . '/laminas/laminas-validator/src/Uri.php',
'Laminas\\Validator\\Uuid' => $vendorDir . '/laminas/laminas-validator/src/Uuid.php',
'Laminas\\Validator\\ValidatorChain' => $vendorDir . '/laminas/laminas-validator/src/ValidatorChain.php',
'Laminas\\Validator\\ValidatorInterface' => $vendorDir . '/laminas/laminas-validator/src/ValidatorInterface.php',
'Laminas\\Validator\\ValidatorPluginManager' => $vendorDir . '/laminas/laminas-validator/src/ValidatorPluginManager.php',
'Laminas\\Validator\\ValidatorPluginManagerAwareInterface' => $vendorDir . '/laminas/laminas-validator/src/ValidatorPluginManagerAwareInterface.php',
'Laminas\\Validator\\ValidatorPluginManagerFactory' => $vendorDir . '/laminas/laminas-validator/src/ValidatorPluginManagerFactory.php',
'Laminas\\Validator\\ValidatorProviderInterface' => $vendorDir . '/laminas/laminas-validator/src/ValidatorProviderInterface.php',
'Laminas\\ZendFrameworkBridge\\Autoloader' => $vendorDir . '/laminas/laminas-zendframework-bridge/src/Autoloader.php',
'Laminas\\ZendFrameworkBridge\\ConfigPostProcessor' => $vendorDir . '/laminas/laminas-zendframework-bridge/src/ConfigPostProcessor.php',
'Laminas\\ZendFrameworkBridge\\Module' => $vendorDir . '/laminas/laminas-zendframework-bridge/src/Module.php',
'Laminas\\ZendFrameworkBridge\\Replacements' => $vendorDir . '/laminas/laminas-zendframework-bridge/src/Replacements.php',
'Laminas\\ZendFrameworkBridge\\RewriteRules' => $vendorDir . '/laminas/laminas-zendframework-bridge/src/RewriteRules.php',
'ListExpression' => $baseDir . '/core/oql/expression.class.inc.php',
'ListOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php',
'LogAPI' => $baseDir . '/core/log.class.inc.php',
@@ -930,8 +1249,6 @@ return array(
'StimulusInternal' => $baseDir . '/core/stimulus.class.inc.php',
'StimulusUserAction' => $baseDir . '/core/stimulus.class.inc.php',
'Str' => $baseDir . '/core/MyHelpers.class.inc.php',
'Swift_LogFileTransport' => $baseDir . '/core/email.class.inc.php',
'Swift_Transport_LogFileTransport' => $baseDir . '/core/email.class.inc.php',
'Symfony\\Bridge\\Twig\\AppVariable' => $vendorDir . '/symfony/twig-bridge/AppVariable.php',
'Symfony\\Bridge\\Twig\\Command\\DebugCommand' => $vendorDir . '/symfony/twig-bridge/Command/DebugCommand.php',
'Symfony\\Bridge\\Twig\\Command\\LintCommand' => $vendorDir . '/symfony/twig-bridge/Command/LintCommand.php',
@@ -1086,9 +1403,6 @@ return array(
'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateNameParser' => $vendorDir . '/symfony/framework-bundle/Templating/TemplateNameParser.php',
'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateReference' => $vendorDir . '/symfony/framework-bundle/Templating/TemplateReference.php',
'Symfony\\Bundle\\FrameworkBundle\\Templating\\TimedPhpEngine' => $vendorDir . '/symfony/framework-bundle/Templating/TimedPhpEngine.php',
'Symfony\\Bundle\\FrameworkBundle\\Test\\ForwardCompatTestTrait' => $vendorDir . '/symfony/framework-bundle/Test/ForwardCompatTestTrait.php',
'Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase' => $vendorDir . '/symfony/framework-bundle/Test/KernelTestCase.php',
'Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestCase' => $vendorDir . '/symfony/framework-bundle/Test/WebTestCase.php',
'Symfony\\Bundle\\FrameworkBundle\\Translation\\PhpExtractor' => $vendorDir . '/symfony/framework-bundle/Translation/PhpExtractor.php',
'Symfony\\Bundle\\FrameworkBundle\\Translation\\PhpStringTokenParser' => $vendorDir . '/symfony/framework-bundle/Translation/PhpStringTokenParser.php',
'Symfony\\Bundle\\FrameworkBundle\\Translation\\TranslationLoader' => $vendorDir . '/symfony/framework-bundle/Translation/TranslationLoader.php',
@@ -1893,7 +2207,6 @@ return array(
'Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface' => $vendorDir . '/symfony/var-dumper/Dumper/DataDumperInterface.php',
'Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper' => $vendorDir . '/symfony/var-dumper/Dumper/HtmlDumper.php',
'Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException' => $vendorDir . '/symfony/var-dumper/Exception/ThrowingCasterException.php',
'Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait' => $vendorDir . '/symfony/var-dumper/Test/VarDumperTestTrait.php',
'Symfony\\Component\\VarDumper\\VarDumper' => $vendorDir . '/symfony/var-dumper/VarDumper.php',
'Symfony\\Component\\Yaml\\Command\\LintCommand' => $vendorDir . '/symfony/yaml/Command/LintCommand.php',
'Symfony\\Component\\Yaml\\Dumper' => $vendorDir . '/symfony/yaml/Dumper.php',
@@ -1953,6 +2266,10 @@ return array(
'TriggerOnStateEnter' => $baseDir . '/core/trigger.class.inc.php',
'TriggerOnStateLeave' => $baseDir . '/core/trigger.class.inc.php',
'TriggerOnThresholdReached' => $baseDir . '/core/trigger.class.inc.php',
'TrueBV\\Exception\\DomainOutOfBoundsException' => $vendorDir . '/true/punycode/src/Exception/DomainOutOfBoundsException.php',
'TrueBV\\Exception\\LabelOutOfBoundsException' => $vendorDir . '/true/punycode/src/Exception/LabelOutOfBoundsException.php',
'TrueBV\\Exception\\OutOfBoundsException' => $vendorDir . '/true/punycode/src/Exception/OutOfBoundsException.php',
'TrueBV\\Punycode' => $vendorDir . '/true/punycode/src/Punycode.php',
'TrueExpression' => $baseDir . '/core/oql/expression.class.inc.php',
'Twig\\Cache\\CacheInterface' => $vendorDir . '/twig/twig/src/Cache/CacheInterface.php',
'Twig\\Cache\\FilesystemCache' => $vendorDir . '/twig/twig/src/Cache/FilesystemCache.php',

View File

@@ -6,12 +6,12 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
'023d27dca8066ef29e6739335ea73bad' => $vendorDir . '/symfony/polyfill-php70/bootstrap.php',
'32dcc8afd4335739640db7d200c1971d' => $vendorDir . '/symfony/polyfill-apcu/bootstrap.php',
'bd9634f2d41831496de0d3dfe4c94881' => $vendorDir . '/symfony/polyfill-php56/bootstrap.php',
'7e9bd612cc444b3eed788ebbe46263a0' => $vendorDir . '/laminas/laminas-zendframework-bridge/src/autoload.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
'2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php',
);

View File

@@ -7,6 +7,7 @@ $baseDir = dirname($vendorDir);
return array(
'Twig\\' => array($vendorDir . '/twig/twig/src'),
'TrueBV\\' => array($vendorDir . '/true/punycode/src'),
'Symfony\\Polyfill\\Util\\' => array($vendorDir . '/symfony/polyfill-util'),
'Symfony\\Polyfill\\Php70\\' => array($vendorDir . '/symfony/polyfill-php70'),
'Symfony\\Polyfill\\Php56\\' => array($vendorDir . '/symfony/polyfill-php56'),
@@ -41,4 +42,12 @@ return array(
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
'Pelago\\' => array($vendorDir . '/pelago/emogrifier/src'),
'Laminas\\ZendFrameworkBridge\\' => array($vendorDir . '/laminas/laminas-zendframework-bridge/src'),
'Laminas\\Validator\\' => array($vendorDir . '/laminas/laminas-validator/src'),
'Laminas\\Stdlib\\' => array($vendorDir . '/laminas/laminas-stdlib/src'),
'Laminas\\ServiceManager\\' => array($vendorDir . '/laminas/laminas-servicemanager/src'),
'Laminas\\Mime\\' => array($vendorDir . '/laminas/laminas-mime/src'),
'Laminas\\Mail\\' => array($vendorDir . '/laminas/laminas-mail/src'),
'Laminas\\Loader\\' => array($vendorDir . '/laminas/laminas-loader/src'),
'Interop\\Container\\' => array($vendorDir . '/container-interop/container-interop/src/Interop/Container'),
);

View File

@@ -60,11 +60,16 @@ class ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b
}
}
/**
* @param string $fileIdentifier
* @param string $file
* @return void
*/
function composerRequire0018331147de7601e7552f7da8e3bb8b($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
require $file;
}
}

View File

@@ -7,20 +7,21 @@ namespace Composer\Autoload;
class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
{
public static $files = array (
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php',
'023d27dca8066ef29e6739335ea73bad' => __DIR__ . '/..' . '/symfony/polyfill-php70/bootstrap.php',
'32dcc8afd4335739640db7d200c1971d' => __DIR__ . '/..' . '/symfony/polyfill-apcu/bootstrap.php',
'bd9634f2d41831496de0d3dfe4c94881' => __DIR__ . '/..' . '/symfony/polyfill-php56/bootstrap.php',
'7e9bd612cc444b3eed788ebbe46263a0' => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src/autoload.php',
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
'2c102faa651ef8ea5874edb585946bce' => __DIR__ . '/..' . '/swiftmailer/swiftmailer/lib/swift_required.php',
);
public static $prefixLengthsPsr4 = array (
'T' =>
array (
'Twig\\' => 5,
'TrueBV\\' => 7,
),
'S' =>
array (
@@ -62,6 +63,20 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
'PhpParser\\' => 10,
'Pelago\\' => 7,
),
'L' =>
array (
'Laminas\\ZendFrameworkBridge\\' => 28,
'Laminas\\Validator\\' => 18,
'Laminas\\Stdlib\\' => 15,
'Laminas\\ServiceManager\\' => 23,
'Laminas\\Mime\\' => 13,
'Laminas\\Mail\\' => 13,
'Laminas\\Loader\\' => 15,
),
'I' =>
array (
'Interop\\Container\\' => 18,
),
);
public static $prefixDirsPsr4 = array (
@@ -69,6 +84,10 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
array (
0 => __DIR__ . '/..' . '/twig/twig/src',
),
'TrueBV\\' =>
array (
0 => __DIR__ . '/..' . '/true/punycode/src',
),
'Symfony\\Polyfill\\Util\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-util',
@@ -205,6 +224,38 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
array (
0 => __DIR__ . '/..' . '/pelago/emogrifier/src',
),
'Laminas\\ZendFrameworkBridge\\' =>
array (
0 => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src',
),
'Laminas\\Validator\\' =>
array (
0 => __DIR__ . '/..' . '/laminas/laminas-validator/src',
),
'Laminas\\Stdlib\\' =>
array (
0 => __DIR__ . '/..' . '/laminas/laminas-stdlib/src',
),
'Laminas\\ServiceManager\\' =>
array (
0 => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src',
),
'Laminas\\Mime\\' =>
array (
0 => __DIR__ . '/..' . '/laminas/laminas-mime/src',
),
'Laminas\\Mail\\' =>
array (
0 => __DIR__ . '/..' . '/laminas/laminas-mail/src',
),
'Laminas\\Loader\\' =>
array (
0 => __DIR__ . '/..' . '/laminas/laminas-loader/src',
),
'Interop\\Container\\' =>
array (
0 => __DIR__ . '/..' . '/container-interop/container-interop/src/Interop/Container',
),
);
public static $prefixesPsr0 = array (
@@ -717,6 +768,9 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
'InlineImage' => __DIR__ . '/../..' . '/core/inlineimage.class.inc.php',
'InlineImageGC' => __DIR__ . '/../..' . '/core/inlineimage.class.inc.php',
'InputOutputTask' => __DIR__ . '/../..' . '/application/iotask.class.inc.php',
'Interop\\Container\\ContainerInterface' => __DIR__ . '/..' . '/container-interop/container-interop/src/Interop/Container/ContainerInterface.php',
'Interop\\Container\\Exception\\ContainerException' => __DIR__ . '/..' . '/container-interop/container-interop/src/Interop/Container/Exception/ContainerException.php',
'Interop\\Container\\Exception\\NotFoundException' => __DIR__ . '/..' . '/container-interop/container-interop/src/Interop/Container/Exception/NotFoundException.php',
'IntervalExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php',
'IntervalOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php',
'Introspection' => __DIR__ . '/../..' . '/core/introspection.class.inc.php',
@@ -728,6 +782,322 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
'JSPopupMenuItem' => __DIR__ . '/../..' . '/application/applicationextension.inc.php',
'JsonPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/JsonPage.php',
'KeyValueStore' => __DIR__ . '/../..' . '/core/counter.class.inc.php',
'Laminas\\Loader\\AutoloaderFactory' => __DIR__ . '/..' . '/laminas/laminas-loader/src/AutoloaderFactory.php',
'Laminas\\Loader\\ClassMapAutoloader' => __DIR__ . '/..' . '/laminas/laminas-loader/src/ClassMapAutoloader.php',
'Laminas\\Loader\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/BadMethodCallException.php',
'Laminas\\Loader\\Exception\\DomainException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/DomainException.php',
'Laminas\\Loader\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/ExceptionInterface.php',
'Laminas\\Loader\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/InvalidArgumentException.php',
'Laminas\\Loader\\Exception\\InvalidPathException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/InvalidPathException.php',
'Laminas\\Loader\\Exception\\MissingResourceNamespaceException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/MissingResourceNamespaceException.php',
'Laminas\\Loader\\Exception\\PluginLoaderException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/PluginLoaderException.php',
'Laminas\\Loader\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/RuntimeException.php',
'Laminas\\Loader\\Exception\\SecurityException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/SecurityException.php',
'Laminas\\Loader\\ModuleAutoloader' => __DIR__ . '/..' . '/laminas/laminas-loader/src/ModuleAutoloader.php',
'Laminas\\Loader\\PluginClassLoader' => __DIR__ . '/..' . '/laminas/laminas-loader/src/PluginClassLoader.php',
'Laminas\\Loader\\PluginClassLocator' => __DIR__ . '/..' . '/laminas/laminas-loader/src/PluginClassLocator.php',
'Laminas\\Loader\\ShortNameLocator' => __DIR__ . '/..' . '/laminas/laminas-loader/src/ShortNameLocator.php',
'Laminas\\Loader\\SplAutoloader' => __DIR__ . '/..' . '/laminas/laminas-loader/src/SplAutoloader.php',
'Laminas\\Loader\\StandardAutoloader' => __DIR__ . '/..' . '/laminas/laminas-loader/src/StandardAutoloader.php',
'Laminas\\Mail\\Address' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Address.php',
'Laminas\\Mail\\AddressList' => __DIR__ . '/..' . '/laminas/laminas-mail/src/AddressList.php',
'Laminas\\Mail\\Address\\AddressInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Address/AddressInterface.php',
'Laminas\\Mail\\ConfigProvider' => __DIR__ . '/..' . '/laminas/laminas-mail/src/ConfigProvider.php',
'Laminas\\Mail\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Exception/BadMethodCallException.php',
'Laminas\\Mail\\Exception\\DomainException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Exception/DomainException.php',
'Laminas\\Mail\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Exception/ExceptionInterface.php',
'Laminas\\Mail\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Exception/InvalidArgumentException.php',
'Laminas\\Mail\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Exception/OutOfBoundsException.php',
'Laminas\\Mail\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Exception/RuntimeException.php',
'Laminas\\Mail\\Header\\AbstractAddressList' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/AbstractAddressList.php',
'Laminas\\Mail\\Header\\Bcc' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Bcc.php',
'Laminas\\Mail\\Header\\Cc' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Cc.php',
'Laminas\\Mail\\Header\\ContentDisposition' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/ContentDisposition.php',
'Laminas\\Mail\\Header\\ContentTransferEncoding' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/ContentTransferEncoding.php',
'Laminas\\Mail\\Header\\ContentType' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/ContentType.php',
'Laminas\\Mail\\Header\\Date' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Date.php',
'Laminas\\Mail\\Header\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Exception/BadMethodCallException.php',
'Laminas\\Mail\\Header\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Exception/ExceptionInterface.php',
'Laminas\\Mail\\Header\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Exception/InvalidArgumentException.php',
'Laminas\\Mail\\Header\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Exception/RuntimeException.php',
'Laminas\\Mail\\Header\\From' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/From.php',
'Laminas\\Mail\\Header\\GenericHeader' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/GenericHeader.php',
'Laminas\\Mail\\Header\\GenericMultiHeader' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/GenericMultiHeader.php',
'Laminas\\Mail\\Header\\HeaderInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/HeaderInterface.php',
'Laminas\\Mail\\Header\\HeaderLoader' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/HeaderLoader.php',
'Laminas\\Mail\\Header\\HeaderLocator' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/HeaderLocator.php',
'Laminas\\Mail\\Header\\HeaderLocatorInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/HeaderLocatorInterface.php',
'Laminas\\Mail\\Header\\HeaderName' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/HeaderName.php',
'Laminas\\Mail\\Header\\HeaderValue' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/HeaderValue.php',
'Laminas\\Mail\\Header\\HeaderWrap' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/HeaderWrap.php',
'Laminas\\Mail\\Header\\IdentificationField' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/IdentificationField.php',
'Laminas\\Mail\\Header\\InReplyTo' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/InReplyTo.php',
'Laminas\\Mail\\Header\\ListParser' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/ListParser.php',
'Laminas\\Mail\\Header\\MessageId' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/MessageId.php',
'Laminas\\Mail\\Header\\MimeVersion' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/MimeVersion.php',
'Laminas\\Mail\\Header\\MultipleHeadersInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/MultipleHeadersInterface.php',
'Laminas\\Mail\\Header\\Received' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Received.php',
'Laminas\\Mail\\Header\\References' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/References.php',
'Laminas\\Mail\\Header\\ReplyTo' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/ReplyTo.php',
'Laminas\\Mail\\Header\\Sender' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Sender.php',
'Laminas\\Mail\\Header\\StructuredInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/StructuredInterface.php',
'Laminas\\Mail\\Header\\Subject' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Subject.php',
'Laminas\\Mail\\Header\\To' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/To.php',
'Laminas\\Mail\\Header\\UnstructuredInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/UnstructuredInterface.php',
'Laminas\\Mail\\Headers' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Headers.php',
'Laminas\\Mail\\Message' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Message.php',
'Laminas\\Mail\\MessageFactory' => __DIR__ . '/..' . '/laminas/laminas-mail/src/MessageFactory.php',
'Laminas\\Mail\\Module' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Module.php',
'Laminas\\Mail\\Protocol\\AbstractProtocol' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/AbstractProtocol.php',
'Laminas\\Mail\\Protocol\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Exception/ExceptionInterface.php',
'Laminas\\Mail\\Protocol\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Exception/InvalidArgumentException.php',
'Laminas\\Mail\\Protocol\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Exception/RuntimeException.php',
'Laminas\\Mail\\Protocol\\Imap' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Imap.php',
'Laminas\\Mail\\Protocol\\Pop3' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Pop3.php',
'Laminas\\Mail\\Protocol\\ProtocolTrait' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/ProtocolTrait.php',
'Laminas\\Mail\\Protocol\\Smtp' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Smtp.php',
'Laminas\\Mail\\Protocol\\SmtpPluginManager' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/SmtpPluginManager.php',
'Laminas\\Mail\\Protocol\\SmtpPluginManagerFactory' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/SmtpPluginManagerFactory.php',
'Laminas\\Mail\\Protocol\\Smtp\\Auth\\Crammd5' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Smtp/Auth/Crammd5.php',
'Laminas\\Mail\\Protocol\\Smtp\\Auth\\Login' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Smtp/Auth/Login.php',
'Laminas\\Mail\\Protocol\\Smtp\\Auth\\Plain' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Smtp/Auth/Plain.php',
'Laminas\\Mail\\Storage' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage.php',
'Laminas\\Mail\\Storage\\AbstractStorage' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/AbstractStorage.php',
'Laminas\\Mail\\Storage\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Exception/ExceptionInterface.php',
'Laminas\\Mail\\Storage\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Exception/InvalidArgumentException.php',
'Laminas\\Mail\\Storage\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Exception/OutOfBoundsException.php',
'Laminas\\Mail\\Storage\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Exception/RuntimeException.php',
'Laminas\\Mail\\Storage\\Folder' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Folder.php',
'Laminas\\Mail\\Storage\\Folder\\FolderInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Folder/FolderInterface.php',
'Laminas\\Mail\\Storage\\Folder\\Maildir' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Folder/Maildir.php',
'Laminas\\Mail\\Storage\\Folder\\Mbox' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Folder/Mbox.php',
'Laminas\\Mail\\Storage\\Imap' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Imap.php',
'Laminas\\Mail\\Storage\\Maildir' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Maildir.php',
'Laminas\\Mail\\Storage\\Mbox' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Mbox.php',
'Laminas\\Mail\\Storage\\Message' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Message.php',
'Laminas\\Mail\\Storage\\Message\\File' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Message/File.php',
'Laminas\\Mail\\Storage\\Message\\MessageInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Message/MessageInterface.php',
'Laminas\\Mail\\Storage\\Part' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Part.php',
'Laminas\\Mail\\Storage\\Part\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Part/Exception/ExceptionInterface.php',
'Laminas\\Mail\\Storage\\Part\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Part/Exception/InvalidArgumentException.php',
'Laminas\\Mail\\Storage\\Part\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Part/Exception/RuntimeException.php',
'Laminas\\Mail\\Storage\\Part\\File' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Part/File.php',
'Laminas\\Mail\\Storage\\Part\\PartInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Part/PartInterface.php',
'Laminas\\Mail\\Storage\\Pop3' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Pop3.php',
'Laminas\\Mail\\Storage\\Writable\\Maildir' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Writable/Maildir.php',
'Laminas\\Mail\\Storage\\Writable\\WritableInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Writable/WritableInterface.php',
'Laminas\\Mail\\Transport\\Envelope' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Envelope.php',
'Laminas\\Mail\\Transport\\Exception\\DomainException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Exception/DomainException.php',
'Laminas\\Mail\\Transport\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Exception/ExceptionInterface.php',
'Laminas\\Mail\\Transport\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Exception/InvalidArgumentException.php',
'Laminas\\Mail\\Transport\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Exception/RuntimeException.php',
'Laminas\\Mail\\Transport\\Factory' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Factory.php',
'Laminas\\Mail\\Transport\\File' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/File.php',
'Laminas\\Mail\\Transport\\FileOptions' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/FileOptions.php',
'Laminas\\Mail\\Transport\\InMemory' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/InMemory.php',
'Laminas\\Mail\\Transport\\Sendmail' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Sendmail.php',
'Laminas\\Mail\\Transport\\Smtp' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Smtp.php',
'Laminas\\Mail\\Transport\\SmtpOptions' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/SmtpOptions.php',
'Laminas\\Mail\\Transport\\TransportInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/TransportInterface.php',
'Laminas\\Mime\\Decode' => __DIR__ . '/..' . '/laminas/laminas-mime/src/Decode.php',
'Laminas\\Mime\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-mime/src/Exception/ExceptionInterface.php',
'Laminas\\Mime\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-mime/src/Exception/InvalidArgumentException.php',
'Laminas\\Mime\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-mime/src/Exception/RuntimeException.php',
'Laminas\\Mime\\Message' => __DIR__ . '/..' . '/laminas/laminas-mime/src/Message.php',
'Laminas\\Mime\\Mime' => __DIR__ . '/..' . '/laminas/laminas-mime/src/Mime.php',
'Laminas\\Mime\\Part' => __DIR__ . '/..' . '/laminas/laminas-mime/src/Part.php',
'Laminas\\ServiceManager\\AbstractFactoryInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/AbstractFactoryInterface.php',
'Laminas\\ServiceManager\\AbstractFactory\\ConfigAbstractFactory' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/AbstractFactory/ConfigAbstractFactory.php',
'Laminas\\ServiceManager\\AbstractFactory\\ReflectionBasedAbstractFactory' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/AbstractFactory/ReflectionBasedAbstractFactory.php',
'Laminas\\ServiceManager\\AbstractPluginManager' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/AbstractPluginManager.php',
'Laminas\\ServiceManager\\Config' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Config.php',
'Laminas\\ServiceManager\\ConfigInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/ConfigInterface.php',
'Laminas\\ServiceManager\\DelegatorFactoryInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/DelegatorFactoryInterface.php',
'Laminas\\ServiceManager\\Exception\\ContainerModificationsNotAllowedException' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Exception/ContainerModificationsNotAllowedException.php',
'Laminas\\ServiceManager\\Exception\\CyclicAliasException' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Exception/CyclicAliasException.php',
'Laminas\\ServiceManager\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Exception/ExceptionInterface.php',
'Laminas\\ServiceManager\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Exception/InvalidArgumentException.php',
'Laminas\\ServiceManager\\Exception\\InvalidServiceException' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Exception/InvalidServiceException.php',
'Laminas\\ServiceManager\\Exception\\ServiceNotCreatedException' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Exception/ServiceNotCreatedException.php',
'Laminas\\ServiceManager\\Exception\\ServiceNotFoundException' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Exception/ServiceNotFoundException.php',
'Laminas\\ServiceManager\\FactoryInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/FactoryInterface.php',
'Laminas\\ServiceManager\\Factory\\AbstractFactoryInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Factory/AbstractFactoryInterface.php',
'Laminas\\ServiceManager\\Factory\\DelegatorFactoryInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Factory/DelegatorFactoryInterface.php',
'Laminas\\ServiceManager\\Factory\\FactoryInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Factory/FactoryInterface.php',
'Laminas\\ServiceManager\\Factory\\InvokableFactory' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Factory/InvokableFactory.php',
'Laminas\\ServiceManager\\InitializerInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/InitializerInterface.php',
'Laminas\\ServiceManager\\Initializer\\InitializerInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Initializer/InitializerInterface.php',
'Laminas\\ServiceManager\\PluginManagerInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/PluginManagerInterface.php',
'Laminas\\ServiceManager\\Proxy\\LazyServiceFactory' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Proxy/LazyServiceFactory.php',
'Laminas\\ServiceManager\\PsrContainerDecorator' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/PsrContainerDecorator.php',
'Laminas\\ServiceManager\\ServiceLocatorInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/ServiceLocatorInterface.php',
'Laminas\\ServiceManager\\ServiceManager' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/ServiceManager.php',
'Laminas\\ServiceManager\\Test\\CommonPluginManagerTrait' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Test/CommonPluginManagerTrait.php',
'Laminas\\ServiceManager\\Tool\\ConfigDumper' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Tool/ConfigDumper.php',
'Laminas\\ServiceManager\\Tool\\ConfigDumperCommand' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Tool/ConfigDumperCommand.php',
'Laminas\\ServiceManager\\Tool\\FactoryCreator' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Tool/FactoryCreator.php',
'Laminas\\ServiceManager\\Tool\\FactoryCreatorCommand' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Tool/FactoryCreatorCommand.php',
'Laminas\\Stdlib\\AbstractOptions' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/AbstractOptions.php',
'Laminas\\Stdlib\\ArrayObject' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayObject.php',
'Laminas\\Stdlib\\ArraySerializableInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArraySerializableInterface.php',
'Laminas\\Stdlib\\ArrayStack' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayStack.php',
'Laminas\\Stdlib\\ArrayUtils' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayUtils.php',
'Laminas\\Stdlib\\ArrayUtils\\MergeRemoveKey' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayUtils/MergeRemoveKey.php',
'Laminas\\Stdlib\\ArrayUtils\\MergeReplaceKey' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKey.php',
'Laminas\\Stdlib\\ArrayUtils\\MergeReplaceKeyInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKeyInterface.php',
'Laminas\\Stdlib\\ConsoleHelper' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ConsoleHelper.php',
'Laminas\\Stdlib\\DispatchableInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/DispatchableInterface.php',
'Laminas\\Stdlib\\ErrorHandler' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ErrorHandler.php',
'Laminas\\Stdlib\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/BadMethodCallException.php',
'Laminas\\Stdlib\\Exception\\DomainException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/DomainException.php',
'Laminas\\Stdlib\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/ExceptionInterface.php',
'Laminas\\Stdlib\\Exception\\ExtensionNotLoadedException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/ExtensionNotLoadedException.php',
'Laminas\\Stdlib\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/InvalidArgumentException.php',
'Laminas\\Stdlib\\Exception\\LogicException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/LogicException.php',
'Laminas\\Stdlib\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/RuntimeException.php',
'Laminas\\Stdlib\\FastPriorityQueue' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/FastPriorityQueue.php',
'Laminas\\Stdlib\\Glob' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Glob.php',
'Laminas\\Stdlib\\Guard\\AllGuardsTrait' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Guard/AllGuardsTrait.php',
'Laminas\\Stdlib\\Guard\\ArrayOrTraversableGuardTrait' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Guard/ArrayOrTraversableGuardTrait.php',
'Laminas\\Stdlib\\Guard\\EmptyGuardTrait' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Guard/EmptyGuardTrait.php',
'Laminas\\Stdlib\\Guard\\NullGuardTrait' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Guard/NullGuardTrait.php',
'Laminas\\Stdlib\\InitializableInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/InitializableInterface.php',
'Laminas\\Stdlib\\JsonSerializable' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/JsonSerializable.php',
'Laminas\\Stdlib\\Message' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Message.php',
'Laminas\\Stdlib\\MessageInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/MessageInterface.php',
'Laminas\\Stdlib\\ParameterObjectInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ParameterObjectInterface.php',
'Laminas\\Stdlib\\Parameters' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Parameters.php',
'Laminas\\Stdlib\\ParametersInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ParametersInterface.php',
'Laminas\\Stdlib\\PriorityList' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/PriorityList.php',
'Laminas\\Stdlib\\PriorityQueue' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/PriorityQueue.php',
'Laminas\\Stdlib\\Request' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Request.php',
'Laminas\\Stdlib\\RequestInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/RequestInterface.php',
'Laminas\\Stdlib\\Response' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Response.php',
'Laminas\\Stdlib\\ResponseInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ResponseInterface.php',
'Laminas\\Stdlib\\SplPriorityQueue' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/SplPriorityQueue.php',
'Laminas\\Stdlib\\SplQueue' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/SplQueue.php',
'Laminas\\Stdlib\\SplStack' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/SplStack.php',
'Laminas\\Stdlib\\StringUtils' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringUtils.php',
'Laminas\\Stdlib\\StringWrapper\\AbstractStringWrapper' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/AbstractStringWrapper.php',
'Laminas\\Stdlib\\StringWrapper\\Iconv' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/Iconv.php',
'Laminas\\Stdlib\\StringWrapper\\Intl' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/Intl.php',
'Laminas\\Stdlib\\StringWrapper\\MbString' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/MbString.php',
'Laminas\\Stdlib\\StringWrapper\\Native' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/Native.php',
'Laminas\\Stdlib\\StringWrapper\\StringWrapperInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/StringWrapperInterface.php',
'Laminas\\Validator\\AbstractValidator' => __DIR__ . '/..' . '/laminas/laminas-validator/src/AbstractValidator.php',
'Laminas\\Validator\\Barcode' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode.php',
'Laminas\\Validator\\Barcode\\AbstractAdapter' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/AbstractAdapter.php',
'Laminas\\Validator\\Barcode\\AdapterInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/AdapterInterface.php',
'Laminas\\Validator\\Barcode\\Codabar' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Codabar.php',
'Laminas\\Validator\\Barcode\\Code128' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Code128.php',
'Laminas\\Validator\\Barcode\\Code25' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Code25.php',
'Laminas\\Validator\\Barcode\\Code25interleaved' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Code25interleaved.php',
'Laminas\\Validator\\Barcode\\Code39' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Code39.php',
'Laminas\\Validator\\Barcode\\Code39ext' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Code39ext.php',
'Laminas\\Validator\\Barcode\\Code93' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Code93.php',
'Laminas\\Validator\\Barcode\\Code93ext' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Code93ext.php',
'Laminas\\Validator\\Barcode\\Ean12' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Ean12.php',
'Laminas\\Validator\\Barcode\\Ean13' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Ean13.php',
'Laminas\\Validator\\Barcode\\Ean14' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Ean14.php',
'Laminas\\Validator\\Barcode\\Ean18' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Ean18.php',
'Laminas\\Validator\\Barcode\\Ean2' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Ean2.php',
'Laminas\\Validator\\Barcode\\Ean5' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Ean5.php',
'Laminas\\Validator\\Barcode\\Ean8' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Ean8.php',
'Laminas\\Validator\\Barcode\\Gtin12' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Gtin12.php',
'Laminas\\Validator\\Barcode\\Gtin13' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Gtin13.php',
'Laminas\\Validator\\Barcode\\Gtin14' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Gtin14.php',
'Laminas\\Validator\\Barcode\\Identcode' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Identcode.php',
'Laminas\\Validator\\Barcode\\Intelligentmail' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Intelligentmail.php',
'Laminas\\Validator\\Barcode\\Issn' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Issn.php',
'Laminas\\Validator\\Barcode\\Itf14' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Itf14.php',
'Laminas\\Validator\\Barcode\\Leitcode' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Leitcode.php',
'Laminas\\Validator\\Barcode\\Planet' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Planet.php',
'Laminas\\Validator\\Barcode\\Postnet' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Postnet.php',
'Laminas\\Validator\\Barcode\\Royalmail' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Royalmail.php',
'Laminas\\Validator\\Barcode\\Sscc' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Sscc.php',
'Laminas\\Validator\\Barcode\\Upca' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Upca.php',
'Laminas\\Validator\\Barcode\\Upce' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Upce.php',
'Laminas\\Validator\\Between' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Between.php',
'Laminas\\Validator\\Bitwise' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Bitwise.php',
'Laminas\\Validator\\Callback' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Callback.php',
'Laminas\\Validator\\ConfigProvider' => __DIR__ . '/..' . '/laminas/laminas-validator/src/ConfigProvider.php',
'Laminas\\Validator\\CreditCard' => __DIR__ . '/..' . '/laminas/laminas-validator/src/CreditCard.php',
'Laminas\\Validator\\Csrf' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Csrf.php',
'Laminas\\Validator\\Date' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Date.php',
'Laminas\\Validator\\DateStep' => __DIR__ . '/..' . '/laminas/laminas-validator/src/DateStep.php',
'Laminas\\Validator\\Db\\AbstractDb' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Db/AbstractDb.php',
'Laminas\\Validator\\Db\\NoRecordExists' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Db/NoRecordExists.php',
'Laminas\\Validator\\Db\\RecordExists' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Db/RecordExists.php',
'Laminas\\Validator\\Digits' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Digits.php',
'Laminas\\Validator\\EmailAddress' => __DIR__ . '/..' . '/laminas/laminas-validator/src/EmailAddress.php',
'Laminas\\Validator\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Exception/BadMethodCallException.php',
'Laminas\\Validator\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Exception/ExceptionInterface.php',
'Laminas\\Validator\\Exception\\ExtensionNotLoadedException' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Exception/ExtensionNotLoadedException.php',
'Laminas\\Validator\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Exception/InvalidArgumentException.php',
'Laminas\\Validator\\Exception\\InvalidMagicMimeFileException' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Exception/InvalidMagicMimeFileException.php',
'Laminas\\Validator\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Exception/RuntimeException.php',
'Laminas\\Validator\\Explode' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Explode.php',
'Laminas\\Validator\\File\\Count' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Count.php',
'Laminas\\Validator\\File\\Crc32' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Crc32.php',
'Laminas\\Validator\\File\\ExcludeExtension' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/ExcludeExtension.php',
'Laminas\\Validator\\File\\ExcludeMimeType' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/ExcludeMimeType.php',
'Laminas\\Validator\\File\\Exists' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Exists.php',
'Laminas\\Validator\\File\\Extension' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Extension.php',
'Laminas\\Validator\\File\\FileInformationTrait' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/FileInformationTrait.php',
'Laminas\\Validator\\File\\FilesSize' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/FilesSize.php',
'Laminas\\Validator\\File\\Hash' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Hash.php',
'Laminas\\Validator\\File\\ImageSize' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/ImageSize.php',
'Laminas\\Validator\\File\\IsCompressed' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/IsCompressed.php',
'Laminas\\Validator\\File\\IsImage' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/IsImage.php',
'Laminas\\Validator\\File\\Md5' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Md5.php',
'Laminas\\Validator\\File\\MimeType' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/MimeType.php',
'Laminas\\Validator\\File\\NotExists' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/NotExists.php',
'Laminas\\Validator\\File\\Sha1' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Sha1.php',
'Laminas\\Validator\\File\\Size' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Size.php',
'Laminas\\Validator\\File\\Upload' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Upload.php',
'Laminas\\Validator\\File\\UploadFile' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/UploadFile.php',
'Laminas\\Validator\\File\\WordCount' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/WordCount.php',
'Laminas\\Validator\\GpsPoint' => __DIR__ . '/..' . '/laminas/laminas-validator/src/GpsPoint.php',
'Laminas\\Validator\\GreaterThan' => __DIR__ . '/..' . '/laminas/laminas-validator/src/GreaterThan.php',
'Laminas\\Validator\\Hex' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Hex.php',
'Laminas\\Validator\\Hostname' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Hostname.php',
'Laminas\\Validator\\Iban' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Iban.php',
'Laminas\\Validator\\Identical' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Identical.php',
'Laminas\\Validator\\InArray' => __DIR__ . '/..' . '/laminas/laminas-validator/src/InArray.php',
'Laminas\\Validator\\Ip' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Ip.php',
'Laminas\\Validator\\IsCountable' => __DIR__ . '/..' . '/laminas/laminas-validator/src/IsCountable.php',
'Laminas\\Validator\\IsInstanceOf' => __DIR__ . '/..' . '/laminas/laminas-validator/src/IsInstanceOf.php',
'Laminas\\Validator\\Isbn' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Isbn.php',
'Laminas\\Validator\\Isbn\\Isbn10' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Isbn/Isbn10.php',
'Laminas\\Validator\\Isbn\\Isbn13' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Isbn/Isbn13.php',
'Laminas\\Validator\\LessThan' => __DIR__ . '/..' . '/laminas/laminas-validator/src/LessThan.php',
'Laminas\\Validator\\Module' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Module.php',
'Laminas\\Validator\\NotEmpty' => __DIR__ . '/..' . '/laminas/laminas-validator/src/NotEmpty.php',
'Laminas\\Validator\\Regex' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Regex.php',
'Laminas\\Validator\\Sitemap\\Changefreq' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Sitemap/Changefreq.php',
'Laminas\\Validator\\Sitemap\\Lastmod' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Sitemap/Lastmod.php',
'Laminas\\Validator\\Sitemap\\Loc' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Sitemap/Loc.php',
'Laminas\\Validator\\Sitemap\\Priority' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Sitemap/Priority.php',
'Laminas\\Validator\\StaticValidator' => __DIR__ . '/..' . '/laminas/laminas-validator/src/StaticValidator.php',
'Laminas\\Validator\\Step' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Step.php',
'Laminas\\Validator\\StringLength' => __DIR__ . '/..' . '/laminas/laminas-validator/src/StringLength.php',
'Laminas\\Validator\\Timezone' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Timezone.php',
'Laminas\\Validator\\Translator\\TranslatorAwareInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Translator/TranslatorAwareInterface.php',
'Laminas\\Validator\\Translator\\TranslatorInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Translator/TranslatorInterface.php',
'Laminas\\Validator\\UndisclosedPassword' => __DIR__ . '/..' . '/laminas/laminas-validator/src/UndisclosedPassword.php',
'Laminas\\Validator\\Uri' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Uri.php',
'Laminas\\Validator\\Uuid' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Uuid.php',
'Laminas\\Validator\\ValidatorChain' => __DIR__ . '/..' . '/laminas/laminas-validator/src/ValidatorChain.php',
'Laminas\\Validator\\ValidatorInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/ValidatorInterface.php',
'Laminas\\Validator\\ValidatorPluginManager' => __DIR__ . '/..' . '/laminas/laminas-validator/src/ValidatorPluginManager.php',
'Laminas\\Validator\\ValidatorPluginManagerAwareInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/ValidatorPluginManagerAwareInterface.php',
'Laminas\\Validator\\ValidatorPluginManagerFactory' => __DIR__ . '/..' . '/laminas/laminas-validator/src/ValidatorPluginManagerFactory.php',
'Laminas\\Validator\\ValidatorProviderInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/ValidatorProviderInterface.php',
'Laminas\\ZendFrameworkBridge\\Autoloader' => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src/Autoloader.php',
'Laminas\\ZendFrameworkBridge\\ConfigPostProcessor' => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src/ConfigPostProcessor.php',
'Laminas\\ZendFrameworkBridge\\Module' => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src/Module.php',
'Laminas\\ZendFrameworkBridge\\Replacements' => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src/Replacements.php',
'Laminas\\ZendFrameworkBridge\\RewriteRules' => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src/RewriteRules.php',
'ListExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php',
'ListOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php',
'LogAPI' => __DIR__ . '/../..' . '/core/log.class.inc.php',
@@ -1160,8 +1530,6 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
'StimulusInternal' => __DIR__ . '/../..' . '/core/stimulus.class.inc.php',
'StimulusUserAction' => __DIR__ . '/../..' . '/core/stimulus.class.inc.php',
'Str' => __DIR__ . '/../..' . '/core/MyHelpers.class.inc.php',
'Swift_LogFileTransport' => __DIR__ . '/../..' . '/core/email.class.inc.php',
'Swift_Transport_LogFileTransport' => __DIR__ . '/../..' . '/core/email.class.inc.php',
'Symfony\\Bridge\\Twig\\AppVariable' => __DIR__ . '/..' . '/symfony/twig-bridge/AppVariable.php',
'Symfony\\Bridge\\Twig\\Command\\DebugCommand' => __DIR__ . '/..' . '/symfony/twig-bridge/Command/DebugCommand.php',
'Symfony\\Bridge\\Twig\\Command\\LintCommand' => __DIR__ . '/..' . '/symfony/twig-bridge/Command/LintCommand.php',
@@ -1316,9 +1684,6 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateNameParser' => __DIR__ . '/..' . '/symfony/framework-bundle/Templating/TemplateNameParser.php',
'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateReference' => __DIR__ . '/..' . '/symfony/framework-bundle/Templating/TemplateReference.php',
'Symfony\\Bundle\\FrameworkBundle\\Templating\\TimedPhpEngine' => __DIR__ . '/..' . '/symfony/framework-bundle/Templating/TimedPhpEngine.php',
'Symfony\\Bundle\\FrameworkBundle\\Test\\ForwardCompatTestTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/ForwardCompatTestTrait.php',
'Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/KernelTestCase.php',
'Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestCase' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/WebTestCase.php',
'Symfony\\Bundle\\FrameworkBundle\\Translation\\PhpExtractor' => __DIR__ . '/..' . '/symfony/framework-bundle/Translation/PhpExtractor.php',
'Symfony\\Bundle\\FrameworkBundle\\Translation\\PhpStringTokenParser' => __DIR__ . '/..' . '/symfony/framework-bundle/Translation/PhpStringTokenParser.php',
'Symfony\\Bundle\\FrameworkBundle\\Translation\\TranslationLoader' => __DIR__ . '/..' . '/symfony/framework-bundle/Translation/TranslationLoader.php',
@@ -2123,7 +2488,6 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
'Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/DataDumperInterface.php',
'Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/HtmlDumper.php',
'Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException' => __DIR__ . '/..' . '/symfony/var-dumper/Exception/ThrowingCasterException.php',
'Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait' => __DIR__ . '/..' . '/symfony/var-dumper/Test/VarDumperTestTrait.php',
'Symfony\\Component\\VarDumper\\VarDumper' => __DIR__ . '/..' . '/symfony/var-dumper/VarDumper.php',
'Symfony\\Component\\Yaml\\Command\\LintCommand' => __DIR__ . '/..' . '/symfony/yaml/Command/LintCommand.php',
'Symfony\\Component\\Yaml\\Dumper' => __DIR__ . '/..' . '/symfony/yaml/Dumper.php',
@@ -2183,6 +2547,10 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
'TriggerOnStateEnter' => __DIR__ . '/../..' . '/core/trigger.class.inc.php',
'TriggerOnStateLeave' => __DIR__ . '/../..' . '/core/trigger.class.inc.php',
'TriggerOnThresholdReached' => __DIR__ . '/../..' . '/core/trigger.class.inc.php',
'TrueBV\\Exception\\DomainOutOfBoundsException' => __DIR__ . '/..' . '/true/punycode/src/Exception/DomainOutOfBoundsException.php',
'TrueBV\\Exception\\LabelOutOfBoundsException' => __DIR__ . '/..' . '/true/punycode/src/Exception/LabelOutOfBoundsException.php',
'TrueBV\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/true/punycode/src/Exception/OutOfBoundsException.php',
'TrueBV\\Punycode' => __DIR__ . '/..' . '/true/punycode/src/Punycode.php',
'TrueExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php',
'Twig\\Cache\\CacheInterface' => __DIR__ . '/..' . '/twig/twig/src/Cache/CacheInterface.php',
'Twig\\Cache\\FilesystemCache' => __DIR__ . '/..' . '/twig/twig/src/Cache/FilesystemCache.php',

View File

@@ -63,6 +63,554 @@
"homepage": "https://github.com/combodo-itop-libs/TCPDF",
"install-path": "../combodo/tcpdf"
},
{
"name": "container-interop/container-interop",
"version": "1.2.0",
"version_normalized": "1.2.0.0",
"source": {
"type": "git",
"url": "https://github.com/container-interop/container-interop.git",
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
"shasum": ""
},
"require": {
"psr/container": "^1.0"
},
"time": "2017-02-14T19:40:03+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Interop\\Container\\": "src/Interop/Container/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
"homepage": "https://github.com/container-interop/container-interop",
"support": {
"issues": "https://github.com/container-interop/container-interop/issues",
"source": "https://github.com/container-interop/container-interop/tree/master"
},
"abandoned": "psr/container",
"install-path": "../container-interop/container-interop"
},
{
"name": "laminas/laminas-loader",
"version": "2.6.1",
"version_normalized": "2.6.1.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-loader.git",
"reference": "5d01c2c237ae9e68bec262f339947e2ea18979bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-loader/zipball/5d01c2c237ae9e68bec262f339947e2ea18979bc",
"reference": "5d01c2c237ae9e68bec262f339947e2ea18979bc",
"shasum": ""
},
"require": {
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^5.6 || ^7.0"
},
"replace": {
"zendframework/zend-loader": "self.version"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.4"
},
"time": "2019-12-31T17:18:27+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.6.x-dev",
"dev-develop": "2.7.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Laminas\\Loader\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Autoloading and plugin loading strategies",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"loader"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-loader/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-loader/issues",
"rss": "https://github.com/laminas/laminas-loader/releases.atom",
"source": "https://github.com/laminas/laminas-loader"
},
"install-path": "../laminas/laminas-loader"
},
{
"name": "laminas/laminas-mail",
"version": "2.12.5",
"version_normalized": "2.12.5.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-mail.git",
"reference": "ed5b36a0deef4ffafe6138c2ae9cafcffafab856"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-mail/zipball/ed5b36a0deef4ffafe6138c2ae9cafcffafab856",
"reference": "ed5b36a0deef4ffafe6138c2ae9cafcffafab856",
"shasum": ""
},
"require": {
"ext-iconv": "*",
"laminas/laminas-loader": "^2.5",
"laminas/laminas-mime": "^2.5",
"laminas/laminas-stdlib": "^2.7 || ^3.0",
"laminas/laminas-validator": "^2.10.2",
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^7.1",
"true/punycode": "^2.1"
},
"replace": {
"zendframework/zend-mail": "^2.10.0"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"laminas/laminas-config": "^2.6",
"laminas/laminas-crypt": "^2.6 || ^3.0",
"laminas/laminas-servicemanager": "^3.2.1",
"phpunit/phpunit": "^7.5.20"
},
"suggest": {
"laminas/laminas-crypt": "Crammd5 support in SMTP Auth",
"laminas/laminas-servicemanager": "^2.7.10 || ^3.3.1 when using SMTP to deliver messages"
},
"time": "2020-12-31T11:41:57+00:00",
"type": "library",
"extra": {
"laminas": {
"component": "Laminas\\Mail",
"config-provider": "Laminas\\Mail\\ConfigProvider"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Laminas\\Mail\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Provides generalized functionality to compose and send both text and MIME-compliant multipart e-mail messages",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"mail"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-mail/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-mail/issues",
"rss": "https://github.com/laminas/laminas-mail/releases.atom",
"source": "https://github.com/laminas/laminas-mail"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"install-path": "../laminas/laminas-mail"
},
{
"name": "laminas/laminas-mime",
"version": "2.7.4",
"version_normalized": "2.7.4.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-mime.git",
"reference": "e45a7d856bf7b4a7b5bd00d6371f9961dc233add"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-mime/zipball/e45a7d856bf7b4a7b5bd00d6371f9961dc233add",
"reference": "e45a7d856bf7b4a7b5bd00d6371f9961dc233add",
"shasum": ""
},
"require": {
"laminas/laminas-stdlib": "^2.7 || ^3.0",
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^5.6 || ^7.0"
},
"replace": {
"zendframework/zend-mime": "^2.7.2"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"laminas/laminas-mail": "^2.6",
"phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.20"
},
"suggest": {
"laminas/laminas-mail": "Laminas\\Mail component"
},
"time": "2020-03-29T13:12:07+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.7.x-dev",
"dev-develop": "2.8.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Laminas\\Mime\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Create and parse MIME messages and parts",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"mime"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-mime/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-mime/issues",
"rss": "https://github.com/laminas/laminas-mime/releases.atom",
"source": "https://github.com/laminas/laminas-mime"
},
"install-path": "../laminas/laminas-mime"
},
{
"name": "laminas/laminas-servicemanager",
"version": "3.5.2",
"version_normalized": "3.5.2.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-servicemanager.git",
"reference": "0669e1eec8d9f61e35a5bc5012796d49f418b259"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/0669e1eec8d9f61e35a5bc5012796d49f418b259",
"reference": "0669e1eec8d9f61e35a5bc5012796d49f418b259",
"shasum": ""
},
"require": {
"container-interop/container-interop": "^1.2",
"laminas/laminas-stdlib": "^3.2.1",
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^5.6 || ^7.0",
"psr/container": "^1.0"
},
"provide": {
"container-interop/container-interop-implementation": "^1.2",
"psr/container-implementation": "^1.0"
},
"replace": {
"zendframework/zend-servicemanager": "^3.4.0"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"mikey179/vfsstream": "^1.6.5",
"ocramius/proxy-manager": "^1.0 || ^2.0",
"phpbench/phpbench": "^0.13.0",
"phpunit/phpunit": "^5.7.25 || ^6.4.4"
},
"suggest": {
"laminas/laminas-stdlib": "laminas-stdlib ^2.5 if you wish to use the MergeReplaceKey or MergeRemoveKey features in Config instances",
"ocramius/proxy-manager": "ProxyManager 1.* to handle lazy initialization of services"
},
"time": "2021-01-17T16:54:43+00:00",
"bin": [
"bin/generate-deps-for-config-factory",
"bin/generate-factory-for-class"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.3-dev",
"dev-develop": "4.0-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Laminas\\ServiceManager\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Factory-Driven Dependency Injection Container",
"homepage": "https://laminas.dev",
"keywords": [
"PSR-11",
"dependency-injection",
"di",
"dic",
"laminas",
"service-manager",
"servicemanager"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-servicemanager/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-servicemanager/issues",
"rss": "https://github.com/laminas/laminas-servicemanager/releases.atom",
"source": "https://github.com/laminas/laminas-servicemanager"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"install-path": "../laminas/laminas-servicemanager"
},
{
"name": "laminas/laminas-stdlib",
"version": "3.2.1",
"version_normalized": "3.2.1.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-stdlib.git",
"reference": "2b18347625a2f06a1a485acfbc870f699dbe51c6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/2b18347625a2f06a1a485acfbc870f699dbe51c6",
"reference": "2b18347625a2f06a1a485acfbc870f699dbe51c6",
"shasum": ""
},
"require": {
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^5.6 || ^7.0"
},
"replace": {
"zendframework/zend-stdlib": "self.version"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"phpbench/phpbench": "^0.13",
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2"
},
"time": "2019-12-31T17:51:15+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2.x-dev",
"dev-develop": "3.3.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Laminas\\Stdlib\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "SPL extensions, array utilities, error handlers, and more",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"stdlib"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-stdlib/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-stdlib/issues",
"rss": "https://github.com/laminas/laminas-stdlib/releases.atom",
"source": "https://github.com/laminas/laminas-stdlib"
},
"install-path": "../laminas/laminas-stdlib"
},
{
"name": "laminas/laminas-validator",
"version": "2.13.5",
"version_normalized": "2.13.5.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-validator.git",
"reference": "d334dddda43af263d6a7e5024fd2b013cb6981f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-validator/zipball/d334dddda43af263d6a7e5024fd2b013cb6981f7",
"reference": "d334dddda43af263d6a7e5024fd2b013cb6981f7",
"shasum": ""
},
"require": {
"container-interop/container-interop": "^1.1",
"laminas/laminas-stdlib": "^3.2.1",
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^7.1"
},
"replace": {
"zendframework/zend-validator": "^2.13.0"
},
"require-dev": {
"laminas/laminas-cache": "^2.6.1",
"laminas/laminas-coding-standard": "~1.0.0",
"laminas/laminas-config": "^2.6",
"laminas/laminas-db": "^2.7",
"laminas/laminas-filter": "^2.6",
"laminas/laminas-http": "^2.5.4",
"laminas/laminas-i18n": "^2.6",
"laminas/laminas-math": "^2.6",
"laminas/laminas-servicemanager": "^2.7.5 || ^3.0.3",
"laminas/laminas-session": "^2.8",
"laminas/laminas-uri": "^2.5",
"phpunit/phpunit": "^7.5.20 || ^8.5.2",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.0"
},
"suggest": {
"laminas/laminas-db": "Laminas\\Db component, required by the (No)RecordExists validator",
"laminas/laminas-filter": "Laminas\\Filter component, required by the Digits validator",
"laminas/laminas-i18n": "Laminas\\I18n component to allow translation of validation error messages",
"laminas/laminas-i18n-resources": "Translations of validator messages",
"laminas/laminas-math": "Laminas\\Math component, required by the Csrf validator",
"laminas/laminas-servicemanager": "Laminas\\ServiceManager component to allow using the ValidatorPluginManager and validator chains",
"laminas/laminas-session": "Laminas\\Session component, ^2.8; required by the Csrf validator",
"laminas/laminas-uri": "Laminas\\Uri component, required by the Uri and Sitemap\\Loc validators",
"psr/http-message": "psr/http-message, required when validating PSR-7 UploadedFileInterface instances via the Upload and UploadFile validators"
},
"time": "2021-01-06T15:05:04+00:00",
"type": "library",
"extra": {
"laminas": {
"component": "Laminas\\Validator",
"config-provider": "Laminas\\Validator\\ConfigProvider"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Laminas\\Validator\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Validation classes for a wide range of domains, and the ability to chain validators to create complex validation criteria",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"validator"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-validator/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-validator/issues",
"rss": "https://github.com/laminas/laminas-validator/releases.atom",
"source": "https://github.com/laminas/laminas-validator"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"install-path": "../laminas/laminas-validator"
},
{
"name": "laminas/laminas-zendframework-bridge",
"version": "1.1.1",
"version_normalized": "1.1.1.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-zendframework-bridge.git",
"reference": "6ede70583e101030bcace4dcddd648f760ddf642"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/6ede70583e101030bcace4dcddd648f760ddf642",
"reference": "6ede70583e101030bcace4dcddd648f760ddf642",
"shasum": ""
},
"require": {
"php": "^5.6 || ^7.0 || ^8.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1 || ^9.3",
"squizlabs/php_codesniffer": "^3.5"
},
"time": "2020-09-14T14:23:00+00:00",
"type": "library",
"extra": {
"laminas": {
"module": "Laminas\\ZendFrameworkBridge"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"src/autoload.php"
],
"psr-4": {
"Laminas\\ZendFrameworkBridge\\": "src//"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Alias legacy ZF class names to Laminas Project equivalents.",
"keywords": [
"ZendFramework",
"autoloading",
"laminas",
"zf"
],
"support": {
"forum": "https://discourse.laminas.dev/",
"issues": "https://github.com/laminas/laminas-zendframework-bridge/issues",
"rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom",
"source": "https://github.com/laminas/laminas-zendframework-bridge"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"install-path": "../laminas/laminas-zendframework-bridge"
},
{
"name": "nikic/php-parser",
"version": "v4.12.0",
@@ -763,63 +1311,6 @@
],
"install-path": "../scssphp/scssphp"
},
{
"name": "swiftmailer/swiftmailer",
"version": "v5.4.12",
"version_normalized": "5.4.12.0",
"source": {
"type": "git",
"url": "https://github.com/swiftmailer/swiftmailer.git",
"reference": "181b89f18a90f8925ef805f950d47a7190e9b950"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/181b89f18a90f8925ef805f950d47a7190e9b950",
"reference": "181b89f18a90f8925ef805f950d47a7190e9b950",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"mockery/mockery": "~0.9.1",
"symfony/phpunit-bridge": "~3.2"
},
"time": "2018-07-31T09:26:32+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.4-dev"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"lib/swift_required.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Chris Corbyn"
},
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Swiftmailer, free feature-rich PHP mailer",
"homepage": "https://swiftmailer.symfony.com",
"keywords": [
"email",
"mail",
"mailer"
],
"install-path": "../swiftmailer/swiftmailer"
},
{
"name": "symfony/cache",
"version": "v3.4.47",
@@ -3028,6 +3519,59 @@
],
"install-path": "../symfony/yaml"
},
{
"name": "true/punycode",
"version": "v2.1.1",
"version_normalized": "2.1.1.0",
"source": {
"type": "git",
"url": "https://github.com/true/php-punycode.git",
"reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/true/php-punycode/zipball/a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
"reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"symfony/polyfill-mbstring": "^1.3"
},
"require-dev": {
"phpunit/phpunit": "~4.7",
"squizlabs/php_codesniffer": "~2.0"
},
"time": "2016-11-16T10:37:54+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"TrueBV\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Renan Gonçalves",
"email": "renan.saddam@gmail.com"
}
],
"description": "A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)",
"homepage": "https://github.com/true/php-punycode",
"keywords": [
"idna",
"punycode"
],
"support": {
"issues": "https://github.com/true/php-punycode/issues",
"source": "https://github.com/true/php-punycode/tree/master"
},
"install-path": "../true/punycode"
},
{
"name": "twig/twig",
"version": "v1.42.4",

View File

@@ -5,7 +5,7 @@
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '9ad341f73a2aa0bd50515d88e1daac99b124238f',
'reference' => 'c47f2245669135902b32c54f3edf7f1bc52de81e',
'name' => '__root__',
'dev' => true,
),
@@ -16,7 +16,7 @@
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '9ad341f73a2aa0bd50515d88e1daac99b124238f',
'reference' => 'c47f2245669135902b32c54f3edf7f1bc52de81e',
'dev_requirement' => false,
),
'combodo/tcpdf' => array(
@@ -28,6 +28,84 @@
'reference' => 'aedd4b7b8cf7fcc24e617c405c9d3304150f4b94',
'dev_requirement' => false,
),
'container-interop/container-interop' => array(
'pretty_version' => '1.2.0',
'version' => '1.2.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../container-interop/container-interop',
'aliases' => array(),
'reference' => '79cbf1341c22ec75643d841642dd5d6acd83bdb8',
'dev_requirement' => false,
),
'container-interop/container-interop-implementation' => array(
'dev_requirement' => false,
'provided' => array(
0 => '^1.2',
),
),
'laminas/laminas-loader' => array(
'pretty_version' => '2.6.1',
'version' => '2.6.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../laminas/laminas-loader',
'aliases' => array(),
'reference' => '5d01c2c237ae9e68bec262f339947e2ea18979bc',
'dev_requirement' => false,
),
'laminas/laminas-mail' => array(
'pretty_version' => '2.12.5',
'version' => '2.12.5.0',
'type' => 'library',
'install_path' => __DIR__ . '/../laminas/laminas-mail',
'aliases' => array(),
'reference' => 'ed5b36a0deef4ffafe6138c2ae9cafcffafab856',
'dev_requirement' => false,
),
'laminas/laminas-mime' => array(
'pretty_version' => '2.7.4',
'version' => '2.7.4.0',
'type' => 'library',
'install_path' => __DIR__ . '/../laminas/laminas-mime',
'aliases' => array(),
'reference' => 'e45a7d856bf7b4a7b5bd00d6371f9961dc233add',
'dev_requirement' => false,
),
'laminas/laminas-servicemanager' => array(
'pretty_version' => '3.5.2',
'version' => '3.5.2.0',
'type' => 'library',
'install_path' => __DIR__ . '/../laminas/laminas-servicemanager',
'aliases' => array(),
'reference' => '0669e1eec8d9f61e35a5bc5012796d49f418b259',
'dev_requirement' => false,
),
'laminas/laminas-stdlib' => array(
'pretty_version' => '3.2.1',
'version' => '3.2.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../laminas/laminas-stdlib',
'aliases' => array(),
'reference' => '2b18347625a2f06a1a485acfbc870f699dbe51c6',
'dev_requirement' => false,
),
'laminas/laminas-validator' => array(
'pretty_version' => '2.13.5',
'version' => '2.13.5.0',
'type' => 'library',
'install_path' => __DIR__ . '/../laminas/laminas-validator',
'aliases' => array(),
'reference' => 'd334dddda43af263d6a7e5024fd2b013cb6981f7',
'dev_requirement' => false,
),
'laminas/laminas-zendframework-bridge' => array(
'pretty_version' => '1.1.1',
'version' => '1.1.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../laminas/laminas-zendframework-bridge',
'aliases' => array(),
'reference' => '6ede70583e101030bcace4dcddd648f760ddf642',
'dev_requirement' => false,
),
'nikic/php-parser' => array(
'pretty_version' => 'v4.12.0',
'version' => '4.12.0.0',
@@ -118,7 +196,8 @@
'psr/container-implementation' => array(
'dev_requirement' => false,
'provided' => array(
0 => '1.0',
0 => '^1.0',
1 => '1.0',
),
),
'psr/log' => array(
@@ -166,15 +245,6 @@
'reference' => '5b3c9d704950d8f9637f5110c36c281ec47dc13c',
'dev_requirement' => false,
),
'swiftmailer/swiftmailer' => array(
'pretty_version' => 'v5.4.12',
'version' => '5.4.12.0',
'type' => 'library',
'install_path' => __DIR__ . '/../swiftmailer/swiftmailer',
'aliases' => array(),
'reference' => '181b89f18a90f8925ef805f950d47a7190e9b950',
'dev_requirement' => false,
),
'symfony/cache' => array(
'pretty_version' => 'v3.4.47',
'version' => '3.4.47.0',
@@ -424,6 +494,15 @@
0 => '6.3.5',
),
),
'true/punycode' => array(
'pretty_version' => 'v2.1.1',
'version' => '2.1.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../true/punycode',
'aliases' => array(),
'reference' => 'a4d0c11a36dd7f4e7cd7096076cab6d3378a071e',
'dev_requirement' => false,
),
'twig/twig' => array(
'pretty_version' => 'v1.42.4',
'version' => '1.42.4.0',
@@ -433,5 +512,41 @@
'reference' => 'e587180584c3d2d6cb864a0454e777bb6dcb6152',
'dev_requirement' => false,
),
'zendframework/zend-loader' => array(
'dev_requirement' => false,
'replaced' => array(
0 => '2.6.1',
),
),
'zendframework/zend-mail' => array(
'dev_requirement' => false,
'replaced' => array(
0 => '^2.10.0',
),
),
'zendframework/zend-mime' => array(
'dev_requirement' => false,
'replaced' => array(
0 => '^2.7.2',
),
),
'zendframework/zend-servicemanager' => array(
'dev_requirement' => false,
'replaced' => array(
0 => '^3.4.0',
),
),
'zendframework/zend-stdlib' => array(
'dev_requirement' => false,
'replaced' => array(
0 => '3.2.1',
),
),
'zendframework/zend-validator' => array(
'dev_requirement' => false,
'replaced' => array(
0 => '^2.13.0',
),
),
),
);

View File

@@ -0,0 +1,51 @@
# Changelog
All notable changes to this project will be documented in this file, in reverse chronological order by release.
## 2.6.1 - 2019-09-04
### Added
- [zendframework/zend-loader#18](https://github.com/zendframework/zend-loader/pull/18) adds support for PHP 7.3.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
## 2.6.0 - 2018-04-30
### Added
- [zendframework/zend-loader#16](https://github.com/zendframework/zend-loader/pull/16) adds support for PHP 7.1 and 7.2.
- [zendframework/zend-loader#8](https://github.com/zendframework/zend-loader/pull/8) adds documentation at https://docs.laminas.dev/laminas-loader/
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- [zendframework/zend-loader#16](https://github.com/zendframework/zend-loader/pull/16) removes support for PHP 5.5.
- [zendframework/zend-loader#16](https://github.com/zendframework/zend-loader/pull/16) removes support for HHVM.
### Fixed
- Nothing.

View File

@@ -0,0 +1,2 @@
Copyright (c) 2019, Laminas Foundation.
All rights reserved. (https://getlaminas.org/)

View File

@@ -0,0 +1,27 @@
Copyright (c) 2019, Laminas Foundation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of Laminas Foundation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,9 @@
# laminas-loader
[![Build Status](https://travis-ci.org/laminas/laminas-loader.svg?branch=master)](https://travis-ci.org/laminas/laminas-loader)
[![Coverage Status](https://coveralls.io/repos/github/laminas/laminas-loader/badge.svg?branch=master)](https://coveralls.io/github/laminas/laminas-loader?branch=master)
laminas-loader provides different strategies for autoloading PHP classes.
- File issues at https://github.com/laminas/laminas-loader/issues
- Documentation is at https://docs.laminas.dev/laminas-loader/

View File

@@ -0,0 +1,58 @@
{
"name": "laminas/laminas-loader",
"description": "Autoloading and plugin loading strategies",
"license": "BSD-3-Clause",
"keywords": [
"laminas",
"loader"
],
"homepage": "https://laminas.dev",
"support": {
"docs": "https://docs.laminas.dev/laminas-loader/",
"issues": "https://github.com/laminas/laminas-loader/issues",
"source": "https://github.com/laminas/laminas-loader",
"rss": "https://github.com/laminas/laminas-loader/releases.atom",
"chat": "https://laminas.dev/chat",
"forum": "https://discourse.laminas.dev"
},
"config": {
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "2.6.x-dev",
"dev-develop": "2.7.x-dev"
}
},
"require": {
"php": "^5.6 || ^7.0",
"laminas/laminas-zendframework-bridge": "^1.0"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.4"
},
"autoload": {
"psr-4": {
"Laminas\\Loader\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"LaminasTest\\Loader\\": "test/"
}
},
"scripts": {
"check": [
"@cs-check",
"@test"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
},
"replace": {
"zendframework/zend-loader": "self.version"
}
}

View File

@@ -0,0 +1,210 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader;
use Traversable;
if (class_exists('Laminas\Loader\AutoloaderFactory')) {
return;
}
abstract class AutoloaderFactory
{
const STANDARD_AUTOLOADER = 'Laminas\Loader\StandardAutoloader';
/**
* @var array All autoloaders registered using the factory
*/
protected static $loaders = [];
/**
* @var StandardAutoloader StandardAutoloader instance for resolving
* autoloader classes via the include_path
*/
protected static $standardAutoloader;
/**
* Factory for autoloaders
*
* Options should be an array or Traversable object of the following structure:
* <code>
* array(
* '<autoloader class name>' => $autoloaderOptions,
* )
* </code>
*
* The factory will then loop through and instantiate each autoloader with
* the specified options, and register each with the spl_autoloader.
*
* You may retrieve the concrete autoloader instances later using
* {@link getRegisteredAutoloaders()}.
*
* Note that the class names must be resolvable on the include_path or via
* the Laminas library, using PSR-0 rules (unless the class has already been
* loaded).
*
* @param array|Traversable $options (optional) options to use. Defaults to Laminas\Loader\StandardAutoloader
* @return void
* @throws Exception\InvalidArgumentException for invalid options
* @throws Exception\InvalidArgumentException for unloadable autoloader classes
* @throws Exception\DomainException for autoloader classes not implementing SplAutoloader
*/
public static function factory($options = null)
{
if (null === $options) {
if (! isset(static::$loaders[static::STANDARD_AUTOLOADER])) {
$autoloader = static::getStandardAutoloader();
$autoloader->register();
static::$loaders[static::STANDARD_AUTOLOADER] = $autoloader;
}
// Return so we don't hit the next check's exception (we're done here anyway)
return;
}
if (! is_array($options) && ! ($options instanceof Traversable)) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(
'Options provided must be an array or Traversable'
);
}
foreach ($options as $class => $autoloaderOptions) {
if (! isset(static::$loaders[$class])) {
$autoloader = static::getStandardAutoloader();
if (! class_exists($class) && ! $autoloader->autoload($class)) {
require_once 'Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(
sprintf('Autoloader class "%s" not loaded', $class)
);
}
if (! is_subclass_of($class, 'Laminas\Loader\SplAutoloader')) {
require_once 'Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(
sprintf('Autoloader class %s must implement Laminas\\Loader\\SplAutoloader', $class)
);
}
if ($class === static::STANDARD_AUTOLOADER) {
$autoloader->setOptions($autoloaderOptions);
} else {
$autoloader = new $class($autoloaderOptions);
}
$autoloader->register();
static::$loaders[$class] = $autoloader;
} else {
static::$loaders[$class]->setOptions($autoloaderOptions);
}
}
}
/**
* Get a list of all autoloaders registered with the factory
*
* Returns an array of autoloader instances.
*
* @return array
*/
public static function getRegisteredAutoloaders()
{
return static::$loaders;
}
/**
* Retrieves an autoloader by class name
*
* @param string $class
* @return SplAutoloader
* @throws Exception\InvalidArgumentException for non-registered class
*/
public static function getRegisteredAutoloader($class)
{
if (! isset(static::$loaders[$class])) {
require_once 'Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(sprintf('Autoloader class "%s" not loaded', $class));
}
return static::$loaders[$class];
}
/**
* Unregisters all autoloaders that have been registered via the factory.
* This will NOT unregister autoloaders registered outside of the fctory.
*
* @return void
*/
public static function unregisterAutoloaders()
{
foreach (static::getRegisteredAutoloaders() as $class => $autoloader) {
spl_autoload_unregister([$autoloader, 'autoload']);
unset(static::$loaders[$class]);
}
}
/**
* Unregister a single autoloader by class name
*
* @param string $autoloaderClass
* @return bool
*/
public static function unregisterAutoloader($autoloaderClass)
{
if (! isset(static::$loaders[$autoloaderClass])) {
return false;
}
$autoloader = static::$loaders[$autoloaderClass];
spl_autoload_unregister([$autoloader, 'autoload']);
unset(static::$loaders[$autoloaderClass]);
return true;
}
/**
* Get an instance of the standard autoloader
*
* Used to attempt to resolve autoloader classes, using the
* StandardAutoloader. The instance is marked as a fallback autoloader, to
* allow resolving autoloaders not under the "Laminas" namespace.
*
* @return SplAutoloader
*/
protected static function getStandardAutoloader()
{
if (null !== static::$standardAutoloader) {
return static::$standardAutoloader;
}
if (! class_exists(static::STANDARD_AUTOLOADER)) {
// Extract the filename from the classname
$stdAutoloader = substr(strrchr(static::STANDARD_AUTOLOADER, '\\'), 1);
require_once __DIR__ . "/$stdAutoloader.php";
}
$loader = new StandardAutoloader();
static::$standardAutoloader = $loader;
return static::$standardAutoloader;
}
/**
* Checks if the object has this class as one of its parents
*
* @see https://bugs.php.net/bug.php?id=53727
* @see https://github.com/zendframework/zf2/pull/1807
*
* @deprecated since laminas 2.3 requires PHP >= 5.3.23
*
* @param string $className
* @param string $type
* @return bool
*/
protected static function isSubclassOf($className, $type)
{
return is_subclass_of($className, $type);
}
}

View File

@@ -0,0 +1,220 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader;
use Traversable;
// Grab SplAutoloader interface
require_once __DIR__ . '/SplAutoloader.php';
/**
* Class-map autoloader
*
* Utilizes class-map files to lookup classfile locations.
*/
class ClassMapAutoloader implements SplAutoloader
{
/**
* Registry of map files that have already been loaded
* @var array
*/
protected $mapsLoaded = [];
/**
* Class name/filename map
* @var array
*/
protected $map = [];
/**
* Constructor
*
* Create a new instance, and optionally configure the autoloader.
*
* @param null|array|Traversable $options
*/
public function __construct($options = null)
{
if (null !== $options) {
$this->setOptions($options);
}
}
/**
* Configure the autoloader
*
* Proxies to {@link registerAutoloadMaps()}.
*
* @param array|Traversable $options
* @return ClassMapAutoloader
*/
public function setOptions($options)
{
$this->registerAutoloadMaps($options);
return $this;
}
/**
* Register an autoload map
*
* An autoload map may be either an associative array, or a file returning
* an associative array.
*
* An autoload map should be an associative array containing
* classname/file pairs.
*
* @param string|array $map
* @throws Exception\InvalidArgumentException
* @return ClassMapAutoloader
*/
public function registerAutoloadMap($map)
{
if (is_string($map)) {
$location = $map;
if ($this === ($map = $this->loadMapFromFile($location))) {
return $this;
}
}
if (! is_array($map)) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(sprintf(
'Map file provided does not return a map. Map file: "%s"',
(isset($location) && is_string($location) ? $location : 'unexpected type: ' . gettype($map))
));
}
$this->map = $map + $this->map;
if (isset($location)) {
$this->mapsLoaded[] = $location;
}
return $this;
}
/**
* Register many autoload maps at once
*
* @param array $locations
* @throws Exception\InvalidArgumentException
* @return ClassMapAutoloader
*/
public function registerAutoloadMaps($locations)
{
if (! is_array($locations) && ! ($locations instanceof Traversable)) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException('Map list must be an array or implement Traversable');
}
foreach ($locations as $location) {
$this->registerAutoloadMap($location);
}
return $this;
}
/**
* Retrieve current autoload map
*
* @return array
*/
public function getAutoloadMap()
{
return $this->map;
}
/**
* {@inheritDoc}
*/
public function autoload($class)
{
if (isset($this->map[$class])) {
require_once $this->map[$class];
return $class;
}
return false;
}
/**
* Register the autoloader with spl_autoload registry
*
* @return void
*/
public function register()
{
spl_autoload_register([$this, 'autoload'], true, true);
}
/**
* Load a map from a file
*
* If the map has been previously loaded, returns the current instance;
* otherwise, returns whatever was returned by calling include() on the
* location.
*
* @param string $location
* @return ClassMapAutoloader|mixed
* @throws Exception\InvalidArgumentException for nonexistent locations
*/
protected function loadMapFromFile($location)
{
if (! file_exists($location)) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(sprintf(
'Map file provided does not exist. Map file: "%s"',
(is_string($location) ? $location : 'unexpected type: ' . gettype($location))
));
}
if (! $path = static::realPharPath($location)) {
$path = realpath($location);
}
if (in_array($path, $this->mapsLoaded)) {
// Already loaded this map
return $this;
}
$map = include $path;
return $map;
}
/**
* Resolve the real_path() to a file within a phar.
*
* @see https://bugs.php.net/bug.php?id=52769
* @param string $path
* @return string
*/
public static function realPharPath($path)
{
if (! preg_match('|^phar:(/{2,3})|', $path, $match)) {
return;
}
$prefixLength = 5 + strlen($match[1]);
$parts = explode('/', str_replace(['/', '\\'], '/', substr($path, $prefixLength)));
$parts = array_values(array_filter($parts, function ($p) {
return ($p !== '' && $p !== '.');
}));
array_walk($parts, function ($value, $key) use (&$parts) {
if ($value === '..') {
unset($parts[$key], $parts[$key - 1]);
$parts = array_values($parts);
}
});
if (file_exists($realPath = str_pad('phar:', $prefixLength, '/') . implode('/', $parts))) {
return $realPath;
}
}
}

View File

@@ -0,0 +1,16 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader\Exception;
require_once __DIR__ . '/ExceptionInterface.php';
class BadMethodCallException extends \BadMethodCallException implements
ExceptionInterface
{
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader\Exception;
require_once __DIR__ . '/ExceptionInterface.php';
class DomainException extends \DomainException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,13 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader\Exception;
interface ExceptionInterface
{
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader\Exception;
require_once __DIR__ . '/ExceptionInterface.php';
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader\Exception;
require_once __DIR__ . '/ExceptionInterface.php';
class InvalidPathException extends \Exception implements ExceptionInterface
{
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader\Exception;
require_once __DIR__ . '/ExceptionInterface.php';
class MissingResourceNamespaceException extends \Exception implements ExceptionInterface
{
}

View File

@@ -0,0 +1,18 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader\Exception;
require_once __DIR__ . '/DomainException.php';
/**
* Plugin class loader exceptions
*/
class PluginLoaderException extends DomainException
{
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader\Exception;
require_once __DIR__ . '/ExceptionInterface.php';
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader\Exception;
require_once __DIR__ . '/DomainException.php';
class SecurityException extends DomainException
{
}

View File

@@ -0,0 +1,441 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader;
// Grab SplAutoloader interface
require_once __DIR__ . '/SplAutoloader.php';
use GlobIterator;
use Phar;
use PharFileInfo;
use SplFileInfo;
use Traversable;
class ModuleAutoloader implements SplAutoloader
{
/**
* @var array An array of module paths to scan
*/
protected $paths = [];
/**
* @var array An array of modulename => path
*/
protected $explicitPaths = [];
/**
* @var array An array of namespaceName => namespacePath
*/
protected $namespacedPaths = [];
/**
* @var string Will contain the absolute phar:// path to the executable when packaged as phar file
*/
protected $pharBasePath = "";
/**
* @var array An array of supported phar extensions (filled on constructor)
*/
protected $pharExtensions = [];
/**
* @var array An array of module classes to their containing files
*/
protected $moduleClassMap = [];
/**
* Constructor
*
* Allow configuration of the autoloader via the constructor.
*
* @param null|array|Traversable $options
*/
public function __construct($options = null)
{
if (extension_loaded('phar')) {
$this->pharBasePath = Phar::running(true);
$this->pharExtensions = [
'phar',
'phar.tar',
'tar',
];
// ext/zlib enabled -> phar can read gzip & zip compressed files
if (extension_loaded('zlib')) {
$this->pharExtensions[] = 'phar.gz';
$this->pharExtensions[] = 'phar.tar.gz';
$this->pharExtensions[] = 'tar.gz';
$this->pharExtensions[] = 'phar.zip';
$this->pharExtensions[] = 'zip';
}
// ext/bzip2 enabled -> phar can read bz2 compressed files
if (extension_loaded('bzip2')) {
$this->pharExtensions[] = 'phar.bz2';
$this->pharExtensions[] = 'phar.tar.bz2';
$this->pharExtensions[] = 'tar.bz2';
}
}
if (null !== $options) {
$this->setOptions($options);
}
}
/**
* Configure the autoloader
*
* In most cases, $options should be either an associative array or
* Traversable object.
*
* @param array|Traversable $options
* @return ModuleAutoloader
*/
public function setOptions($options)
{
$this->registerPaths($options);
return $this;
}
/**
* Retrieves the class map for all loaded modules.
*
* @return array
*/
public function getModuleClassMap()
{
return $this->moduleClassMap;
}
/**
* Sets the class map used to speed up the module autoloading.
*
* @param array $classmap
* @return ModuleAutoloader
*/
public function setModuleClassMap(array $classmap)
{
$this->moduleClassMap = $classmap;
return $this;
}
/**
* Autoload a class
*
* @param $class
* @return mixed
* False [if unable to load $class]
* get_class($class) [if $class is successfully loaded]
*/
public function autoload($class)
{
// Limit scope of this autoloader
if (substr($class, -7) !== '\Module') {
return false;
}
if (isset($this->moduleClassMap[$class])) {
require_once $this->moduleClassMap[$class];
return $class;
}
$moduleName = substr($class, 0, -7);
if (isset($this->explicitPaths[$moduleName])) {
$classLoaded = $this->loadModuleFromDir($this->explicitPaths[$moduleName], $class);
if ($classLoaded) {
return $classLoaded;
}
$classLoaded = $this->loadModuleFromPhar($this->explicitPaths[$moduleName], $class);
if ($classLoaded) {
return $classLoaded;
}
}
if (count($this->namespacedPaths) >= 1) {
foreach ($this->namespacedPaths as $namespace => $path) {
if (false === strpos($moduleName, $namespace)) {
continue;
}
$moduleNameBuffer = str_replace($namespace . "\\", "", $moduleName);
$path .= DIRECTORY_SEPARATOR . $moduleNameBuffer . DIRECTORY_SEPARATOR;
$classLoaded = $this->loadModuleFromDir($path, $class);
if ($classLoaded) {
return $classLoaded;
}
$classLoaded = $this->loadModuleFromPhar($path, $class);
if ($classLoaded) {
return $classLoaded;
}
}
}
$moduleClassPath = str_replace('\\', DIRECTORY_SEPARATOR, $moduleName);
$pharSuffixPattern = null;
if ($this->pharExtensions) {
$pharSuffixPattern = '(' . implode('|', array_map('preg_quote', $this->pharExtensions)) . ')';
}
foreach ($this->paths as $path) {
$path = $path . $moduleClassPath;
if ($path == '.' || substr($path, 0, 2) == './' || substr($path, 0, 2) == '.\\') {
if (! $basePath = $this->pharBasePath) {
$basePath = realpath('.');
}
if (false === $basePath) {
$basePath = getcwd();
}
$path = rtrim($basePath, '\/\\') . substr($path, 1);
}
$classLoaded = $this->loadModuleFromDir($path, $class);
if ($classLoaded) {
return $classLoaded;
}
// No directory with Module.php, searching for phars
if ($pharSuffixPattern) {
foreach (new GlobIterator($path . '.*') as $entry) {
if ($entry->isDir()) {
continue;
}
if (! preg_match('#.+\.' . $pharSuffixPattern . '$#', $entry->getPathname())) {
continue;
}
$classLoaded = $this->loadModuleFromPhar($entry->getPathname(), $class);
if ($classLoaded) {
return $classLoaded;
}
}
}
}
return false;
}
/**
* loadModuleFromDir
*
* @param string $dirPath
* @param string $class
* @return mixed
* False [if unable to load $class]
* get_class($class) [if $class is successfully loaded]
*/
protected function loadModuleFromDir($dirPath, $class)
{
$modulePath = $dirPath . '/Module.php';
if (substr($modulePath, 0, 7) === 'phar://') {
$file = new PharFileInfo($modulePath);
} else {
$file = new SplFileInfo($modulePath);
}
if (($file->isReadable() && $file->isFile())) {
// Found directory with Module.php in it
$absModulePath = $this->pharBasePath ? (string) $file : $file->getRealPath();
require_once $absModulePath;
if (class_exists($class)) {
$this->moduleClassMap[$class] = $absModulePath;
return $class;
}
}
return false;
}
/**
* loadModuleFromPhar
*
* @param string $pharPath
* @param string $class
* @return mixed
* False [if unable to load $class]
* get_class($class) [if $class is successfully loaded]
*/
protected function loadModuleFromPhar($pharPath, $class)
{
$pharPath = static::normalizePath($pharPath, false);
$file = new SplFileInfo($pharPath);
if (! $file->isReadable() || ! $file->isFile()) {
return false;
}
$fileRealPath = $file->getRealPath();
// Phase 0: Check for executable phar with Module class in stub
if (strpos($fileRealPath, '.phar') !== false) {
// First see if the stub makes the Module class available
require_once $fileRealPath;
if (class_exists($class)) {
$this->moduleClassMap[$class] = $fileRealPath;
return $class;
}
}
// Phase 1: Not executable phar, no stub, or stub did not provide Module class; try Module.php directly
$moduleClassFile = 'phar://' . $fileRealPath . '/Module.php';
$moduleFile = new SplFileInfo($moduleClassFile);
if ($moduleFile->isReadable() && $moduleFile->isFile()) {
require_once $moduleClassFile;
if (class_exists($class)) {
$this->moduleClassMap[$class] = $moduleClassFile;
return $class;
}
}
// Phase 2: Check for nested module directory within archive
// Checks for /path/to/MyModule.tar/MyModule/Module.php
// (shell-integrated zip/tar utilities wrap directories like this)
$pharBaseName = $this->pharFileToModuleName($fileRealPath);
$moduleClassFile = 'phar://' . $fileRealPath . '/' . $pharBaseName . '/Module.php';
$moduleFile = new SplFileInfo($moduleClassFile);
if ($moduleFile->isReadable() && $moduleFile->isFile()) {
require_once $moduleClassFile;
if (class_exists($class)) {
$this->moduleClassMap[$class] = $moduleClassFile;
return $class;
}
}
return false;
}
/**
* Register the autoloader with spl_autoload registry
*
* @return void
*/
public function register()
{
spl_autoload_register([$this, 'autoload']);
}
/**
* Unregister the autoloader with spl_autoload registry
*
* @return void
*/
public function unregister()
{
spl_autoload_unregister([$this, 'autoload']);
}
/**
* registerPaths
*
* @param array|Traversable $paths
* @throws \InvalidArgumentException
* @return ModuleAutoloader
*/
public function registerPaths($paths)
{
if (! is_array($paths) && ! $paths instanceof Traversable) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(
'Parameter to \\Laminas\\Loader\\ModuleAutoloader\'s '
. 'registerPaths method must be an array or '
. 'implement the Traversable interface'
);
}
foreach ($paths as $module => $path) {
if (is_string($module)) {
$this->registerPath($path, $module);
} else {
$this->registerPath($path);
}
}
return $this;
}
/**
* registerPath
*
* @param string $path
* @param bool|string $moduleName
* @throws \InvalidArgumentException
* @return ModuleAutoloader
*/
public function registerPath($path, $moduleName = false)
{
if (! is_string($path)) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(sprintf(
'Invalid path provided; must be a string, received %s',
gettype($path)
));
}
if ($moduleName) {
if (in_array(substr($moduleName, -2), ['\\*', '\\%'])) {
$this->namespacedPaths[substr($moduleName, 0, -2)] = static::normalizePath($path);
} else {
$this->explicitPaths[$moduleName] = static::normalizePath($path);
}
} else {
$this->paths[] = static::normalizePath($path);
}
return $this;
}
/**
* getPaths
*
* This is primarily for unit testing, but could have other uses.
*
* @return array
*/
public function getPaths()
{
return $this->paths;
}
/**
* Returns the base module name from the path to a phar
*
* @param string $pharPath
* @return string
*/
protected function pharFileToModuleName($pharPath)
{
do {
$pathinfo = pathinfo($pharPath);
$pharPath = $pathinfo['filename'];
} while (isset($pathinfo['extension']));
return $pathinfo['filename'];
}
/**
* Normalize a path for insertion in the stack
*
* @param string $path
* @param bool $trailingSlash Whether trailing slash should be included
* @return string
*/
public static function normalizePath($path, $trailingSlash = true)
{
$path = rtrim($path, '/');
$path = rtrim($path, '\\');
if ($trailingSlash) {
$path .= DIRECTORY_SEPARATOR;
}
return $path;
}
}

View File

@@ -0,0 +1,216 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader;
use ArrayIterator;
use IteratorAggregate;
use Traversable;
/**
* Plugin class locator interface
*/
class PluginClassLoader implements PluginClassLocator
{
/**
* List of plugin name => class name pairs
* @var array
*/
protected $plugins = [];
/**
* Static map allow global seeding of plugin loader
* @var array
*/
protected static $staticMap = [];
/**
* Constructor
*
* @param null|array|Traversable $map If provided, seeds the loader with a map
*/
public function __construct($map = null)
{
// Merge in static overrides
if (! empty(static::$staticMap)) {
$this->registerPlugins(static::$staticMap);
}
// Merge in constructor arguments
if ($map !== null) {
$this->registerPlugins($map);
}
}
/**
* Add a static map of plugins
*
* A null value will clear the static map.
*
* @param null|array|Traversable $map
* @throws Exception\InvalidArgumentException
* @return void
*/
public static function addStaticMap($map)
{
if (null === $map) {
static::$staticMap = [];
return;
}
if (! is_array($map) && ! $map instanceof Traversable) {
throw new Exception\InvalidArgumentException('Expects an array or Traversable object');
}
foreach ($map as $key => $value) {
static::$staticMap[$key] = $value;
}
}
/**
* Register a class to a given short name
*
* @param string $shortName
* @param string $className
* @return PluginClassLoader
*/
public function registerPlugin($shortName, $className)
{
$this->plugins[strtolower($shortName)] = $className;
return $this;
}
/**
* Register many plugins at once
*
* If $map is a string, assumes that the map is the class name of a
* Traversable object (likely a ShortNameLocator); it will then instantiate
* this class and use it to register plugins.
*
* If $map is an array or Traversable object, it will iterate it to
* register plugin names/classes.
*
* For all other arguments, or if the string $map is not a class or not a
* Traversable class, an exception will be raised.
*
* @param string|array|Traversable $map
* @return PluginClassLoader
* @throws Exception\InvalidArgumentException
*/
public function registerPlugins($map)
{
if (is_string($map)) {
if (! class_exists($map)) {
throw new Exception\InvalidArgumentException('Map class provided is invalid');
}
$map = new $map;
}
if (is_array($map)) {
$map = new ArrayIterator($map);
}
if (! $map instanceof Traversable) {
throw new Exception\InvalidArgumentException('Map provided is invalid; must be traversable');
}
// iterator_apply doesn't work as expected with IteratorAggregate
if ($map instanceof IteratorAggregate) {
$map = $map->getIterator();
}
foreach ($map as $name => $class) {
if (is_int($name) || is_numeric($name)) {
if (! is_object($class) && class_exists($class)) {
$class = new $class();
}
if ($class instanceof Traversable) {
$this->registerPlugins($class);
continue;
}
}
$this->registerPlugin($name, $class);
}
return $this;
}
/**
* Unregister a short name lookup
*
* @param mixed $shortName
* @return PluginClassLoader
*/
public function unregisterPlugin($shortName)
{
$lookup = strtolower($shortName);
if (array_key_exists($lookup, $this->plugins)) {
unset($this->plugins[$lookup]);
}
return $this;
}
/**
* Get a list of all registered plugins
*
* @return array|Traversable
*/
public function getRegisteredPlugins()
{
return $this->plugins;
}
/**
* Whether or not a plugin by a specific name has been registered
*
* @param string $name
* @return bool
*/
public function isLoaded($name)
{
$lookup = strtolower($name);
return isset($this->plugins[$lookup]);
}
/**
* Return full class name for a named helper
*
* @param string $name
* @return string|false
*/
public function getClassName($name)
{
return $this->load($name);
}
/**
* Load a helper via the name provided
*
* @param string $name
* @return string|false
*/
public function load($name)
{
if (! $this->isLoaded($name)) {
return false;
}
return $this->plugins[strtolower($name)];
}
/**
* Defined by IteratorAggregate
*
* Returns an instance of ArrayIterator, containing a map of
* all plugins
*
* @return ArrayIterator
*/
public function getIterator()
{
return new ArrayIterator($this->plugins);
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader;
use IteratorAggregate;
use Traversable;
/**
* Plugin class locator interface
*/
interface PluginClassLocator extends ShortNameLocator, IteratorAggregate
{
/**
* Register a class to a given short name
*
* @param string $shortName
* @param string $className
* @return PluginClassLocator
*/
public function registerPlugin($shortName, $className);
/**
* Unregister a short name lookup
*
* @param mixed $shortName
* @return void
*/
public function unregisterPlugin($shortName);
/**
* Get a list of all registered plugins
*
* @return array|Traversable
*/
public function getRegisteredPlugins();
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader;
/**
* Short name locator interface
*/
interface ShortNameLocator
{
/**
* Whether or not a Helper by a specific name
*
* @param string $name
* @return bool
*/
public function isLoaded($name);
/**
* Return full class name for a named helper
*
* @param string $name
* @return string
*/
public function getClassName($name);
/**
* Load a helper via the name provided
*
* @param string $name
* @return string
*/
public function load($name);
}

View File

@@ -0,0 +1,64 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader;
use Traversable;
if (interface_exists('Laminas\Loader\SplAutoloader')) {
return;
}
/**
* Defines an interface for classes that may register with the spl_autoload
* registry
*/
interface SplAutoloader
{
/**
* Constructor
*
* Allow configuration of the autoloader via the constructor.
*
* @param null|array|Traversable $options
*/
public function __construct($options = null);
/**
* Configure the autoloader
*
* In most cases, $options should be either an associative array or
* Traversable object.
*
* @param array|Traversable $options
* @return SplAutoloader
*/
public function setOptions($options);
/**
* Autoload a class
*
* @param $class
* @return mixed
* False [if unable to load $class]
* get_class($class) [if $class is successfully loaded]
*/
public function autoload($class);
/**
* Register the autoloader with spl_autoload registry
*
* Typically, the body of this will simply be:
* <code>
* spl_autoload_register(array($this, 'autoload'));
* </code>
*
* @return void
*/
public function register();
}

View File

@@ -0,0 +1,327 @@
<?php
/**
* @see https://github.com/laminas/laminas-loader for the canonical source repository
* @copyright https://github.com/laminas/laminas-loader/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-loader/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Loader;
// Grab SplAutoloader interface
require_once __DIR__ . '/SplAutoloader.php';
/**
* PSR-0 compliant autoloader
*
* Allows autoloading both namespaced and vendor-prefixed classes. Class
* lookups are performed on the filesystem. If a class file for the referenced
* class is not found, a PHP warning will be raised by include().
*/
class StandardAutoloader implements SplAutoloader
{
const NS_SEPARATOR = '\\';
const PREFIX_SEPARATOR = '_';
const LOAD_NS = 'namespaces';
const LOAD_PREFIX = 'prefixes';
const ACT_AS_FALLBACK = 'fallback_autoloader';
/** @deprecated Use AUTOREGISTER_LAMINAS instead */
const AUTOREGISTER_ZF = 'autoregister_laminas';
const AUTOREGISTER_LAMINAS = 'autoregister_laminas';
/**
* @var array Namespace/directory pairs to search; Laminas library added by default
*/
protected $namespaces = [];
/**
* @var array Prefix/directory pairs to search
*/
protected $prefixes = [];
/**
* @var bool Whether or not the autoloader should also act as a fallback autoloader
*/
protected $fallbackAutoloaderFlag = false;
/**
* Constructor
*
* @param null|array|\Traversable $options
*/
public function __construct($options = null)
{
if (null !== $options) {
$this->setOptions($options);
}
}
/**
* Configure autoloader
*
* Allows specifying both "namespace" and "prefix" pairs, using the
* following structure:
* <code>
* array(
* 'namespaces' => array(
* 'Laminas' => '/path/to/Laminas/library',
* 'Doctrine' => '/path/to/Doctrine/library',
* ),
* 'prefixes' => array(
* 'Phly_' => '/path/to/Phly/library',
* ),
* 'fallback_autoloader' => true,
* )
* </code>
*
* @param array|\Traversable $options
* @throws Exception\InvalidArgumentException
* @return StandardAutoloader
*/
public function setOptions($options)
{
if (! is_array($options) && ! ($options instanceof \Traversable)) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException('Options must be either an array or Traversable');
}
foreach ($options as $type => $pairs) {
switch ($type) {
case self::AUTOREGISTER_LAMINAS:
if ($pairs) {
$this->registerNamespace('Laminas', dirname(__DIR__));
}
break;
case self::LOAD_NS:
if (is_array($pairs) || $pairs instanceof \Traversable) {
$this->registerNamespaces($pairs);
}
break;
case self::LOAD_PREFIX:
if (is_array($pairs) || $pairs instanceof \Traversable) {
$this->registerPrefixes($pairs);
}
break;
case self::ACT_AS_FALLBACK:
$this->setFallbackAutoloader($pairs);
break;
default:
// ignore
}
}
return $this;
}
/**
* Set flag indicating fallback autoloader status
*
* @param bool $flag
* @return StandardAutoloader
*/
public function setFallbackAutoloader($flag)
{
$this->fallbackAutoloaderFlag = (bool) $flag;
return $this;
}
/**
* Is this autoloader acting as a fallback autoloader?
*
* @return bool
*/
public function isFallbackAutoloader()
{
return $this->fallbackAutoloaderFlag;
}
/**
* Register a namespace/directory pair
*
* @param string $namespace
* @param string $directory
* @return StandardAutoloader
*/
public function registerNamespace($namespace, $directory)
{
$namespace = rtrim($namespace, self::NS_SEPARATOR) . self::NS_SEPARATOR;
$this->namespaces[$namespace] = $this->normalizeDirectory($directory);
return $this;
}
/**
* Register many namespace/directory pairs at once
*
* @param array $namespaces
* @throws Exception\InvalidArgumentException
* @return StandardAutoloader
*/
public function registerNamespaces($namespaces)
{
if (! is_array($namespaces) && ! $namespaces instanceof \Traversable) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException('Namespace pairs must be either an array or Traversable');
}
foreach ($namespaces as $namespace => $directory) {
$this->registerNamespace($namespace, $directory);
}
return $this;
}
/**
* Register a prefix/directory pair
*
* @param string $prefix
* @param string $directory
* @return StandardAutoloader
*/
public function registerPrefix($prefix, $directory)
{
$prefix = rtrim($prefix, self::PREFIX_SEPARATOR). self::PREFIX_SEPARATOR;
$this->prefixes[$prefix] = $this->normalizeDirectory($directory);
return $this;
}
/**
* Register many namespace/directory pairs at once
*
* @param array $prefixes
* @throws Exception\InvalidArgumentException
* @return StandardAutoloader
*/
public function registerPrefixes($prefixes)
{
if (! is_array($prefixes) && ! $prefixes instanceof \Traversable) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException('Prefix pairs must be either an array or Traversable');
}
foreach ($prefixes as $prefix => $directory) {
$this->registerPrefix($prefix, $directory);
}
return $this;
}
/**
* Defined by Autoloadable; autoload a class
*
* @param string $class
* @return false|string
*/
public function autoload($class)
{
$isFallback = $this->isFallbackAutoloader();
if (false !== strpos($class, self::NS_SEPARATOR)) {
if ($this->loadClass($class, self::LOAD_NS)) {
return $class;
} elseif ($isFallback) {
return $this->loadClass($class, self::ACT_AS_FALLBACK);
}
return false;
}
if (false !== strpos($class, self::PREFIX_SEPARATOR)) {
if ($this->loadClass($class, self::LOAD_PREFIX)) {
return $class;
} elseif ($isFallback) {
return $this->loadClass($class, self::ACT_AS_FALLBACK);
}
return false;
}
if ($isFallback) {
return $this->loadClass($class, self::ACT_AS_FALLBACK);
}
return false;
}
/**
* Register the autoloader with spl_autoload
*
* @return void
*/
public function register()
{
spl_autoload_register([$this, 'autoload']);
}
/**
* Transform the class name to a filename
*
* @param string $class
* @param string $directory
* @return string
*/
protected function transformClassNameToFilename($class, $directory)
{
// $class may contain a namespace portion, in which case we need
// to preserve any underscores in that portion.
$matches = [];
preg_match('/(?P<namespace>.+\\\)?(?P<class>[^\\\]+$)/', $class, $matches);
$class = (isset($matches['class'])) ? $matches['class'] : '';
$namespace = (isset($matches['namespace'])) ? $matches['namespace'] : '';
return $directory
. str_replace(self::NS_SEPARATOR, '/', $namespace)
. str_replace(self::PREFIX_SEPARATOR, '/', $class)
. '.php';
}
/**
* Load a class, based on its type (namespaced or prefixed)
*
* @param string $class
* @param string $type
* @return bool|string
* @throws Exception\InvalidArgumentException
*/
protected function loadClass($class, $type)
{
if (! in_array($type, [self::LOAD_NS, self::LOAD_PREFIX, self::ACT_AS_FALLBACK])) {
require_once __DIR__ . '/Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException();
}
// Fallback autoloading
if ($type === self::ACT_AS_FALLBACK) {
// create filename
$filename = $this->transformClassNameToFilename($class, '');
$resolvedName = stream_resolve_include_path($filename);
if ($resolvedName !== false) {
return include $resolvedName;
}
return false;
}
// Namespace and/or prefix autoloading
foreach ($this->$type as $leader => $path) {
if (0 === strpos($class, $leader)) {
// Trim off leader (namespace or prefix)
$trimmedClass = substr($class, strlen($leader));
// create filename
$filename = $this->transformClassNameToFilename($trimmedClass, $path);
if (file_exists($filename)) {
return include $filename;
}
}
}
return false;
}
/**
* Normalize the directory to include a trailing directory separator
*
* @param string $directory
* @return string
*/
protected function normalizeDirectory($directory)
{
$last = $directory[strlen($directory) - 1];
if (in_array($last, ['/', '\\'])) {
$directory[strlen($directory) - 1] = DIRECTORY_SEPARATOR;
return $directory;
}
$directory .= DIRECTORY_SEPARATOR;
return $directory;
}
}

View File

@@ -0,0 +1,562 @@
# Changelog
All notable changes to this project will be documented in this file, in reverse chronological order by release.
## 2.12.5 - 2020-12-31
-----
### Release Notes for [2.12.5](https://github.com/laminas/laminas-mail/milestone/9)
2.12.x bugfix release (patch)
### 2.12.5
- Total issues resolved: **0**
- Total pull requests resolved: **1**
- Total contributors: **1**
#### Bug
- [108: Fix Invalid header line for Content-Disposition string - incomplete continuation](https://github.com/laminas/laminas-mail/pull/108) thanks to @glensc
## 2.12.3 - TBD
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#107](https://github.com/laminas/laminas-mail/pull/107) corrects a return type annotation in Laminas\Mail\Address\AddressInterface and in implementer.
## 2.12.2 - 2020-08-06
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#103](https://github.com/laminas/laminas-mail/pull/103) fixes issues on Windows whereby the "Subject" and "To" headers were duplicated.
- [#104](https://github.com/laminas/laminas-mail/pull/104) fixes an issue that occured when the `Sendmail` transport was configured with a `-f` option (From address). Prior to the fix, the option would be overwritten by the message `From` or `Sender` headers, which could lead to errors on systems where all mail must be sent from a specific address. The fixed behavior is to always honor the `-f` option, and ignore the `From` and `Sender` headers if it was provided to the transport.
## 2.12.1 - 2020-08-05
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#102](https://github.com/laminas/laminas-mail/pull/102) corrects a parameter typehint and a return type within the `Protocol\Imap` subcomponent to correctly detail what they allow.
## 2.12.0 - 2020-07-30
### Added
- [#95](https://github.com/laminas/laminas-mail/pull/95) adds a new interface, `Laminas\Mail\Header\HeaderLocatorInterface`. This defines classes that will locate header classes based on an email header name.
- [#95](https://github.com/laminas/laminas-mail/pull/95) adds a new class, `Laminas\Mail\Header\HeaderLocator`, implementing `Laminas\Mail\Header\HeaderLocatorInterface`. This is the default implementation of that new interface.
- [#95](https://github.com/laminas/laminas-mail/pull/95) adds the methods `setHeaderLocator(Laminas\Mail\Header\HeaderLocatorInterface $locator)` and `getHeaderLocator(): Laminas\Mail\Header\HeaderLocatorInterface` to the `Laminas\Mail\Headers` implementation. Users are encouraged to use these when providing custom header implementations in order to prepare for a 3.0 release. **The value of `getHeaderLocator()` will now be used as the default mechanism for resolving header names to header classes.**
- [#94](https://github.com/laminas/laminas-mail/pull/94) and [#99](https://github.com/laminas/laminas-mail/pull/99) add the "novalidatecert" option for each of the POP3, IMAP, and SMTP protocol implementations. When toggled true, you can connect to servers using self-signed certificates.
### Changed
- [#95](https://github.com/laminas/laminas-mail/pull/95) bumps the minimum supported PHP version to 7.1.
### Deprecated
- [#99](https://github.com/laminas/laminas-mail/pull/99) deprecates the `Laminas\Mail\Protocol\AbstractProtocol::_connect()` method, as it is no longer used internally.
- [#95](https://github.com/laminas/laminas-mail/pull/95) deprecates `Laminas\Mail\Header\HeaderLoader` in favor of the new `Laminas\Mail\Header\HeaderLocator` class. The class will be removed in version 3.0.0.
- [#95](https://github.com/laminas/laminas-mail/pull/95) deprecates the `Headers::getPluginClassLoader()` and `Headers::setPluginClassLoader()` methods, in favor of the new `setHeaderLocator()` and `getHeaderLocator()` methods. These methods will be removed in version 3.0.0, and laminas-loader `PluginClassLocator` instances will no longer be supported. Please update your code to use the new `HeaderLocatorInterface` instead.
### Removed
- [#98](https://github.com/laminas/laminas-mail/pull/98) removes `Laminas\Mail\Transport\Null`, as it is unusable with the new minimum supported PHP version (7.1). Users should use `Laminas\Mail\Transport\InMemory` instead. As this has been the default when requesting a "null" transport from `Laminas\Mail\Transport\Factory` for the past several minor releases, end-users should be unaffected. However, **users are encouraged to specify "inmemory" instead of "null" when requiring a no-op transport.**
### Fixed
- Nothing.
## 2.11.1 - 2020-07-28
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#97](https://github.com/laminas/laminas-mail/pull/97) adds code to `Header\ContentType::addParameter()` to ensure the value is trimmed of whitespace, fixing issues whereby filenames might contain a leading or trailing space.
## 2.11.0 - 2020-06-30
### Added
- [#31](https://github.com/laminas/laminas-mail/pull/31) adds the class `Laminas\Main\Header\ContentDisposition`, which implements `Laminas\Mail\Header\UnstructuredInterface`, and which provides propery encoding and escaping for `Content-Disposition` mail headers.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#31](https://github.com/laminas/laminas-mail/pull/31) provides a fix to ensure that the `Content-Disposition` header is properly encoded.
## 2.10.2 - 2020-06-30
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#89](https://github.com/laminas/laminas-mail/pull/89) corrects two parameter typehints within the Storage subcomponent to correctly detail what they allow.
- [#93](https://github.com/laminas/laminas-mail/pull/93) fixes an issue whereby an address containing a `;` character was not getting quoted, causing it to be interpreted as an address separator instead of part of the address.
## 2.10.1 - 2020-04-21
### Added
- [#81](https://github.com/laminas/laminas-mail/pull/81) adds PHP 7.3 and 7.4 support.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#83](https://github.com/laminas/laminas-mail/pull/83) fixes PHPDocs in `Transport\InMemory` (last message can be `null`).
- [#84](https://github.com/laminas/laminas-mail/pull/84) fixes PHP 7.4 compatibility.
- [#82](https://github.com/laminas/laminas-mail/pull/82) fixes numerous issues in `Storage\Maildir`. This storage adapter was not working before and unit tests were disabled.
- [#75](https://github.com/laminas/laminas-mail/pull/75) fixes how `Laminas\Mail\Header\ListParser::parse()` parses the string with quotes.
- [#88](https://github.com/laminas/laminas-mail/pull/88) fixes recognising encoding of `Subject` and `GenericHeader` headers.
## 2.10.0 - 2018-06-07
### Added
- [zendframework/zend-mail#213](https://github.com/zendframework/zend-mail/pull/213) re-adds support for PHP 5.6 and 7.0; Laminas policy is never
to bump the major version of a PHP requirement unless the package is bumping major version.
- [zendframework/zend-mail#172](https://github.com/zendframework/zend-mail/pull/172) adds the flag `connection_time_limit` to the possible `Laminas\Mail\Transport\Smtp` options.
This flag, when provided as a positive integer, and in conjunction with the `use_complete_quit` flag, will
reconnect to the server after the specified interval.
- [zendframework/zend-mail#166](https://github.com/zendframework/zend-mail/pull/166) adds functionality for handling `References` and `In-Reply-To` headers.
- [zendframework/zend-mail#148](https://github.com/zendframework/zend-mail/pull/148) adds the optional constructor argument `$comment` and the method `getComment()` to the class
`Laminas\Mail\Address`. When a comment is present, `toString()` will include it in the representation.
- [zendframework/zend-mail#148](https://github.com/zendframework/zend-mail/pull/148) adds the method `Laminas\Mail\Address::fromString(string $address, $comment = null) : Address`.
The method can be used to generate an instance from a string containing a `(name)?<email>` value.
The `$comment` argument can be used to associate a comment with the address.
### Changed
- [zendframework/zend-mail#196](https://github.com/zendframework/zend-mail/pull/196) updates how the `Headers::fromString()` handles header line continuations
that include a single empty line, ensuring they are concatenated to the
header value.
- [zendframework/zend-mail#165](https://github.com/zendframework/zend-mail/pull/165) changes the `AbstractAddressList` IDN&lt;-&gt;ASCII conversion; it now no longer requires
ext-intl, but instead uses a bundled true/punycode library to accomplish it. This also means that
the conversions will work on any PHP installation.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-mail#211](https://github.com/zendframework/zend-mail/pull/211) fixes how the `ContentType` header class parses the value it receives. Previously,
it was incorrectly splitting the value on semi-colons that were inside quotes; in now correctly
ignores them.
- [zendframework/zend-mail#204](https://github.com/zendframework/zend-mail/pull/204) fixes `HeaderWrap::mimeDecodeValue()` behavior when handling a multiline UTF-8
header split across a character. The fix will only work when ext-imap is present, however.
- [zendframework/zend-mail#164](https://github.com/zendframework/zend-mail/pull/164) fixes the return value from `Laminas\Mail\Protocol\Imap::capability()` when no response is
returned from the server; previously, it returned `false`, but now correctly returns an empty array.
- [zendframework/zend-mail#148](https://github.com/zendframework/zend-mail/pull/148) fixes how `Laminas\Mail\Header\AbstractAddressList` parses address values, ensuring
that they now retain any address comment discovered to include in the generated `Laminas\Mail\Address` instances.
- [zendframework/zend-mail#147](https://github.com/zendframework/zend-mail/pull/147) fixes how address lists are parsed, expanding the functionality to allow either
`,` or `;` delimiters (or both in combination).
## 2.9.0 - 2017-03-01
### Added
- [zendframework/zend-mail#177](https://github.com/zendframework/zend-mail/issues/177)
[zendframework/zend-mail#181](https://github.com/zendframework/zend-mail/pull/181)
[zendframework/zend-mail#192](https://github.com/zendframework/zend-mail/pull/192)
[zendframework/zend-mail#189](https://github.com/zendframework/zend-mail/pull/189) PHP 7.2 support
- [zendframework/zend-mail#73](https://github.com/zendframework/zend-mail/issues/73)
[zendframework/zend-mail#160](https://github.com/zendframework/zend-mail/pull/160) Support for
mails that don't have a `To`, as long as `Cc` or `Bcc` are set.
- [zendframework/zend-mail#161](https://github.com/zendframework/zend-mail/issues/161) removed
useless try-catch that just re-throws.
- [zendframework/zend-mail#134](https://github.com/zendframework/zend-mail/issues/134) simplified
checks for the existence of some string sub-sequences, which were
needlessly performed via regular expressions
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-mail#188](https://github.com/zendframework/zend-mail/pull/188) split strings
before calling `iconv_mime_decode()`, which destroys newlines, rendering
DKIM parsing useless.
- [zendframework/zend-mail#156](https://github.com/zendframework/zend-mail/pull/156) fixed a
regression in which `<` and `>` would appear doubled in message
identifiers.
- [zendframework/zend-mail#143](https://github.com/zendframework/zend-mail/pull/143) fixed parsing
of `<` and `>` being part of the email address comment.
## 2.8.0 - 2017-06-08
### Added
- [zendframework/zend-mail#117](https://github.com/zendframework/zend-mail/pull/117) adds support
configuring whether or not an SMTP transport should issue a `QUIT` at
`__destruct()` and/or end of script execution. Use the `use_complete_quit`
configuration flag and/or the `setuseCompleteQuit($flag)` method to change
the setting (default is to enable this behavior, which was the previous
behavior).
- [zendframework/zend-mail#128](https://github.com/zendframework/zend-mail/pull/128) adds a
requirement on ext/iconv, as it is used internally.
- [zendframework/zend-mail#132](https://github.com/zendframework/zend-mail/pull/132) bumps minimum
php version to 5.6
- [zendframework/zend-mail#144](https://github.com/zendframework/zend-mail/pull/144) adds support
for TLS versions 1.1 and 1.2 for all protocols supporting TLS operations.
### Changed
- [zendframework/zend-mail#140](https://github.com/zendframework/zend-mail/pull/140) updates the
`Sendmail` transport such that `From` and `Sender` addresses are passed to
`escapeshellarg()` when forming the `-f` argument for the `sendmail` binary.
While malformed addresses should never reach this class, this extra hardening
helps ensure safety in cases where a developer codes their own
`AddressInterface` implementations for these types of addresses.
- [zendframework/zend-mail#141](https://github.com/zendframework/zend-mail/pull/141) updates
`Laminas\Mail\Message::getHeaders()` to throw an exception in a case where the
`$headers` property is not a `Headers` instance.
- [zendframework/zend-mail#150](https://github.com/zendframework/zend-mail/pull/150) updates the
`Smtp` protocol to allow an empty or `none` value for the SSL configuration
value.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-mail#151](https://github.com/zendframework/zend-mail/pull/151) fixes a condition
in the `Sendmail` transport whereby CLI parameters were not properly trimmed.
## 2.7.3 - 2017-02-14
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-mail#93](https://github.com/zendframework/zend-mail/pull/93) fixes a situation
whereby `getSender()` was unintentionally creating a blank `Sender` header,
instead of returning `null` if none exists, fixing an issue in the SMTP
transport.
- [zendframework/zend-mail#105](https://github.com/zendframework/zend-mail/pull/105) fixes the header
implementation to allow zero (`0`) values for header values.
- [zendframework/zend-mail#116](https://github.com/zendframework/zend-mail/pull/116) fixes how the
`AbstractProtocol` handles `stream_socket_client()` errors, ensuring an
exception is thrown with detailed information regarding the failure.
## 2.7.2 - 2016-12-19
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Fixes [ZF2016-04](https://framework.zend.com/security/advisory/ZF2016-04).
## 2.7.1 - 2016-05-09
### Added
- [zendframework/zend-mail#38](https://github.com/zendframework/zend-mail/pull/38) adds support in the
IMAP protocol adapter for fetching items by UID.
- [zendframework/zend-mail#88](https://github.com/zendframework/zend-mail/pull/88) adds and publishes
documentation to https://docs.laminas.dev/laminas-mail/
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-mail#9](https://github.com/zendframework/zend-mail/pull/9) fixes the
`Laminas\Mail\Header\Sender::fromString()` implementation to more closely follow
the ABNF defined in RFC-5322, specifically to allow addresses in the form
`user@domain` (with no TLD).
- [zendframework/zend-mail#28](https://github.com/zendframework/zend-mail/pull/28) and
[zendframework/zend-mail#87](https://github.com/zendframework/zend-mail/pull/87) fix header value
validation when headers wrap using the sequence `\r\n\t`; prior to this
release, such sequences incorrectly marked a header value invalid.
- [zendframework/zend-mail#37](https://github.com/zendframework/zend-mail/pull/37) ensures that empty
lines do not result in PHP errors when consuming messages from a Courier IMAP
server.
- [zendframework/zend-mail#81](https://github.com/zendframework/zend-mail/pull/81) fixes the validation
in `Laminas\Mail\Address` to also DNS hostnames as well as local addresses.
## 2.7.0 - 2016-04-11
### Added
- [zendframework/zend-mail#41](https://github.com/zendframework/zend-mail/pull/41) adds support for
IMAP delimiters in the IMAP storage adapter.
- [zendframework/zend-mail#80](https://github.com/zendframework/zend-mail/pull/80) adds:
- `Laminas\Mail\Protocol\SmtpPluginManagerFactory`, for creating and returning an
`SmtpPluginManagerFactory` instance.
- `Laminas\Mail\ConfigProvider`, which maps the `SmtpPluginManager` to the above
factory.
- `Laminas\Mail\Module`, which does the same, for laminas-mvc contexts.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
## 2.6.2 - 2016-04-11
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-mail#44](https://github.com/zendframework/zend-mail/pull/44) fixes an issue with
decoding of addresses where the full name contains a comma (e.g., "Lastname,
Firstname").
- [zendframework/zend-mail#45](https://github.com/zendframework/zend-mail/pull/45) ensures that the
message parser allows deserializing message bodies containing multiple EOL
sequences.
- [zendframework/zend-mail#78](https://github.com/zendframework/zend-mail/pull/78) fixes the logic of
`HeaderWrap::canBeEncoded()` to ensure it returns correctly for header lines
containing at least one multibyte character, and particularly when that
character falls at specific locations (per a
[reported bug at php.net](https://bugs.php.net/bug.php?id=53891)).
## 2.6.1 - 2016-02-24
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-mail#72](https://github.com/zendframework/zend-mail/pull/72) re-implements
`SmtpPluginManager` as a laminas-servicemanager `AbstractPluginManager`, after
reports that making it standalone broke important extensibility use cases
(specifically, replacing existing plugins and/or providing additional plugins
could only be managed with significant code changes).
## 2.6.0 - 2016-02-18
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-mail#47](https://github.com/zendframework/zend-mail/pull/47) updates the
component to remove the (soft) dependency on laminas-servicemanager, by
altering the `SmtpPluginManager` to implement container-interop's
`ContainerInterface` instead of extending from `AbstractPluginManager`.
Usage remains the same, though developers who were adding services
to the plugin manager will need to instead extend it now.
- [zendframework/zend-mail#70](https://github.com/zendframework/zend-mail/pull/70) updates dependencies
to stable, forwards-compatible versions, and removes unused dependencies.
## 2.5.2 - 2015-09-10
### Added
- [zendframework/zend-mail#12](https://github.com/zendframework/zend-mail/pull/12) adds support for
simple comments in address lists.
- [zendframework/zend-mail#13](https://github.com/zendframework/zend-mail/pull/13) adds support for
groups in address lists.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-mail#26](https://github.com/zendframework/zend-mail/pull/26) fixes the
`ContentType` header to properly handle parameters with encoded values.
- [zendframework/zend-mail#11](https://github.com/zendframework/zend-mail/pull/11) fixes the
behavior of the `Sender` header, ensuring it can handle domains that do not
contain a TLD, as well as addresses referencing mailboxes (no domain).
- [zendframework/zend-mail#24](https://github.com/zendframework/zend-mail/pull/24) fixes parsing of
mail messages that contain an initial blank line (prior to the headers), a
situation observed in particular with GMail.

View File

@@ -0,0 +1 @@
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/)

View File

@@ -0,0 +1,26 @@
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of Laminas Foundation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,13 @@
# laminas-mail
[![Build Status](https://travis-ci.com/laminas/laminas-mail.svg?branch=master)](https://travis-ci.com/laminas/laminas-mail)
[![Coverage Status](https://coveralls.io/repos/github/laminas/laminas-mail/badge.svg?branch=master)](https://coveralls.io/github/laminas/laminas-mail?branch=master)
`Laminas\Mail` provides generalized functionality to compose and send both text and
MIME-compliant multipart email messages. Mail can be sent with `Laminas\Mail` via
the `Mail\Transport\Sendmail`, `Mail\Transport\Smtp` or the `Mail\Transport\File`
transport. Of course, you can also implement your own transport by implementing
the `Mail\Transport\TransportInterface`.
- File issues at https://github.com/laminas/laminas-mail/issues
- Documentation is at https://docs.laminas.dev/laminas-mail/

View File

@@ -0,0 +1,71 @@
{
"name": "laminas/laminas-mail",
"description": "Provides generalized functionality to compose and send both text and MIME-compliant multipart e-mail messages",
"license": "BSD-3-Clause",
"keywords": [
"laminas",
"mail"
],
"homepage": "https://laminas.dev",
"support": {
"docs": "https://docs.laminas.dev/laminas-mail/",
"issues": "https://github.com/laminas/laminas-mail/issues",
"source": "https://github.com/laminas/laminas-mail",
"rss": "https://github.com/laminas/laminas-mail/releases.atom",
"chat": "https://laminas.dev/chat",
"forum": "https://discourse.laminas.dev"
},
"config": {
"sort-packages": true
},
"extra": {
"laminas": {
"component": "Laminas\\Mail",
"config-provider": "Laminas\\Mail\\ConfigProvider"
}
},
"require": {
"php": "^7.1",
"ext-iconv": "*",
"laminas/laminas-loader": "^2.5",
"laminas/laminas-mime": "^2.5",
"laminas/laminas-stdlib": "^2.7 || ^3.0",
"laminas/laminas-validator": "^2.10.2",
"laminas/laminas-zendframework-bridge": "^1.0",
"true/punycode": "^2.1"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"laminas/laminas-config": "^2.6",
"laminas/laminas-crypt": "^2.6 || ^3.0",
"laminas/laminas-servicemanager": "^3.2.1",
"phpunit/phpunit": "^7.5.20"
},
"suggest": {
"laminas/laminas-crypt": "Crammd5 support in SMTP Auth",
"laminas/laminas-servicemanager": "^2.7.10 || ^3.3.1 when using SMTP to deliver messages"
},
"autoload": {
"psr-4": {
"Laminas\\Mail\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"LaminasTest\\Mail\\": "test/"
}
},
"scripts": {
"check": [
"@cs-check",
"@test"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
},
"replace": {
"zendframework/zend-mail": "^2.10.0"
}
}

View File

@@ -0,0 +1,166 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail;
use Laminas\Validator\EmailAddress as EmailAddressValidator;
use Laminas\Validator\Hostname;
class Address implements Address\AddressInterface
{
protected $comment;
protected $email;
protected $name;
/**
* Create an instance from a string value.
*
* Parses a string representing a single address. If it is a valid format,
* it then creates and returns an instance of itself using the name and
* email it has parsed from the value.
*
* @param string $address
* @param null|string $comment Comment associated with the address, if any.
* @throws Exception\InvalidArgumentException
* @return self
*/
public static function fromString($address, $comment = null)
{
if (! preg_match('/^((?P<name>.*)<(?P<namedEmail>[^>]+)>|(?P<email>.+))$/', $address, $matches)) {
throw new Exception\InvalidArgumentException('Invalid address format');
}
$name = null;
if (isset($matches['name'])) {
$name = trim($matches['name']);
}
if (empty($name)) {
$name = null;
}
if (isset($matches['namedEmail'])) {
$email = $matches['namedEmail'];
}
if (isset($matches['email'])) {
$email = $matches['email'];
}
$email = trim($email);
return new static($email, $name, $comment);
}
/**
* Constructor
*
* @param string $email
* @param null|string $name
* @param null|string $comment
* @throws Exception\InvalidArgumentException
*/
public function __construct($email, $name = null, $comment = null)
{
$emailAddressValidator = new EmailAddressValidator(Hostname::ALLOW_DNS | Hostname::ALLOW_LOCAL);
if (! is_string($email) || empty($email)) {
throw new Exception\InvalidArgumentException('Email must be a valid email address');
}
if (preg_match("/[\r\n]/", $email)) {
throw new Exception\InvalidArgumentException('CRLF injection detected');
}
if (! $emailAddressValidator->isValid($email)) {
$invalidMessages = $emailAddressValidator->getMessages();
throw new Exception\InvalidArgumentException(array_shift($invalidMessages));
}
if (null !== $name) {
if (! is_string($name)) {
throw new Exception\InvalidArgumentException('Name must be a string');
}
if (preg_match("/[\r\n]/", $name)) {
throw new Exception\InvalidArgumentException('CRLF injection detected');
}
$this->name = $name;
}
$this->email = $email;
if (null !== $comment) {
$this->comment = $comment;
}
}
/**
* Retrieve email
*
* @return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Retrieve name, if any
*
* @return null|string
*/
public function getName()
{
return $this->name;
}
/**
* Retrieve comment, if any
*
* @return null|string
*/
public function getComment()
{
return $this->comment;
}
/**
* String representation of address
*
* @return string
*/
public function toString()
{
$string = sprintf('<%s>', $this->getEmail());
$name = $this->constructName();
if (null === $name) {
return $string;
}
return sprintf('%s %s', $name, $string);
}
/**
* Constructs the name string
*
* If a comment is present, appends the comment (commented using parens) to
* the name before returning it; otherwise, returns just the name.
*
* @return null|string
*/
private function constructName()
{
$name = $this->getName();
$comment = $this->getComment();
if ($comment === null || $comment === '') {
return $name;
}
$string = sprintf('%s (%s)', $name, $comment);
return trim($string);
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Address;
interface AddressInterface
{
/**
* Retrieve email
*
* @return string
*/
public function getEmail();
/**
* Retrieve name, if any
*
* @return null|string
*/
public function getName();
/**
* String representation of address
*
* @return string
*/
public function toString();
}

View File

@@ -0,0 +1,237 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail;
use Countable;
use Iterator;
class AddressList implements Countable, Iterator
{
/**
* List of Address objects we're managing
*
* @var array
*/
protected $addresses = [];
/**
* Add an address to the list
*
* @param string|Address\AddressInterface $emailOrAddress
* @param null|string $name
* @throws Exception\InvalidArgumentException
* @return AddressList
*/
public function add($emailOrAddress, $name = null)
{
if (is_string($emailOrAddress)) {
$emailOrAddress = $this->createAddress($emailOrAddress, $name);
}
if (! $emailOrAddress instanceof Address\AddressInterface) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects an email address or %s\Address object as its first argument; received "%s"',
__METHOD__,
__NAMESPACE__,
(is_object($emailOrAddress) ? get_class($emailOrAddress) : gettype($emailOrAddress))
));
}
$email = strtolower($emailOrAddress->getEmail());
if ($this->has($email)) {
return $this;
}
$this->addresses[$email] = $emailOrAddress;
return $this;
}
/**
* Add many addresses at once
*
* If an email key is provided, it will be used as the email, and the value
* as the name. Otherwise, the value is passed as the sole argument to add(),
* and, as such, can be either email strings or Address\AddressInterface objects.
*
* @param array $addresses
* @throws Exception\RuntimeException
* @return AddressList
*/
public function addMany(array $addresses)
{
foreach ($addresses as $key => $value) {
if (is_int($key) || is_numeric($key)) {
$this->add($value);
continue;
}
if (! is_string($key)) {
throw new Exception\RuntimeException(sprintf(
'Invalid key type in provided addresses array ("%s")',
(is_object($key) ? get_class($key) : var_export($key, 1))
));
}
$this->add($key, $value);
}
return $this;
}
/**
* Add an address to the list from any valid string format, such as
* - "Laminas Dev" <dev@laminas.com>
* - dev@laminas.com
*
* @param string $address
* @param null|string $comment Comment associated with the address, if any.
* @throws Exception\InvalidArgumentException
* @return AddressList
*/
public function addFromString($address, $comment = null)
{
$this->add(Address::fromString($address, $comment));
return $this;
}
/**
* Merge another address list into this one
*
* @param AddressList $addressList
* @return AddressList
*/
public function merge(AddressList $addressList)
{
foreach ($addressList as $address) {
$this->add($address);
}
return $this;
}
/**
* Does the email exist in this list?
*
* @param string $email
* @return bool
*/
public function has($email)
{
$email = strtolower($email);
return isset($this->addresses[$email]);
}
/**
* Get an address by email
*
* @param string $email
* @return bool|Address\AddressInterface
*/
public function get($email)
{
$email = strtolower($email);
if (! isset($this->addresses[$email])) {
return false;
}
return $this->addresses[$email];
}
/**
* Delete an address from the list
*
* @param string $email
* @return bool
*/
public function delete($email)
{
$email = strtolower($email);
if (! isset($this->addresses[$email])) {
return false;
}
unset($this->addresses[$email]);
return true;
}
/**
* Return count of addresses
*
* @return int
*/
public function count()
{
return count($this->addresses);
}
/**
* Rewind iterator
*
* @return mixed the value of the first addresses element, or false if the addresses is
* empty.
* @see addresses
*/
public function rewind()
{
return reset($this->addresses);
}
/**
* Return current item in iteration
*
* @return Address
*/
public function current()
{
return current($this->addresses);
}
/**
* Return key of current item of iteration
*
* @return string
*/
public function key()
{
return key($this->addresses);
}
/**
* Move to next item
*
* @return mixed the addresses value in the next place that's pointed to by the
* internal array pointer, or false if there are no more elements.
* @see addresses
*/
public function next()
{
return next($this->addresses);
}
/**
* Is the current item of iteration valid?
*
* @return bool
*/
public function valid()
{
$key = key($this->addresses);
return ($key !== null && $key !== false);
}
/**
* Create an address object
*
* @param string $email
* @param string|null $name
* @return Address
*/
protected function createAddress($email, $name)
{
return new Address($email, $name);
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail;
class ConfigProvider
{
/**
* Retrieve configuration for laminas-mail package.
*
* @return array
*/
public function __invoke()
{
return [
'dependencies' => $this->getDependencyConfig(),
];
}
/**
* Retrieve dependency settings for laminas-mail package.
*
* @return array
*/
public function getDependencyConfig()
{
return [
// Legacy Zend Framework aliases
'aliases' => [
\Zend\Mail\Protocol\SmtpPluginManager::class => Protocol\SmtpPluginManager::class,
],
'factories' => [
Protocol\SmtpPluginManager::class => Protocol\SmtpPluginManagerFactory::class,
],
];
}
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class BadMethodCallException extends \BadMethodCallException implements
ExceptionInterface
{
}

View File

@@ -0,0 +1,16 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class DomainException extends \DomainException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,13 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Exception;
interface ExceptionInterface
{
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class InvalidArgumentException extends \InvalidArgumentException implements
ExceptionInterface
{
}

View File

@@ -0,0 +1,16 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,16 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,261 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
use Laminas\Mail\Address;
use Laminas\Mail\AddressList;
use Laminas\Mail\Headers;
use TrueBV\Exception\OutOfBoundsException;
use TrueBV\Punycode;
/**
* Base class for headers composing address lists (to, from, cc, bcc, reply-to)
*/
abstract class AbstractAddressList implements HeaderInterface
{
/**
* @var AddressList
*/
protected $addressList;
/**
* @var string Normalized field name
*/
protected $fieldName;
/**
* Header encoding
*
* @var string
*/
protected $encoding = 'ASCII';
/**
* @var string lower case field name
*/
protected static $type;
/**
* @var Punycode|null
*/
private static $punycode;
public static function fromString($headerLine)
{
list($fieldName, $fieldValue) = GenericHeader::splitHeaderLine($headerLine);
if (strtolower($fieldName) !== static::$type) {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for "%s" string',
__CLASS__
));
}
// split value on ","
$fieldValue = str_replace(Headers::FOLDING, ' ', $fieldValue);
$fieldValue = preg_replace('/[^:]+:([^;]*);/', '$1,', $fieldValue);
$values = ListParser::parse($fieldValue);
$wasEncoded = false;
$addresses = array_map(
function ($value) use (&$wasEncoded) {
$decodedValue = HeaderWrap::mimeDecodeValue($value);
$wasEncoded = $wasEncoded || ($decodedValue !== $value);
$value = trim($decodedValue);
$comments = self::getComments($value);
$value = self::stripComments($value);
$value = preg_replace(
[
'#(?<!\\\)"(.*)(?<!\\\)"#', // quoted-text
'#\\\([\x01-\x09\x0b\x0c\x0e-\x7f])#', // quoted-pair
],
[
'\\1',
'\\1',
],
$value
);
return empty($value) ? null : Address::fromString($value, $comments);
},
$values
);
$addresses = array_filter($addresses);
$header = new static();
if ($wasEncoded) {
$header->setEncoding('UTF-8');
}
/** @var AddressList $addressList */
$addressList = $header->getAddressList();
foreach ($addresses as $address) {
$addressList->add($address);
}
return $header;
}
public function getFieldName()
{
return $this->fieldName;
}
/**
* Safely convert UTF-8 encoded domain name to ASCII
* @param string $domainName the UTF-8 encoded email
* @return string
*/
protected function idnToAscii($domainName)
{
if (null === self::$punycode) {
self::$punycode = new Punycode();
}
try {
return self::$punycode->encode($domainName);
} catch (OutOfBoundsException $e) {
return $domainName;
}
}
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
$emails = [];
$encoding = $this->getEncoding();
foreach ($this->getAddressList() as $address) {
$email = $address->getEmail();
$name = $address->getName();
// quote $name if value requires so
if (! empty($name) && (false !== strpos($name, ',') || false !== strpos($name, ';'))) {
// FIXME: what if name contains double quote?
$name = sprintf('"%s"', $name);
}
if ($format === HeaderInterface::FORMAT_ENCODED
&& 'ASCII' !== $encoding
) {
if (! empty($name)) {
$name = HeaderWrap::mimeEncodeValue($name, $encoding);
}
if (preg_match('/^(.+)@([^@]+)$/', $email, $matches)) {
$localPart = $matches[1];
$hostname = $this->idnToAscii($matches[2]);
$email = sprintf('%s@%s', $localPart, $hostname);
}
}
if (empty($name)) {
$emails[] = $email;
} else {
$emails[] = sprintf('%s <%s>', $name, $email);
}
}
// Ensure the values are valid before sending them.
if ($format !== HeaderInterface::FORMAT_RAW) {
foreach ($emails as $email) {
HeaderValue::assertValid($email);
}
}
return implode(',' . Headers::FOLDING, $emails);
}
public function setEncoding($encoding)
{
$this->encoding = $encoding;
return $this;
}
public function getEncoding()
{
return $this->encoding;
}
/**
* Set address list for this header
*
* @param AddressList $addressList
*/
public function setAddressList(AddressList $addressList)
{
$this->addressList = $addressList;
}
/**
* Get address list managed by this header
*
* @return AddressList
*/
public function getAddressList()
{
if (null === $this->addressList) {
$this->setAddressList(new AddressList());
}
return $this->addressList;
}
public function toString()
{
$name = $this->getFieldName();
$value = $this->getFieldValue(HeaderInterface::FORMAT_ENCODED);
return (empty($value)) ? '' : sprintf('%s: %s', $name, $value);
}
/**
* Retrieve comments from value, if any.
*
* Supposed to be private, protected as a workaround for PHP bug 68194
*
* @param string $value
* @return string
*/
protected static function getComments($value)
{
$matches = [];
preg_match_all(
'/\\(
(?P<comment>(
\\\\.|
[^\\\\)]
)+)
\\)/x',
$value,
$matches
);
return isset($matches['comment']) ? implode(', ', $matches['comment']) : '';
}
/**
* Strip all comments from value, if any.
*
* Supposed to be private, protected as a workaround for PHP bug 68194
*
* @param string $value
* @return string
*/
protected static function stripComments($value)
{
return preg_replace(
'/\\(
(
\\\\.|
[^\\\\)]
)+
\\)/x',
'',
$value
);
}
}

View File

@@ -0,0 +1,22 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
class Bcc extends AbstractAddressList
{
/**
* @var string
*/
protected $fieldName = 'Bcc';
/**
* @var string
*/
protected static $type = 'bcc';
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
class Cc extends AbstractAddressList
{
protected $fieldName = 'Cc';
protected static $type = 'cc';
}

View File

@@ -0,0 +1,313 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
use Laminas\Mail\Headers;
use Laminas\Mime\Mime;
class ContentDisposition implements UnstructuredInterface
{
/**
* 78 chars (RFC 2822) - (semicolon + space (Header::FOLDING))
*
* @var int
*/
const MAX_PARAMETER_LENGTH = 76;
/**
* @var string
*/
protected $disposition = 'inline';
/**
* Header encoding
*
* @var string
*/
protected $encoding = 'ASCII';
/**
* @var array
*/
protected $parameters = [];
/**
* @inheritDoc
*/
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'content-disposition') {
throw new Exception\InvalidArgumentException('Invalid header line for Content-Disposition string');
}
$value = str_replace(Headers::FOLDING, ' ', $value);
$parts = explode(';', $value, 2);
$header = new static();
$header->setDisposition($parts[0]);
if (isset($parts[1])) {
$values = ListParser::parse(trim($parts[1]), [';', '=']);
$length = count($values);
$continuedValues = [];
for ($i = 0; $i < $length; $i += 2) {
$value = $values[$i + 1];
$value = trim($value, "'\" \t\n\r\0\x0B");
$name = trim($values[$i], "'\" \t\n\r\0\x0B");
if (strpos($name, '*')) {
list($name, $count) = explode('*', $name);
// allow optional count:
// Content-Disposition: attachment; filename*=UTF-8''%64%61%61%6D%69%2D%6D%C3%B5%72%76%2E%6A%70%67
if ($count === "") {
$count = 0;
}
if (! is_numeric($count)) {
$type = gettype($count);
$value = var_export($count, 1);
throw new Exception\InvalidArgumentException(sprintf(
"Invalid header line for Content-Disposition string".
" - count expected to be numeric, got %s with value %s",
$type,
$value
));
}
if (! isset($continuedValues[$name])) {
$continuedValues[$name] = [];
}
$continuedValues[$name][$count] = $value;
} else {
$header->setParameter($name, $value);
}
}
foreach ($continuedValues as $name => $values) {
$value = '';
for ($i = 0; $i < count($values); $i++) {
if (! isset($values[$i])) {
throw new Exception\InvalidArgumentException(
'Invalid header line for Content-Disposition string - incomplete continuation'.
'; HeaderLine: '.$headerLine
);
}
$value .= $values[$i];
}
$header->setParameter($name, $value);
}
}
return $header;
}
/**
* @inheritDoc
*/
public function getFieldName()
{
return 'Content-Disposition';
}
/**
* @inheritDoc
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
$result = $this->disposition;
if (empty($this->parameters)) {
return $result;
}
foreach ($this->parameters as $attribute => $value) {
$valueIsEncoded = false;
if (HeaderInterface::FORMAT_ENCODED === $format && ! Mime::isPrintable($value)) {
$value = $this->getEncodedValue($value);
$valueIsEncoded = true;
}
$line = sprintf('%s="%s"', $attribute, $value);
if (strlen($line) < self::MAX_PARAMETER_LENGTH) {
$lines = explode(Headers::FOLDING, $result);
if (count($lines) === 1) {
$existingLineLength = strlen('Content-Disposition: ' . $result);
} else {
$existingLineLength = 1 + strlen($lines[count($lines) - 1]);
}
if ((2 + $existingLineLength + strlen($line)) <= self::MAX_PARAMETER_LENGTH) {
$result .= '; ' . $line;
} else {
$result .= ';' . Headers::FOLDING . $line;
}
} else {
// Use 'continuation' per RFC 2231
$maxValueLength = strlen($value);
do {
$maxValueLength = ceil(0.6 * $maxValueLength);
} while ($maxValueLength > self::MAX_PARAMETER_LENGTH);
if ($valueIsEncoded) {
$encodedLength = strlen($value);
$value = HeaderWrap::mimeDecodeValue($value);
$decodedLength = strlen($value);
$maxValueLength -= ($encodedLength - $decodedLength);
}
$valueParts = str_split($value, $maxValueLength);
$i = 0;
foreach ($valueParts as $valuePart) {
$attributePart = $attribute . '*' . $i++;
if ($valueIsEncoded) {
$valuePart = $this->getEncodedValue($valuePart);
}
$result .= sprintf(';%s%s="%s"', Headers::FOLDING, $attributePart, $valuePart);
}
}
}
return $result;
}
/**
* @param string $value
* @return string
*/
protected function getEncodedValue($value)
{
$configuredEncoding = $this->encoding;
$this->encoding = 'UTF-8';
$value = HeaderWrap::wrap($value, $this);
$this->encoding = $configuredEncoding;
return $value;
}
/**
* @inheritDoc
*/
public function setEncoding($encoding)
{
$this->encoding = $encoding;
return $this;
}
/**
* @inheritDoc
*/
public function getEncoding()
{
return $this->encoding;
}
/**
* @inheritDoc
*/
public function toString()
{
return 'Content-Disposition: ' . $this->getFieldValue(HeaderInterface::FORMAT_ENCODED);
}
/**
* Set the content disposition
* Expected values include 'inline', 'attachment'
*
* @param string $disposition
* @return ContentDisposition
*/
public function setDisposition($disposition)
{
$this->disposition = strtolower($disposition);
return $this;
}
/**
* Retrieve the content disposition
*
* @return string
*/
public function getDisposition()
{
return $this->disposition;
}
/**
* Add a parameter pair
*
* @param string $name
* @param string $value
* @return ContentDisposition
*/
public function setParameter($name, $value)
{
$name = strtolower($name);
if (! HeaderValue::isValid($name)) {
throw new Exception\InvalidArgumentException(
'Invalid content-disposition parameter name detected'
);
}
// '5' here is for the quotes & equal sign in `name="value"`,
// and the space & semicolon for line folding
if ((strlen($name) + 5) >= self::MAX_PARAMETER_LENGTH) {
throw new Exception\InvalidArgumentException(
'Invalid content-disposition parameter name detected (too long)'
);
}
$this->parameters[$name] = $value;
return $this;
}
/**
* Get all parameters
*
* @return array
*/
public function getParameters()
{
return $this->parameters;
}
/**
* Get a parameter by name
*
* @param string $name
* @return null|string
*/
public function getParameter($name)
{
$name = strtolower($name);
if (isset($this->parameters[$name])) {
return $this->parameters[$name];
}
return null;
}
/**
* Remove a named parameter
*
* @param string $name
* @return bool
*/
public function removeParameter($name)
{
$name = strtolower($name);
if (isset($this->parameters[$name])) {
unset($this->parameters[$name]);
return true;
}
return false;
}
}

View File

@@ -0,0 +1,114 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
class ContentTransferEncoding implements HeaderInterface
{
/**
* Allowed Content-Transfer-Encoding parameters specified by RFC 1521
* (reduced set)
* @var array
*/
protected static $allowedTransferEncodings = [
'7bit',
'8bit',
'quoted-printable',
'base64',
'binary',
/*
* not implemented:
* x-token: 'X-'
*/
];
/**
* @var string
*/
protected $transferEncoding;
/**
* @var array
*/
protected $parameters = [];
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'content-transfer-encoding') {
throw new Exception\InvalidArgumentException('Invalid header line for Content-Transfer-Encoding string');
}
$header = new static();
$header->setTransferEncoding($value);
return $header;
}
public function getFieldName()
{
return 'Content-Transfer-Encoding';
}
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
return $this->transferEncoding;
}
public function setEncoding($encoding)
{
// Header must be always in US-ASCII
return $this;
}
public function getEncoding()
{
return 'ASCII';
}
public function toString()
{
return 'Content-Transfer-Encoding: ' . $this->getFieldValue();
}
/**
* Set the content transfer encoding
*
* @param string $transferEncoding
* @throws Exception\InvalidArgumentException
* @return $this
*/
public function setTransferEncoding($transferEncoding)
{
// Per RFC 1521, the value of the header is not case sensitive
$transferEncoding = strtolower($transferEncoding);
if (! in_array($transferEncoding, static::$allowedTransferEncodings)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects one of "'. implode(', ', static::$allowedTransferEncodings) . '"; received "%s"',
__METHOD__,
(string) $transferEncoding
));
}
$this->transferEncoding = $transferEncoding;
return $this;
}
/**
* Retrieve the content transfer encoding
*
* @return string
*/
public function getTransferEncoding()
{
return $this->transferEncoding;
}
}

View File

@@ -0,0 +1,202 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
use Laminas\Mail\Headers;
use Laminas\Mime\Mime;
class ContentType implements UnstructuredInterface
{
/**
* @var string
*/
protected $type;
/**
* Header encoding
*
* @var string
*/
protected $encoding = 'ASCII';
/**
* @var array
*/
protected $parameters = [];
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'content-type') {
throw new Exception\InvalidArgumentException('Invalid header line for Content-Type string');
}
$value = str_replace(Headers::FOLDING, ' ', $value);
$parts = explode(';', $value, 2);
$header = new static();
$header->setType($parts[0]);
if (isset($parts[1])) {
$values = ListParser::parse(trim($parts[1]), [';', '=']);
$length = count($values);
for ($i = 0; $i < $length; $i += 2) {
$value = $values[$i + 1];
$value = trim($value, "'\" \t\n\r\0\x0B");
$header->addParameter($values[$i], $value);
}
}
return $header;
}
public function getFieldName()
{
return 'Content-Type';
}
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
$prepared = $this->type;
if (empty($this->parameters)) {
return $prepared;
}
$values = [$prepared];
foreach ($this->parameters as $attribute => $value) {
if (HeaderInterface::FORMAT_ENCODED === $format && ! Mime::isPrintable($value)) {
$this->encoding = 'UTF-8';
$value = HeaderWrap::wrap($value, $this);
$this->encoding = 'ASCII';
}
$values[] = sprintf('%s="%s"', $attribute, $value);
}
return implode(';' . Headers::FOLDING, $values);
}
public function setEncoding($encoding)
{
$this->encoding = $encoding;
return $this;
}
public function getEncoding()
{
return $this->encoding;
}
public function toString()
{
return 'Content-Type: ' . $this->getFieldValue(HeaderInterface::FORMAT_ENCODED);
}
/**
* Set the content type
*
* @param string $type
* @throws Exception\InvalidArgumentException
* @return ContentType
*/
public function setType($type)
{
if (! preg_match('/^[a-z-]+\/[a-z0-9.+-]+$/i', $type)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a value in the format "type/subtype"; received "%s"',
__METHOD__,
(string) $type
));
}
$this->type = $type;
return $this;
}
/**
* Retrieve the content type
*
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* Add a parameter pair
*
* @param string $name
* @param string $value
* @return ContentType
* @throws Exception\InvalidArgumentException for parameter names that do not follow RFC 2822
* @throws Exception\InvalidArgumentException for parameter values that do not follow RFC 2822
*/
public function addParameter($name, $value)
{
$name = trim(strtolower($name));
$value = (string) $value;
if (! HeaderValue::isValid($name)) {
throw new Exception\InvalidArgumentException('Invalid content-type parameter name detected');
}
if (! HeaderWrap::canBeEncoded($value)) {
throw new Exception\InvalidArgumentException(
'Parameter value must be composed of printable US-ASCII or UTF-8 characters.'
);
}
$this->parameters[$name] = $value;
return $this;
}
/**
* Get all parameters
*
* @return array
*/
public function getParameters()
{
return $this->parameters;
}
/**
* Get a parameter by name
*
* @param string $name
* @return null|string
*/
public function getParameter($name)
{
$name = strtolower($name);
if (isset($this->parameters[$name])) {
return $this->parameters[$name];
}
return;
}
/**
* Remove a named parameter
*
* @param string $name
* @return bool
*/
public function removeParameter($name)
{
$name = strtolower($name);
if (isset($this->parameters[$name])) {
unset($this->parameters[$name]);
return true;
}
return false;
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
/**
* @todo Add accessors for setting date from DateTime, Laminas\Date, or a string
*/
class Date implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'date') {
throw new Exception\InvalidArgumentException('Invalid header line for Date string');
}
$header = new static($value);
return $header;
}
public function __construct($value)
{
if (! HeaderValue::isValid($value)) {
throw new Exception\InvalidArgumentException('Invalid Date header value detected');
}
$this->value = $value;
}
public function getFieldName()
{
return 'Date';
}
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
return $this->value;
}
public function setEncoding($encoding)
{
// This header must be always in US-ASCII
return $this;
}
public function getEncoding()
{
return 'ASCII';
}
public function toString()
{
return 'Date: ' . $this->getFieldValue();
}
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header\Exception;
use Laminas\Mail\Exception;
class BadMethodCallException extends Exception\BadMethodCallException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header\Exception;
use Laminas\Mail\Exception\ExceptionInterface as MailException;
interface ExceptionInterface extends MailException
{
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header\Exception;
use Laminas\Mail\Exception;
class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header\Exception;
use Laminas\Mail\Exception;
class RuntimeException extends Exception\RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
class From extends AbstractAddressList
{
protected $fieldName = 'From';
protected static $type = 'from';
}

View File

@@ -0,0 +1,198 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
use Laminas\Mime\Mime;
class GenericHeader implements HeaderInterface, UnstructuredInterface
{
/**
* @var string
*/
protected $fieldName = null;
/**
* @var string
*/
protected $fieldValue = null;
/**
* Header encoding
*
* @var null|string
*/
protected $encoding;
/**
* @param string $headerLine
* @return GenericHeader
*/
public static function fromString($headerLine)
{
list($name, $value) = self::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
$header = new static($name, $value);
return $header;
}
/**
* Splits the header line in `name` and `value` parts.
*
* @param string $headerLine
* @return string[] `name` in the first index and `value` in the second.
* @throws Exception\InvalidArgumentException If header does not match with the format ``name:value``
*/
public static function splitHeaderLine($headerLine)
{
$parts = explode(':', $headerLine, 2);
if (count($parts) !== 2) {
throw new Exception\InvalidArgumentException('Header must match with the format "name:value"');
}
if (! HeaderName::isValid($parts[0])) {
throw new Exception\InvalidArgumentException('Invalid header name detected');
}
if (! HeaderValue::isValid($parts[1])) {
throw new Exception\InvalidArgumentException('Invalid header value detected');
}
$parts[1] = ltrim($parts[1]);
return $parts;
}
/**
* Constructor
*
* @param string $fieldName Optional
* @param string $fieldValue Optional
*/
public function __construct($fieldName = null, $fieldValue = null)
{
if ($fieldName) {
$this->setFieldName($fieldName);
}
if ($fieldValue !== null) {
$this->setFieldValue($fieldValue);
}
}
/**
* Set header name
*
* @param string $fieldName
* @return GenericHeader
* @throws Exception\InvalidArgumentException;
*/
public function setFieldName($fieldName)
{
if (! is_string($fieldName) || empty($fieldName)) {
throw new Exception\InvalidArgumentException('Header name must be a string');
}
// Pre-filter to normalize valid characters, change underscore to dash
$fieldName = str_replace(' ', '-', ucwords(str_replace(['_', '-'], ' ', $fieldName)));
if (! HeaderName::isValid($fieldName)) {
throw new Exception\InvalidArgumentException(
'Header name must be composed of printable US-ASCII characters, except colon.'
);
}
$this->fieldName = $fieldName;
return $this;
}
public function getFieldName()
{
return $this->fieldName;
}
/**
* Set header value
*
* @param string $fieldValue
* @return GenericHeader
* @throws Exception\InvalidArgumentException;
*/
public function setFieldValue($fieldValue)
{
$fieldValue = (string) $fieldValue;
if (! HeaderWrap::canBeEncoded($fieldValue)) {
throw new Exception\InvalidArgumentException(
'Header value must be composed of printable US-ASCII characters and valid folding sequences.'
);
}
$this->fieldValue = $fieldValue;
$this->encoding = null;
return $this;
}
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
if (HeaderInterface::FORMAT_ENCODED === $format) {
return HeaderWrap::wrap($this->fieldValue, $this);
}
return $this->fieldValue;
}
public function setEncoding($encoding)
{
if ($encoding === $this->encoding) {
return $this;
}
if ($encoding === null) {
$this->encoding = null;
return $this;
}
$encoding = strtoupper($encoding);
if ($encoding === 'UTF-8') {
$this->encoding = $encoding;
return $this;
}
if ($encoding === 'ASCII' && Mime::isPrintable($this->fieldValue)) {
$this->encoding = $encoding;
return $this;
}
$this->encoding = null;
return $this;
}
public function getEncoding()
{
if (! $this->encoding) {
$this->encoding = Mime::isPrintable($this->fieldValue) ? 'ASCII' : 'UTF-8';
}
return $this->encoding;
}
public function toString()
{
$name = $this->getFieldName();
if (empty($name)) {
throw new Exception\RuntimeException('Header name is not set, use setFieldName()');
}
$value = $this->getFieldValue(HeaderInterface::FORMAT_ENCODED);
return $name . ': ' . $value;
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
/**
* Generic class for Headers with multiple occurs in the same message
*/
class GenericMultiHeader extends GenericHeader implements MultipleHeadersInterface
{
public static function fromString($headerLine)
{
list($fieldName, $fieldValue) = GenericHeader::splitHeaderLine($headerLine);
$fieldValue = HeaderWrap::mimeDecodeValue($fieldValue);
if (strpos($fieldValue, ',')) {
$headers = [];
foreach (explode(',', $fieldValue) as $multiValue) {
$headers[] = new static($fieldName, $multiValue);
}
return $headers;
}
return new static($fieldName, $fieldValue);
}
/**
* Cast multiple header objects to a single string header
*
* @param array $headers
* @throws Exception\InvalidArgumentException
* @return string
*/
public function toStringMultipleHeaders(array $headers)
{
$name = $this->getFieldName();
$values = [$this->getFieldValue(HeaderInterface::FORMAT_ENCODED)];
foreach ($headers as $header) {
if (! $header instanceof static) {
throw new Exception\InvalidArgumentException(
'This method toStringMultipleHeaders was expecting an array of headers of the same type'
);
}
$values[] = $header->getFieldValue(HeaderInterface::FORMAT_ENCODED);
}
return $name . ': ' . implode(',', $values);
}
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
interface HeaderInterface
{
/**
* Format value in Mime-Encoding (Quoted-Printable). Result is valid US-ASCII string
*
* @var bool
*/
const FORMAT_ENCODED = true;
/**
* Return value in internal encoding which is usually UTF-8
*
* @var bool
*/
const FORMAT_RAW = false;
/**
* Factory to generate a header object from a string
*
* @param string $headerLine
* @return static
* @throws Exception\InvalidArgumentException If the header does not match with RFC 2822 definition.
* @see http://tools.ietf.org/html/rfc2822#section-2.2
*/
public static function fromString($headerLine);
/**
* Retrieve header name
*
* @return string
*/
public function getFieldName();
/**
* Retrieve header value
*
* @param bool $format Return the value in Mime::Encoded or in Raw format
* @return string
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW);
/**
* Set header encoding
*
* @param string $encoding
* @return $this
*/
public function setEncoding($encoding);
/**
* Get header encoding
*
* @return string
*/
public function getEncoding();
/**
* Cast to string
*
* Returns in form of "NAME: VALUE"
*
* @return string
*/
public function toString();
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
use Laminas\Loader\PluginClassLoader;
/**
* Plugin Class Loader implementation for HTTP headers
*/
class HeaderLoader extends PluginClassLoader
{
/**
* @var array Pre-aliased Header plugins
*/
protected $plugins = [
'bcc' => Bcc::class,
'cc' => Cc::class,
'contentdisposition' => ContentDisposition::class,
'content_disposition' => ContentDisposition::class,
'content-disposition' => ContentDisposition::class,
'contenttype' => ContentType::class,
'content_type' => ContentType::class,
'content-type' => ContentType::class,
'contenttransferencoding' => ContentTransferEncoding::class,
'content_transfer_encoding' => ContentTransferEncoding::class,
'content-transfer-encoding' => ContentTransferEncoding::class,
'date' => Date::class,
'from' => From::class,
'in-reply-to' => InReplyTo::class,
'message-id' => MessageId::class,
'mimeversion' => MimeVersion::class,
'mime_version' => MimeVersion::class,
'mime-version' => MimeVersion::class,
'received' => Received::class,
'references' => References::class,
'replyto' => ReplyTo::class,
'reply_to' => ReplyTo::class,
'reply-to' => ReplyTo::class,
'sender' => Sender::class,
'subject' => Subject::class,
'to' => To::class,
];
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\Mail\Header;
/**
* Plugin Class Loader implementation for HTTP headers
*/
final class HeaderLocator implements HeaderLocatorInterface
{
/**
* @var array Pre-aliased Header plugins
*/
private $plugins = [
'bcc' => Bcc::class,
'cc' => Cc::class,
'contentdisposition' => ContentDisposition::class,
'content_disposition' => ContentDisposition::class,
'content-disposition' => ContentDisposition::class,
'contenttype' => ContentType::class,
'content_type' => ContentType::class,
'content-type' => ContentType::class,
'contenttransferencoding' => ContentTransferEncoding::class,
'content_transfer_encoding' => ContentTransferEncoding::class,
'content-transfer-encoding' => ContentTransferEncoding::class,
'date' => Date::class,
'from' => From::class,
'in-reply-to' => InReplyTo::class,
'message-id' => MessageId::class,
'mimeversion' => MimeVersion::class,
'mime_version' => MimeVersion::class,
'mime-version' => MimeVersion::class,
'received' => Received::class,
'references' => References::class,
'replyto' => ReplyTo::class,
'reply_to' => ReplyTo::class,
'reply-to' => ReplyTo::class,
'sender' => Sender::class,
'subject' => Subject::class,
'to' => To::class,
];
public function get(string $name, ?string $default = null): ?string
{
$name = $this->normalizeName($name);
return isset($this->plugins[$name]) ? $this->plugins[$name] : $default;
}
public function has(string $name): bool
{
return isset($this->plugins[$this->normalizeName($name)]);
}
public function add(string $name, string $class): void
{
$this->plugins[$this->normalizeName($name)] = $class;
}
public function remove(string $name): void
{
unset($this->plugins[$this->normalizeName($name)]);
}
private function normalizeName(string $name): string
{
return strtolower($name);
}
}

View File

@@ -0,0 +1,25 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\Mail\Header;
/**
* Interface detailing how to resolve header names to classes.
*/
interface HeaderLocatorInterface
{
public function get(string $name, ?string $default = null): ?string;
public function has(string $name): bool;
public function add(string $name, string $class): void;
public function remove(string $name): void;
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
final class HeaderName
{
/**
* No public constructor.
*/
private function __construct()
{
}
/**
* Filter the header name according to RFC 2822
*
* @see http://www.rfc-base.org/txt/rfc-2822.txt (section 2.2)
* @param string $name
* @return string
*/
public static function filter($name)
{
$result = '';
$tot = strlen($name);
for ($i = 0; $i < $tot; $i += 1) {
$ord = ord($name[$i]);
if ($ord > 32 && $ord < 127 && $ord !== 58) {
$result .= $name[$i];
}
}
return $result;
}
/**
* Determine if the header name contains any invalid characters.
*
* @param string $name
* @return bool
*/
public static function isValid($name)
{
$tot = strlen($name);
for ($i = 0; $i < $tot; $i += 1) {
$ord = ord($name[$i]);
if ($ord < 33 || $ord > 126 || $ord === 58) {
return false;
}
}
return true;
}
/**
* Assert that the header name is valid.
*
* Raises an exception if invalid.
*
* @param string $name
* @throws Exception\RuntimeException
* @return void
*/
public static function assertValid($name)
{
if (! self::isValid($name)) {
throw new Exception\RuntimeException('Invalid header name detected');
}
}
}

View File

@@ -0,0 +1,116 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
final class HeaderValue
{
/**
* No public constructor.
*/
private function __construct()
{
}
/**
* Filter the header value according to RFC 2822
*
* @see http://www.rfc-base.org/txt/rfc-2822.txt (section 2.2)
* @param string $value
* @return string
*/
public static function filter($value)
{
$result = '';
$total = strlen($value);
// Filter for CR and LF characters, leaving CRLF + WSP sequences for
// Long Header Fields (section 2.2.3 of RFC 2822)
for ($i = 0; $i < $total; $i += 1) {
$ord = ord($value[$i]);
if ($ord === 10 || $ord > 127) {
continue;
}
if ($ord === 13) {
if ($i + 2 >= $total) {
continue;
}
$lf = ord($value[$i + 1]);
$sp = ord($value[$i + 2]);
if ($lf !== 10 || $sp !== 32) {
continue;
}
$result .= "\r\n ";
$i += 2;
continue;
}
$result .= $value[$i];
}
return $result;
}
/**
* Determine if the header value contains any invalid characters.
*
* @see http://www.rfc-base.org/txt/rfc-2822.txt (section 2.2)
* @param string $value
* @return bool
*/
public static function isValid($value)
{
$total = strlen($value);
for ($i = 0; $i < $total; $i += 1) {
$ord = ord($value[$i]);
// bare LF means we aren't valid
if ($ord === 10 || $ord > 127) {
return false;
}
if ($ord === 13) {
if ($i + 2 >= $total) {
return false;
}
$lf = ord($value[$i + 1]);
$sp = ord($value[$i + 2]);
if ($lf !== 10 || ! in_array($sp, [9, 32], true)) {
return false;
}
// skip over the LF following this
$i += 2;
}
}
return true;
}
/**
* Assert that the header value is valid.
*
* Raises an exception if invalid.
*
* @param string $value
* @throws Exception\RuntimeException
* @return void
*/
public static function assertValid($value)
{
if (! self::isValid($value)) {
throw new Exception\RuntimeException('Invalid header value detected');
}
}
}

View File

@@ -0,0 +1,161 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
use Laminas\Mail\Headers;
use Laminas\Mime\Mime;
/**
* Utility class used for creating wrapped or MIME-encoded versions of header
* values.
*/
abstract class HeaderWrap
{
/**
* Wrap a long header line
*
* @param string $value
* @param HeaderInterface $header
* @return string
*/
public static function wrap($value, HeaderInterface $header)
{
if ($header instanceof UnstructuredInterface) {
return static::wrapUnstructuredHeader($value, $header);
} elseif ($header instanceof StructuredInterface) {
return static::wrapStructuredHeader($value, $header);
}
return $value;
}
/**
* Wrap an unstructured header line
*
* Wrap at 78 characters or before, based on whitespace.
*
* @param string $value
* @param HeaderInterface $header
* @return string
*/
protected static function wrapUnstructuredHeader($value, HeaderInterface $header)
{
$encoding = $header->getEncoding();
if ($encoding == 'ASCII') {
return wordwrap($value, 78, Headers::FOLDING);
}
return static::mimeEncodeValue($value, $encoding, 78);
}
/**
* Wrap a structured header line
*
* @param string $value
* @param StructuredInterface $header
* @return string
*/
protected static function wrapStructuredHeader($value, StructuredInterface $header)
{
$delimiter = $header->getDelimiter();
$length = strlen($value);
$lines = [];
$temp = '';
for ($i = 0; $i < $length; $i++) {
$temp .= $value[$i];
if ($value[$i] == $delimiter) {
$lines[] = $temp;
$temp = '';
}
}
return implode(Headers::FOLDING, $lines);
}
/**
* MIME-encode a value
*
* Performs quoted-printable encoding on a value, setting maximum
* line-length to 998.
*
* @param string $value
* @param string $encoding
* @param int $lineLength maximum line-length, by default 998
* @return string Returns the mime encode value without the last line ending
*/
public static function mimeEncodeValue($value, $encoding, $lineLength = 998)
{
return Mime::encodeQuotedPrintableHeader($value, $encoding, $lineLength, Headers::EOL);
}
/**
* MIME-decode a value
*
* Performs quoted-printable decoding on a value.
*
* @param string $value
* @return string Returns the mime encode value without the last line ending
*/
public static function mimeDecodeValue($value)
{
// unfold first, because iconv_mime_decode is discarding "\n" with no apparent reason
// making the resulting value no longer valid.
// see https://tools.ietf.org/html/rfc2822#section-2.2.3 about unfolding
$parts = explode(Headers::FOLDING, $value);
$value = implode(' ', $parts);
$decodedValue = iconv_mime_decode($value, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, 'UTF-8');
// imap (unlike iconv) can handle multibyte headers which are splitted across multiple line
if (self::isNotDecoded($value, $decodedValue) && extension_loaded('imap')) {
return array_reduce(
imap_mime_header_decode(imap_utf8($value)),
function ($accumulator, $headerPart) {
return $accumulator . $headerPart->text;
},
''
);
}
return $decodedValue;
}
private static function isNotDecoded($originalValue, $value)
{
return 0 === strpos($value, '=?')
&& strlen($value) - 2 === strpos($value, '?=')
&& false !== strpos($originalValue, $value);
}
/**
* Test if is possible apply MIME-encoding
*
* @param string $value
* @return bool
*/
public static function canBeEncoded($value)
{
// avoid any wrapping by specifying line length long enough
// "test" -> 4
// "x-test: =?ISO-8859-1?B?dGVzdA==?=" -> 33
// 8 +2 +3 +3 -> 16
$charset = 'UTF-8';
$lineLength = strlen($value) * 4 + strlen($charset) + 16;
$preferences = [
'scheme' => 'Q',
'input-charset' => $charset,
'output-charset' => $charset,
'line-length' => $lineLength,
];
$encoded = iconv_mime_encode('x-test', $value, $preferences);
return (false !== $encoded);
}
}

View File

@@ -0,0 +1,143 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
use Laminas\Mail\Headers;
/**
* @see https://tools.ietf.org/html/rfc5322#section-3.6.4
*/
abstract class IdentificationField implements HeaderInterface
{
/**
* @var string lower case field name
*/
protected static $type;
/**
* @var string[]
*/
protected $messageIds;
/**
* @var string
*/
protected $fieldName;
/**
* @param string $headerLine
* @return static
*/
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
if (strtolower($name) !== static::$type) {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for "%s" string',
__CLASS__
));
}
$value = HeaderWrap::mimeDecodeValue($value);
$messageIds = array_map(
[IdentificationField::class, "trimMessageId"],
explode(" ", $value)
);
$header = new static();
$header->setIds($messageIds);
return $header;
}
/**
* @param string $id
* @return string
*/
private static function trimMessageId($id)
{
return trim($id, "\t\n\r\0\x0B<>");
}
/**
* @return string
*/
public function getFieldName()
{
return $this->fieldName;
}
/**
* @param bool $format
* @return string
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
return implode(Headers::FOLDING, array_map(function ($id) {
return sprintf('<%s>', $id);
}, $this->messageIds));
}
/**
* @param string $encoding Ignored; headers of this type MUST always be in
* ASCII.
* @return static This method is a no-op, and implements a fluent interface.
*/
public function setEncoding($encoding)
{
return $this;
}
/**
* @return string Always returns ASCII
*/
public function getEncoding()
{
return 'ASCII';
}
/**
* @return string
*/
public function toString()
{
return sprintf('%s: %s', $this->getFieldName(), $this->getFieldValue());
}
/**
* Set the message ids
*
* @param string[] $ids
* @return static This method implements a fluent interface.
*/
public function setIds($ids)
{
foreach ($ids as $id) {
if (! HeaderValue::isValid($id)
|| preg_match("/[\r\n]/", $id)
) {
throw new Exception\InvalidArgumentException('Invalid ID detected');
}
}
$this->messageIds = array_map([IdentificationField::class, "trimMessageId"], $ids);
return $this;
}
/**
* Retrieve the message ids
*
* @return string[]
*/
public function getIds()
{
return $this->messageIds;
}
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
class InReplyTo extends IdentificationField
{
protected $fieldName = 'In-Reply-To';
protected static $type = 'in-reply-to';
}

View File

@@ -0,0 +1,99 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
use function in_array;
/**
* @internal
*/
class ListParser
{
const CHAR_QUOTES = ['\'', '"'];
const CHAR_DELIMS = [',', ';'];
const CHAR_ESCAPE = '\\';
/**
* @param string $value
* @param array $delims Delimiters allowed between values; parser will
* split on these, as long as they are not within quotes. Defaults
* to ListParser::CHAR_DELIMS.
* @return array
*/
public static function parse($value, array $delims = self::CHAR_DELIMS)
{
$values = [];
$length = strlen($value);
$currentValue = '';
$inEscape = false;
$inQuote = false;
$currentQuoteDelim = null;
for ($i = 0; $i < $length; $i += 1) {
$char = $value[$i];
// If we are in an escape sequence, append the character and continue.
if ($inEscape) {
$currentValue .= $char;
$inEscape = false;
continue;
}
// If we are not in a quoted string, and have a delimiter, append
// the current value to the list, and reset the current value.
if (in_array($char, $delims, true) && ! $inQuote) {
$values [] = $currentValue;
$currentValue = '';
continue;
}
// Append the character to the current value
$currentValue .= $char;
// Escape sequence discovered.
if (self::CHAR_ESCAPE === $char) {
$inEscape = true;
continue;
}
// If the character is not a quote character, we are done
// processing it.
if (! in_array($char, self::CHAR_QUOTES)) {
continue;
}
// If the character matches a previously matched quote delimiter,
// we reset our quote status and the currently opened quote
// delimiter.
if ($char === $currentQuoteDelim) {
$inQuote = false;
$currentQuoteDelim = null;
continue;
}
// If already in quote and the character does not match the previously
// matched quote delimiter, we're done here.
if ($inQuote) {
continue;
}
// Otherwise, we're starting a quoted string.
$inQuote = true;
$currentQuoteDelim = $char;
}
// If we reached the end of the string and still have a current value,
// append it to the list (no delimiter was reached).
if ('' !== $currentValue) {
$values [] = $currentValue;
}
return $values;
}
}

View File

@@ -0,0 +1,119 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
class MessageId implements HeaderInterface
{
/**
* @var string
*/
protected $messageId;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'message-id') {
throw new Exception\InvalidArgumentException('Invalid header line for Message-ID string');
}
$header = new static();
$header->setId($value);
return $header;
}
public function getFieldName()
{
return 'Message-ID';
}
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
return $this->messageId;
}
public function setEncoding($encoding)
{
// This header must be always in US-ASCII
return $this;
}
public function getEncoding()
{
return 'ASCII';
}
public function toString()
{
return 'Message-ID: ' . $this->getFieldValue();
}
/**
* Set the message id
*
* @param string|null $id
* @return MessageId
*/
public function setId($id = null)
{
if ($id === null) {
$id = $this->createMessageId();
} else {
$id = trim($id, '<>');
}
if (! HeaderValue::isValid($id)
|| preg_match("/[\r\n]/", $id)
) {
throw new Exception\InvalidArgumentException('Invalid ID detected');
}
$this->messageId = sprintf('<%s>', $id);
return $this;
}
/**
* Retrieve the message id
*
* @return string
*/
public function getId()
{
return $this->messageId;
}
/**
* Creates the Message-ID
*
* @return string
*/
public function createMessageId()
{
$time = time();
if (isset($_SERVER['REMOTE_ADDR'])) {
$user = $_SERVER['REMOTE_ADDR'];
} else {
$user = getmypid();
}
$rand = mt_rand();
if (isset($_SERVER["SERVER_NAME"])) {
$hostName = $_SERVER["SERVER_NAME"];
} else {
$hostName = php_uname('n');
}
return sha1($time . $user . $rand) . '@' . $hostName;
}
}

View File

@@ -0,0 +1,87 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
class MimeVersion implements HeaderInterface
{
/**
* @var string Version string
*/
protected $version = '1.0';
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'mime-version') {
throw new Exception\InvalidArgumentException('Invalid header line for MIME-Version string');
}
// Check for version, and set if found
$header = new static();
if (preg_match('/^(?P<version>\d+\.\d+)$/', $value, $matches)) {
$header->setVersion($matches['version']);
}
return $header;
}
public function getFieldName()
{
return 'MIME-Version';
}
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
return $this->version;
}
public function setEncoding($encoding)
{
// This header must be always in US-ASCII
return $this;
}
public function getEncoding()
{
return 'ASCII';
}
public function toString()
{
return 'MIME-Version: ' . $this->getFieldValue();
}
/**
* Set the version string used in this header
*
* @param string $version
* @return MimeVersion
*/
public function setVersion($version)
{
if (! preg_match('/^[1-9]\d*\.\d+$/', $version)) {
throw new Exception\InvalidArgumentException('Invalid MIME-Version value detected');
}
$this->version = $version;
return $this;
}
/**
* Retrieve the version string for this header
*
* @return string
*/
public function getVersion()
{
return $this->version;
}
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
interface MultipleHeadersInterface extends HeaderInterface
{
public function toStringMultipleHeaders(array $headers);
}

View File

@@ -0,0 +1,92 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
use Laminas\Mail\Headers;
/**
* @todo Allow setting date from DateTime, Laminas\Date, or string
*/
class Received implements HeaderInterface, MultipleHeadersInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'received') {
throw new Exception\InvalidArgumentException('Invalid header line for Received string');
}
$header = new static($value);
return $header;
}
public function __construct($value = '')
{
if (! HeaderValue::isValid($value)) {
throw new Exception\InvalidArgumentException('Invalid Received value provided');
}
$this->value = $value;
}
public function getFieldName()
{
return 'Received';
}
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
return $this->value;
}
public function setEncoding($encoding)
{
// This header must be always in US-ASCII
return $this;
}
public function getEncoding()
{
return 'ASCII';
}
public function toString()
{
return 'Received: ' . $this->getFieldValue();
}
/**
* Serialize collection of Received headers to string
*
* @param array $headers
* @throws Exception\RuntimeException
* @return string
*/
public function toStringMultipleHeaders(array $headers)
{
$strings = [$this->toString()];
foreach ($headers as $header) {
if (! $header instanceof Received) {
throw new Exception\RuntimeException(
'The Received multiple header implementation can only accept an array of Received headers'
);
}
$strings[] = $header->toString();
}
return implode(Headers::EOL, $strings);
}
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
class References extends IdentificationField
{
protected $fieldName = 'References';
protected static $type = 'references';
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
class ReplyTo extends AbstractAddressList
{
protected $fieldName = 'Reply-To';
protected static $type = 'reply-to';
}

View File

@@ -0,0 +1,153 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
use Laminas\Mail;
use Laminas\Mime\Mime;
/**
* Sender header class methods.
*
* @see https://tools.ietf.org/html/rfc2822 RFC 2822
* @see https://tools.ietf.org/html/rfc2047 RFC 2047
*/
class Sender implements HeaderInterface
{
/**
* @var \Laminas\Mail\Address\AddressInterface
*/
protected $address;
/**
* Header encoding
*
* @var null|string
*/
protected $encoding;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'sender') {
throw new Exception\InvalidArgumentException('Invalid header name for Sender string');
}
$header = new static();
/**
* matches the header value so that the email must be enclosed by < > when a name is present
* 'name' and 'email' capture groups correspond respectively to 'display-name' and 'addr-spec' in the ABNF
* @see https://tools.ietf.org/html/rfc5322#section-3.4
*/
$hasMatches = preg_match(
'/^(?:(?P<name>.+)\s)?(?(name)<|<?)(?P<email>[^\s]+?)(?(name)>|>?)$/',
$value,
$matches
);
if ($hasMatches !== 1) {
throw new Exception\InvalidArgumentException('Invalid header value for Sender string');
}
$senderName = trim($matches['name']);
if (empty($senderName)) {
$senderName = null;
}
$header->setAddress($matches['email'], $senderName);
return $header;
}
public function getFieldName()
{
return 'Sender';
}
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
if (! $this->address instanceof Mail\Address\AddressInterface) {
return '';
}
$email = sprintf('<%s>', $this->address->getEmail());
$name = $this->address->getName();
if (! empty($name)) {
if ($format == HeaderInterface::FORMAT_ENCODED) {
$encoding = $this->getEncoding();
if ('ASCII' !== $encoding) {
$name = HeaderWrap::mimeEncodeValue($name, $encoding);
}
}
$email = sprintf('%s %s', $name, $email);
}
return $email;
}
public function setEncoding($encoding)
{
$this->encoding = $encoding;
return $this;
}
public function getEncoding()
{
if (! $this->encoding) {
$this->encoding = Mime::isPrintable($this->getFieldValue(HeaderInterface::FORMAT_RAW))
? 'ASCII'
: 'UTF-8';
}
return $this->encoding;
}
public function toString()
{
return 'Sender: ' . $this->getFieldValue(HeaderInterface::FORMAT_ENCODED);
}
/**
* Set the address used in this header
*
* @param string|\Laminas\Mail\Address\AddressInterface $emailOrAddress
* @param null|string $name
* @throws Exception\InvalidArgumentException
* @return Sender
*/
public function setAddress($emailOrAddress, $name = null)
{
if (is_string($emailOrAddress)) {
$emailOrAddress = new Mail\Address($emailOrAddress, $name);
} elseif (! $emailOrAddress instanceof Mail\Address\AddressInterface) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a string or AddressInterface object; received "%s"',
__METHOD__,
(is_object($emailOrAddress) ? get_class($emailOrAddress) : gettype($emailOrAddress))
));
}
$this->address = $emailOrAddress;
return $this;
}
/**
* Retrieve the internal address from this header
*
* @return \Laminas\Mail\Address\AddressInterface|null
*/
public function getAddress()
{
return $this->address;
}
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
interface StructuredInterface extends HeaderInterface
{
/**
* Return the delimiter at which a header line should be wrapped
*
* @return string
*/
public function getDelimiter();
}

View File

@@ -0,0 +1,119 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
use Laminas\Mime\Mime;
/**
* Subject header class methods.
*
* @see https://tools.ietf.org/html/rfc2822 RFC 2822
* @see https://tools.ietf.org/html/rfc2047 RFC 2047
*/
class Subject implements UnstructuredInterface
{
/**
* @var string
*/
protected $subject = '';
/**
* Header encoding
*
* @var null|string
*/
protected $encoding;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
$value = HeaderWrap::mimeDecodeValue($value);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'subject') {
throw new Exception\InvalidArgumentException('Invalid header line for Subject string');
}
$header = new static();
$header->setSubject($value);
return $header;
}
public function getFieldName()
{
return 'Subject';
}
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
if (HeaderInterface::FORMAT_ENCODED === $format) {
return HeaderWrap::wrap($this->subject, $this);
}
return $this->subject;
}
public function setEncoding($encoding)
{
if ($encoding === $this->encoding) {
return $this;
}
if ($encoding === null) {
$this->encoding = null;
return $this;
}
$encoding = strtoupper($encoding);
if ($encoding === 'UTF-8') {
$this->encoding = $encoding;
return $this;
}
if ($encoding === 'ASCII' && Mime::isPrintable($this->subject)) {
$this->encoding = $encoding;
return $this;
}
$this->encoding = null;
return $this;
}
public function getEncoding()
{
if (! $this->encoding) {
$this->encoding = Mime::isPrintable($this->subject) ? 'ASCII' : 'UTF-8';
}
return $this->encoding;
}
public function setSubject($subject)
{
$subject = (string) $subject;
if (! HeaderWrap::canBeEncoded($subject)) {
throw new Exception\InvalidArgumentException(
'Subject value must be composed of printable US-ASCII or UTF-8 characters.'
);
}
$this->subject = $subject;
$this->encoding = null;
return $this;
}
public function toString()
{
return 'Subject: ' . $this->getFieldValue(HeaderInterface::FORMAT_ENCODED);
}
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
class To extends AbstractAddressList
{
protected $fieldName = 'To';
protected static $type = 'to';
}

View File

@@ -0,0 +1,16 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Header;
/**
* Marker interface for unstructured headers.
*/
interface UnstructuredInterface extends HeaderInterface
{
}

View File

@@ -0,0 +1,606 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\Mail;
use ArrayIterator;
use Countable;
use Iterator;
use Laminas\Loader\PluginClassLoader;
use Laminas\Loader\PluginClassLocator;
use Laminas\Mail\Header\GenericHeader;
use Laminas\Mail\Header\HeaderInterface;
use Traversable;
/**
* Basic mail headers collection functionality
*
* Handles aggregation of headers
*/
class Headers implements Countable, Iterator
{
/** @var string End of Line for fields */
const EOL = "\r\n";
/** @var string Start of Line when folding */
const FOLDING = "\r\n ";
/**
* @var null|Header\HeaderLocatorInterface
*/
private $headerLocator;
/**
* @todo Remove for 3.0.0.
* @var null|PluginClassLocator
*/
protected $pluginClassLoader;
/**
* @var array key names for $headers array
*/
protected $headersKeys = [];
/**
* @var Header\HeaderInterface[] instances
*/
protected $headers = [];
/**
* Header encoding; defaults to ASCII
*
* @var string
*/
protected $encoding = 'ASCII';
/**
* Populates headers from string representation
*
* Parses a string for headers, and aggregates them, in order, in the
* current instance, primarily as strings until they are needed (they
* will be lazy loaded)
*
* @param string $string
* @param string $EOL EOL string; defaults to {@link EOL}
* @throws Exception\RuntimeException
* @return Headers
*/
public static function fromString($string, $EOL = self::EOL)
{
$headers = new static();
$currentLine = '';
$emptyLine = 0;
// iterate the header lines, some might be continuations
$lines = explode($EOL, $string);
$total = count($lines);
for ($i = 0; $i < $total; $i += 1) {
$line = $lines[$i];
// Empty line indicates end of headers
// EXCEPT if there are more lines, in which case, there's a possible error condition
if (preg_match('/^\s*$/', $line)) {
$emptyLine += 1;
if ($emptyLine > 2) {
throw new Exception\RuntimeException('Malformed header detected');
}
continue;
}
if ($emptyLine > 1) {
throw new Exception\RuntimeException('Malformed header detected');
}
// check if a header name is present
if (preg_match('/^[\x21-\x39\x3B-\x7E]+:.*$/', $line)) {
if ($currentLine) {
// a header name was present, then store the current complete line
$headers->addHeaderLine($currentLine);
}
$currentLine = trim($line);
continue;
}
// continuation: append to current line
// recover the whitespace that break the line (unfolding, rfc2822#section-2.2.3)
if (preg_match('/^\s+.*$/', $line)) {
$currentLine .= ' ' . trim($line);
continue;
}
// Line does not match header format!
throw new Exception\RuntimeException(sprintf(
'Line "%s" does not match header format!',
$line
));
}
if ($currentLine) {
$headers->addHeaderLine($currentLine);
}
return $headers;
}
/**
* Set an alternate PluginClassLocator implementation for loading header classes.
*
* @deprecated since 2.12.0
* @todo Remove for version 3.0.0
* @return $this
*/
public function setPluginClassLoader(PluginClassLocator $pluginClassLoader)
{
// Silenced; can be caught in custom error handlers.
@trigger_error(sprintf(
'Since laminas/laminas-mail 2.12.0: Usage of %s is deprecated; use %s::setHeaderLocator() instead',
__METHOD__,
__CLASS__
), E_USER_DEPRECATED);
$this->pluginClassLoader = $pluginClassLoader;
return $this;
}
/**
* Return a PluginClassLocator instance for customizing headers.
*
* Lazyloads a Header\HeaderLoader if necessary.
*
* @deprecated since 2.12.0
* @todo Remove for version 3.0.0
* @return PluginClassLocator
*/
public function getPluginClassLoader()
{
// Silenced; can be caught in custom error handlers.
@trigger_error(sprintf(
'Since laminas/laminas-mail 2.12.0: Usage of %s is deprecated; use %s::getHeaderLocator() instead',
__METHOD__,
__CLASS__
), E_USER_DEPRECATED);
if (! $this->pluginClassLoader) {
$this->pluginClassLoader = new Header\HeaderLoader();
}
return $this->pluginClassLoader;
}
/**
* Retrieve the header class locator for customizing headers.
*
* Lazyloads a Header\HeaderLocator instance if necessary.
*/
public function getHeaderLocator(): Header\HeaderLocatorInterface
{
if (! $this->headerLocator) {
$this->setHeaderLocator(new Header\HeaderLocator());
}
return $this->headerLocator;
}
/**
* @todo Return self when we update to 7.4 or later as minimum PHP version.
* @return $this
*/
public function setHeaderLocator(Header\HeaderLocatorInterface $headerLocator)
{
$this->headerLocator = $headerLocator;
return $this;
}
/**
* Set the header encoding
*
* @param string $encoding
* @return Headers
*/
public function setEncoding($encoding)
{
$this->encoding = $encoding;
foreach ($this as $header) {
$header->setEncoding($encoding);
}
return $this;
}
/**
* Get the header encoding
*
* @return string
*/
public function getEncoding()
{
return $this->encoding;
}
/**
* Add many headers at once
*
* Expects an array (or Traversable object) of type/value pairs.
*
* @param array|Traversable $headers
* @throws Exception\InvalidArgumentException
* @return Headers
*/
public function addHeaders($headers)
{
if (! is_array($headers) && ! $headers instanceof Traversable) {
throw new Exception\InvalidArgumentException(sprintf(
'Expected array or Traversable; received "%s"',
(is_object($headers) ? get_class($headers) : gettype($headers))
));
}
foreach ($headers as $name => $value) {
if (is_int($name)) {
if (is_string($value)) {
$this->addHeaderLine($value);
} elseif (is_array($value) && count($value) == 1) {
$this->addHeaderLine(key($value), current($value));
} elseif (is_array($value) && count($value) == 2) {
$this->addHeaderLine($value[0], $value[1]);
} elseif ($value instanceof Header\HeaderInterface) {
$this->addHeader($value);
}
} elseif (is_string($name)) {
$this->addHeaderLine($name, $value);
}
}
return $this;
}
/**
* Add a raw header line, either in name => value, or as a single string 'name: value'
*
* This method allows for lazy-loading in that the parsing and instantiation of HeaderInterface object
* will be delayed until they are retrieved by either get() or current()
*
* @throws Exception\InvalidArgumentException
* @param string $headerFieldNameOrLine
* @param string $fieldValue optional
* @return Headers
*/
public function addHeaderLine($headerFieldNameOrLine, $fieldValue = null)
{
if (! is_string($headerFieldNameOrLine)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects its first argument to be a string; received "%s"',
__METHOD__,
(is_object($headerFieldNameOrLine)
? get_class($headerFieldNameOrLine)
: gettype($headerFieldNameOrLine))
));
}
if ($fieldValue === null) {
$headers = $this->loadHeader($headerFieldNameOrLine);
$headers = is_array($headers) ? $headers : [$headers];
foreach ($headers as $header) {
$this->addHeader($header);
}
} elseif (is_array($fieldValue)) {
foreach ($fieldValue as $i) {
$this->addHeader(Header\GenericMultiHeader::fromString($headerFieldNameOrLine . ':' . $i));
}
} else {
$this->addHeader(Header\GenericHeader::fromString($headerFieldNameOrLine . ':' . $fieldValue));
}
return $this;
}
/**
* Add a Header\Interface to this container, for raw values see {@link addHeaderLine()} and {@link addHeaders()}
*
* @param Header\HeaderInterface $header
* @return Headers
*/
public function addHeader(Header\HeaderInterface $header)
{
$key = $this->normalizeFieldName($header->getFieldName());
$this->headersKeys[] = $key;
$this->headers[] = $header;
if ($this->getEncoding() !== 'ASCII') {
$header->setEncoding($this->getEncoding());
}
return $this;
}
/**
* Remove a Header from the container
*
* @param string|Header\HeaderInterface field name or specific header instance to remove
* @return bool
*/
public function removeHeader($instanceOrFieldName)
{
if (! $instanceOrFieldName instanceof Header\HeaderInterface && ! is_string($instanceOrFieldName)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s requires a string or %s instance; received %s',
__METHOD__,
Header\HeaderInterface::class,
is_object($instanceOrFieldName) ? get_class($instanceOrFieldName) : gettype($instanceOrFieldName)
));
}
if ($instanceOrFieldName instanceof Header\HeaderInterface) {
$indexes = array_keys($this->headers, $instanceOrFieldName, true);
}
if (is_string($instanceOrFieldName)) {
$key = $this->normalizeFieldName($instanceOrFieldName);
$indexes = array_keys($this->headersKeys, $key, true);
}
if (! empty($indexes)) {
foreach ($indexes as $index) {
unset($this->headersKeys[$index]);
unset($this->headers[$index]);
}
return true;
}
return false;
}
/**
* Clear all headers
*
* Removes all headers from queue
*
* @return Headers
*/
public function clearHeaders()
{
$this->headers = $this->headersKeys = [];
return $this;
}
/**
* Get all headers of a certain name/type
*
* @param string $name
* @return bool|ArrayIterator|Header\HeaderInterface Returns false if there is no headers with $name in this
* contain, an ArrayIterator if the header is a MultipleHeadersInterface instance and finally returns
* HeaderInterface for the rest of cases.
*/
public function get($name)
{
$key = $this->normalizeFieldName($name);
$results = [];
foreach (array_keys($this->headersKeys, $key) as $index) {
if ($this->headers[$index] instanceof Header\GenericHeader) {
$results[] = $this->lazyLoadHeader($index);
} else {
$results[] = $this->headers[$index];
}
}
switch (count($results)) {
case 0:
return false;
case 1:
if ($results[0] instanceof Header\MultipleHeadersInterface) {
return new ArrayIterator($results);
} else {
return $results[0];
}
//fall-trough
default:
return new ArrayIterator($results);
}
}
/**
* Test for existence of a type of header
*
* @param string $name
* @return bool
*/
public function has($name)
{
$name = $this->normalizeFieldName($name);
return in_array($name, $this->headersKeys);
}
/**
* Advance the pointer for this object as an iterator
*
*/
public function next()
{
next($this->headers);
}
/**
* Return the current key for this object as an iterator
*
* @return mixed
*/
public function key()
{
return key($this->headers);
}
/**
* Is this iterator still valid?
*
* @return bool
*/
public function valid()
{
return (current($this->headers) !== false);
}
/**
* Reset the internal pointer for this object as an iterator
*
*/
public function rewind()
{
reset($this->headers);
}
/**
* Return the current value for this iterator, lazy loading it if need be
*
* @return Header\HeaderInterface
*/
public function current()
{
$current = current($this->headers);
if ($current instanceof Header\GenericHeader) {
$current = $this->lazyLoadHeader(key($this->headers));
}
return $current;
}
/**
* Return the number of headers in this contain, if all headers have not been parsed, actual count could
* increase if MultipleHeader objects exist in the Request/Response. If you need an exact count, iterate
*
* @return int count of currently known headers
*/
public function count()
{
return count($this->headers);
}
/**
* Render all headers at once
*
* This method handles the normal iteration of headers; it is up to the
* concrete classes to prepend with the appropriate status/request line.
*
* @return string
*/
public function toString()
{
$headers = '';
foreach ($this as $header) {
if ($str = $header->toString()) {
$headers .= $str . self::EOL;
}
}
return $headers;
}
/**
* Return the headers container as an array
*
* @param bool $format Return the values in Mime::Encoded or in Raw format
* @return array
* @todo determine how to produce single line headers, if they are supported
*/
public function toArray($format = Header\HeaderInterface::FORMAT_RAW)
{
$headers = [];
/* @var $header Header\HeaderInterface */
foreach ($this->headers as $header) {
if ($header instanceof Header\MultipleHeadersInterface) {
$name = $header->getFieldName();
if (! isset($headers[$name])) {
$headers[$name] = [];
}
$headers[$name][] = $header->getFieldValue($format);
} else {
$headers[$header->getFieldName()] = $header->getFieldValue($format);
}
}
return $headers;
}
/**
* By calling this, it will force parsing and loading of all headers, after this count() will be accurate
*
* @return bool
*/
public function forceLoading()
{
foreach ($this as $item) {
// $item should now be loaded
}
return true;
}
/**
* Create Header object from header line
*
* @param string $headerLine
* @return Header\HeaderInterface|Header\HeaderInterface[]
*/
public function loadHeader($headerLine)
{
list($name, ) = Header\GenericHeader::splitHeaderLine($headerLine);
/** @var HeaderInterface $class */
$class = $this->resolveHeaderClass($name);
return $class::fromString($headerLine);
}
/**
* @param $index
* @return mixed
*/
protected function lazyLoadHeader($index)
{
$current = $this->headers[$index];
$key = $this->headersKeys[$index];
/** @var GenericHeader $class */
$class = $this->resolveHeaderClass($key);
$encoding = $current->getEncoding();
$headers = $class::fromString($current->toString());
if (is_array($headers)) {
$current = array_shift($headers);
$current->setEncoding($encoding);
$this->headers[$index] = $current;
foreach ($headers as $header) {
$header->setEncoding($encoding);
$this->headersKeys[] = $key;
$this->headers[] = $header;
}
return $current;
}
$current = $headers;
$current->setEncoding($encoding);
$this->headers[$index] = $current;
return $current;
}
/**
* Normalize a field name
*
* @param string $fieldName
* @return string
*/
protected function normalizeFieldName($fieldName)
{
return str_replace(['-', '_', ' ', '.'], '', strtolower($fieldName));
}
/**
* @param string $key
* @return string
*/
private function resolveHeaderClass($key)
{
if ($this->pluginClassLoader) {
return $this->pluginClassLoader->load($key) ?: Header\GenericHeader::class;
}
return $this->getHeaderLocator()->get($key, Header\GenericHeader::class);
}
}

View File

@@ -0,0 +1,576 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail;
use Laminas\Mail\Header\ContentType;
use Laminas\Mail\Header\Sender;
use Laminas\Mime;
use Traversable;
class Message
{
/**
* Content of the message
*
* @var string|object|Mime\Message
*/
protected $body;
/**
* @var Headers
*/
protected $headers;
/**
* Message encoding
*
* Used to determine whether or not to encode headers; defaults to ASCII.
*
* @var string
*/
protected $encoding = 'ASCII';
/**
* Is the message valid?
*
* If we don't any From addresses, we're invalid, according to RFC2822.
*
* @return bool
*/
public function isValid()
{
$from = $this->getFrom();
if (! $from instanceof AddressList) {
return false;
}
return (bool) count($from);
}
/**
* Set the message encoding
*
* @param string $encoding
* @return Message
*/
public function setEncoding($encoding)
{
$this->encoding = $encoding;
$this->getHeaders()->setEncoding($encoding);
return $this;
}
/**
* Get the message encoding
*
* @return string
*/
public function getEncoding()
{
return $this->encoding;
}
/**
* Compose headers
*
* @param Headers $headers
* @return Message
*/
public function setHeaders(Headers $headers)
{
$this->headers = $headers;
$headers->setEncoding($this->getEncoding());
return $this;
}
/**
* Access headers collection
*
* Lazy-loads if not already attached.
*
* @return Headers
*/
public function getHeaders()
{
if (null === $this->headers) {
$this->setHeaders(new Headers());
$date = Header\Date::fromString('Date: ' . date('r'));
$this->headers->addHeader($date);
}
return $this->headers;
}
/**
* Set (overwrite) From addresses
*
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList
* @param string|null $name
* @return Message
*/
public function setFrom($emailOrAddressList, $name = null)
{
$this->clearHeaderByName('from');
return $this->addFrom($emailOrAddressList, $name);
}
/**
* Add a "From" address
*
* @param string|Address|array|AddressList|Traversable $emailOrAddressOrList
* @param string|null $name
* @return Message
*/
public function addFrom($emailOrAddressOrList, $name = null)
{
$addressList = $this->getFrom();
$this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__);
return $this;
}
/**
* Retrieve list of From senders
*
* @return AddressList
*/
public function getFrom()
{
return $this->getAddressListFromHeader('from', __NAMESPACE__ . '\Header\From');
}
/**
* Overwrite the address list in the To recipients
*
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList
* @param null|string $name
* @return Message
*/
public function setTo($emailOrAddressList, $name = null)
{
$this->clearHeaderByName('to');
return $this->addTo($emailOrAddressList, $name);
}
/**
* Add one or more addresses to the To recipients
*
* Appends to the list.
*
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressOrList
* @param null|string $name
* @return Message
*/
public function addTo($emailOrAddressOrList, $name = null)
{
$addressList = $this->getTo();
$this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__);
return $this;
}
/**
* Access the address list of the To header
*
* @return AddressList
*/
public function getTo()
{
return $this->getAddressListFromHeader('to', __NAMESPACE__ . '\Header\To');
}
/**
* Set (overwrite) CC addresses
*
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList
* @param string|null $name
* @return Message
*/
public function setCc($emailOrAddressList, $name = null)
{
$this->clearHeaderByName('cc');
return $this->addCc($emailOrAddressList, $name);
}
/**
* Add a "Cc" address
*
* @param string|Address|array|AddressList|Traversable $emailOrAddressOrList
* @param string|null $name
* @return Message
*/
public function addCc($emailOrAddressOrList, $name = null)
{
$addressList = $this->getCc();
$this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__);
return $this;
}
/**
* Retrieve list of CC recipients
*
* @return AddressList
*/
public function getCc()
{
return $this->getAddressListFromHeader('cc', __NAMESPACE__ . '\Header\Cc');
}
/**
* Set (overwrite) BCC addresses
*
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList
* @param string|null $name
* @return Message
*/
public function setBcc($emailOrAddressList, $name = null)
{
$this->clearHeaderByName('bcc');
return $this->addBcc($emailOrAddressList, $name);
}
/**
* Add a "Bcc" address
*
* @param string|Address|array|AddressList|Traversable $emailOrAddressOrList
* @param string|null $name
* @return Message
*/
public function addBcc($emailOrAddressOrList, $name = null)
{
$addressList = $this->getBcc();
$this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__);
return $this;
}
/**
* Retrieve list of BCC recipients
*
* @return AddressList
*/
public function getBcc()
{
return $this->getAddressListFromHeader('bcc', __NAMESPACE__ . '\Header\Bcc');
}
/**
* Overwrite the address list in the Reply-To recipients
*
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList
* @param null|string $name
* @return Message
*/
public function setReplyTo($emailOrAddressList, $name = null)
{
$this->clearHeaderByName('reply-to');
return $this->addReplyTo($emailOrAddressList, $name);
}
/**
* Add one or more addresses to the Reply-To recipients
*
* Appends to the list.
*
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressOrList
* @param null|string $name
* @return Message
*/
public function addReplyTo($emailOrAddressOrList, $name = null)
{
$addressList = $this->getReplyTo();
$this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__);
return $this;
}
/**
* Access the address list of the Reply-To header
*
* @return AddressList
*/
public function getReplyTo()
{
return $this->getAddressListFromHeader('reply-to', __NAMESPACE__ . '\Header\ReplyTo');
}
/**
* setSender
*
* @param mixed $emailOrAddress
* @param mixed $name
* @return Message
*/
public function setSender($emailOrAddress, $name = null)
{
/** @var Sender $header */
$header = $this->getHeaderByName('sender', __NAMESPACE__ . '\Header\Sender');
$header->setAddress($emailOrAddress, $name);
return $this;
}
/**
* Retrieve the sender address, if any
*
* @return null|Address\AddressInterface
*/
public function getSender()
{
$headers = $this->getHeaders();
if (! $headers->has('sender')) {
return null;
}
/** @var Sender $header */
$header = $this->getHeaderByName('sender', __NAMESPACE__ . '\Header\Sender');
return $header->getAddress();
}
/**
* Set the message subject header value
*
* @param string $subject
* @return Message
*/
public function setSubject($subject)
{
$headers = $this->getHeaders();
if (! $headers->has('subject')) {
$header = new Header\Subject();
$headers->addHeader($header);
} else {
$header = $headers->get('subject');
}
$header->setSubject($subject);
$header->setEncoding($this->getEncoding());
return $this;
}
/**
* Get the message subject header value
*
* @return null|string
*/
public function getSubject()
{
$headers = $this->getHeaders();
if (! $headers->has('subject')) {
return;
}
$header = $headers->get('subject');
return $header->getFieldValue();
}
/**
* Set the message body
*
* @param null|string|\Laminas\Mime\Message|object $body
* @throws Exception\InvalidArgumentException
* @return Message
*/
public function setBody($body)
{
if (! is_string($body) && $body !== null) {
if (! is_object($body)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a string or object argument; received "%s"',
__METHOD__,
gettype($body)
));
}
if (! $body instanceof Mime\Message) {
if (! method_exists($body, '__toString')) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects object arguments of type %s or implementing __toString();'
. ' object of type "%s" received',
__METHOD__,
Mime\Message::class,
get_class($body)
));
}
}
}
$this->body = $body;
if (! $this->body instanceof Mime\Message) {
return $this;
}
// Get headers, and set Mime-Version header
$headers = $this->getHeaders();
$this->getHeaderByName('mime-version', __NAMESPACE__ . '\Header\MimeVersion');
// Multipart content headers
if ($this->body->isMultiPart()) {
$mime = $this->body->getMime();
/** @var ContentType $header */
$header = $this->getHeaderByName('content-type', __NAMESPACE__ . '\Header\ContentType');
$header->setType('multipart/mixed');
$header->addParameter('boundary', $mime->boundary());
return $this;
}
// MIME single part headers
$parts = $this->body->getParts();
if (! empty($parts)) {
$part = array_shift($parts);
$headers->addHeaders($part->getHeadersArray("\r\n"));
}
return $this;
}
/**
* Return the currently set message body
*
* @return object|string|Mime\Message
*/
public function getBody()
{
return $this->body;
}
/**
* Get the string-serialized message body text
*
* @return string
*/
public function getBodyText()
{
if ($this->body instanceof Mime\Message) {
return $this->body->generateMessage(Headers::EOL);
}
return (string) $this->body;
}
/**
* Retrieve a header by name
*
* If not found, instantiates one based on $headerClass.
*
* @param string $headerName
* @param string $headerClass
* @return Header\HeaderInterface|\ArrayIterator header instance or collection of headers
*/
protected function getHeaderByName($headerName, $headerClass)
{
$headers = $this->getHeaders();
if ($headers->has($headerName)) {
$header = $headers->get($headerName);
} else {
$header = new $headerClass();
$headers->addHeader($header);
}
return $header;
}
/**
* Clear a header by name
*
* @param string $headerName
*/
protected function clearHeaderByName($headerName)
{
$this->getHeaders()->removeHeader($headerName);
}
/**
* Retrieve the AddressList from a named header
*
* Used with To, From, Cc, Bcc, and ReplyTo headers. If the header does not
* exist, instantiates it.
*
* @param string $headerName
* @param string $headerClass
* @throws Exception\DomainException
* @return AddressList
*/
protected function getAddressListFromHeader($headerName, $headerClass)
{
$header = $this->getHeaderByName($headerName, $headerClass);
if (! $header instanceof Header\AbstractAddressList) {
throw new Exception\DomainException(sprintf(
'Cannot grab address list from header of type "%s"; not an AbstractAddressList implementation',
get_class($header)
));
}
return $header->getAddressList();
}
/**
* Update an address list
*
* Proxied to this from addFrom, addTo, addCc, addBcc, and addReplyTo.
*
* @param AddressList $addressList
* @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressOrList
* @param null|string $name
* @param string $callingMethod
* @throws Exception\InvalidArgumentException
*/
protected function updateAddressList(AddressList $addressList, $emailOrAddressOrList, $name, $callingMethod)
{
if ($emailOrAddressOrList instanceof Traversable) {
foreach ($emailOrAddressOrList as $address) {
$addressList->add($address);
}
return;
}
if (is_array($emailOrAddressOrList)) {
$addressList->addMany($emailOrAddressOrList);
return;
}
if (! is_string($emailOrAddressOrList) && ! $emailOrAddressOrList instanceof Address\AddressInterface) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a string, AddressInterface, array, AddressList, or Traversable as its first argument;'
. ' received "%s"',
$callingMethod,
(is_object($emailOrAddressOrList) ? get_class($emailOrAddressOrList) : gettype($emailOrAddressOrList))
));
}
if (is_string($emailOrAddressOrList) && $name === null) {
$addressList->addFromString($emailOrAddressOrList);
return;
}
$addressList->add($emailOrAddressOrList, $name);
}
/**
* Serialize to string
*
* @return string
*/
public function toString()
{
$headers = $this->getHeaders();
return $headers->toString()
. Headers::EOL
. $this->getBodyText();
}
/**
* Instantiate from raw message string
*
* @todo Restore body to Mime\Message
* @param string $rawMessage
* @return Message
*/
public static function fromString($rawMessage)
{
$message = new static();
/** @var Headers $headers */
$headers = null;
$content = null;
Mime\Decode::splitMessage($rawMessage, $headers, $content, Headers::EOL);
if ($headers->has('mime-version')) {
// todo - restore body to mime\message
}
$message->setHeaders($headers);
$message->setBody($content);
return $message;
}
}

View File

@@ -0,0 +1,64 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail;
use Traversable;
class MessageFactory
{
/**
* @param array|Traversable $options
* @return Message
*/
public static function getInstance($options = [])
{
if (! is_array($options) && ! $options instanceof Traversable) {
throw new Exception\InvalidArgumentException(sprintf(
'"%s" expects an array or Traversable; received "%s"',
__METHOD__,
(is_object($options) ? get_class($options) : gettype($options))
));
}
$message = new Message();
foreach ($options as $key => $value) {
$setter = self::getSetterMethod($key);
if (method_exists($message, $setter)) {
$message->{$setter}($value);
}
}
return $message;
}
/**
* Generate a setter method name based on a provided key.
*
* @param string $key
* @return string
*/
private static function getSetterMethod($key)
{
return 'set'
. str_replace(
' ',
'',
ucwords(
strtr(
$key,
[
'-' => ' ',
'_' => ' ',
]
)
)
);
}
}

View File

@@ -0,0 +1,25 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail;
class Module
{
/**
* Retrieve laminas-mail package configuration for laminas-mvc context.
*
* @return array
*/
public function getConfig()
{
$provider = new ConfigProvider();
return [
'service_manager' => $provider->getDependencyConfig(),
];
}
}

View File

@@ -0,0 +1,356 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Protocol;
use Laminas\Validator;
/**
* Provides low-level methods for concrete adapters to communicate with a
* remote mail server and track requests and responses.
*
* @todo Implement proxy settings
*/
abstract class AbstractProtocol
{
/**
* Mail default EOL string
*/
const EOL = "\r\n";
/**
* Default timeout in seconds for initiating session
*/
const TIMEOUT_CONNECTION = 30;
/**
* Maximum of the transaction log
* @var int
*/
protected $maximumLog = 64;
/**
* Hostname or IP address of remote server
* @var string
*/
protected $host;
/**
* Port number of connection
* @var int
*/
protected $port;
/**
* Instance of Laminas\Validator\ValidatorChain to check hostnames
* @var \Laminas\Validator\ValidatorChain
*/
protected $validHost;
/**
* Socket connection resource
* @var null|resource
*/
protected $socket;
/**
* Last request sent to server
* @var string
*/
protected $request;
/**
* Array of server responses to last request
* @var array
*/
protected $response;
/**
* Log of mail requests and server responses for a session
* @var array
*/
private $log = [];
/**
* Constructor.
*
* @param string $host OPTIONAL Hostname of remote connection (default: 127.0.0.1)
* @param int $port OPTIONAL Port number (default: null)
* @throws Exception\RuntimeException
*/
public function __construct($host = '127.0.0.1', $port = null)
{
$this->validHost = new Validator\ValidatorChain();
$this->validHost->attach(new Validator\Hostname(Validator\Hostname::ALLOW_ALL));
if (! $this->validHost->isValid($host)) {
throw new Exception\RuntimeException(implode(', ', $this->validHost->getMessages()));
}
$this->host = $host;
$this->port = $port;
}
/**
* Class destructor to cleanup open resources
*
*/
public function __destruct()
{
$this->_disconnect();
}
/**
* Set the maximum log size
*
* @param int $maximumLog Maximum log size
*/
public function setMaximumLog($maximumLog)
{
$this->maximumLog = (int) $maximumLog;
}
/**
* Get the maximum log size
*
* @return int the maximum log size
*/
public function getMaximumLog()
{
return $this->maximumLog;
}
/**
* Create a connection to the remote host
*
* Concrete adapters for this class will implement their own unique connect
* scripts, using the _connect() method to create the socket resource.
*/
abstract public function connect();
/**
* Retrieve the last client request
*
* @return string
*/
public function getRequest()
{
return $this->request;
}
/**
* Retrieve the last server response
*
* @return array
*/
public function getResponse()
{
return $this->response;
}
/**
* Retrieve the transaction log
*
* @return string
*/
public function getLog()
{
return implode('', $this->log);
}
/**
* Reset the transaction log
*
*/
public function resetLog()
{
$this->log = [];
}
// @codingStandardsIgnoreStart
/**
* Add the transaction log
*
* @param string $value new transaction
*/
protected function _addLog($value)
{
// @codingStandardsIgnoreEnd
if ($this->maximumLog >= 0 && count($this->log) >= $this->maximumLog) {
array_shift($this->log);
}
$this->log[] = $value;
}
// @codingStandardsIgnoreStart
/**
* Connect to the server using the supplied transport and target
*
* An example $remote string may be 'tcp://mail.example.com:25' or 'ssh://hostname.com:2222'
*
* @deprecated Since 1.12.0. Implementations should use the ProtocolTrait::setupSocket() method instead.
* @todo Remove for 3.0.0.
* @param string $remote Remote
* @throws Exception\RuntimeException
* @return bool
*/
protected function _connect($remote)
{
// @codingStandardsIgnoreEnd
$errorNum = 0;
$errorStr = '';
// open connection
set_error_handler(
function ($error, $message = '') {
throw new Exception\RuntimeException(sprintf('Could not open socket: %s', $message), $error);
},
E_WARNING
);
$this->socket = stream_socket_client($remote, $errorNum, $errorStr, self::TIMEOUT_CONNECTION);
restore_error_handler();
if ($this->socket === false) {
if ($errorNum == 0) {
$errorStr = 'Could not open socket';
}
throw new Exception\RuntimeException($errorStr);
}
if (($result = stream_set_timeout($this->socket, self::TIMEOUT_CONNECTION)) === false) {
throw new Exception\RuntimeException('Could not set stream timeout');
}
return $result;
}
// @codingStandardsIgnoreStart
/**
* Disconnect from remote host and free resource
*
*/
protected function _disconnect()
{
// @codingStandardsIgnoreEnd
if (is_resource($this->socket)) {
fclose($this->socket);
}
}
// @codingStandardsIgnoreStart
/**
* Send the given request followed by a LINEEND to the server.
*
* @param string $request
* @throws Exception\RuntimeException
* @return int|bool Number of bytes written to remote host
*/
protected function _send($request)
{
// @codingStandardsIgnoreEnd
if (! is_resource($this->socket)) {
throw new Exception\RuntimeException('No connection has been established to ' . $this->host);
}
$this->request = $request;
$result = fwrite($this->socket, $request . self::EOL);
// Save request to internal log
$this->_addLog($request . self::EOL);
if ($result === false) {
throw new Exception\RuntimeException('Could not send request to ' . $this->host);
}
return $result;
}
// @codingStandardsIgnoreStart
/**
* Get a line from the stream.
*
* @param int $timeout Per-request timeout value if applicable
* @throws Exception\RuntimeException
* @return string
*/
protected function _receive($timeout = null)
{
// @codingStandardsIgnoreEnd
if (! is_resource($this->socket)) {
throw new Exception\RuntimeException('No connection has been established to ' . $this->host);
}
// Adapters may wish to supply per-commend timeouts according to appropriate RFC
if ($timeout !== null) {
stream_set_timeout($this->socket, $timeout);
}
// Retrieve response
$response = fgets($this->socket, 1024);
// Save request to internal log
$this->_addLog($response);
// Check meta data to ensure connection is still valid
$info = stream_get_meta_data($this->socket);
if (! empty($info['timed_out'])) {
throw new Exception\RuntimeException($this->host . ' has timed out');
}
if ($response === false) {
throw new Exception\RuntimeException('Could not read from ' . $this->host);
}
return $response;
}
// @codingStandardsIgnoreStart
/**
* Parse server response for successful codes
*
* Read the response from the stream and check for expected return code.
* Throws a Laminas\Mail\Protocol\Exception\ExceptionInterface if an unexpected code is returned.
*
* @param string|array $code One or more codes that indicate a successful response
* @param int $timeout Per-request timeout value if applicable
* @throws Exception\RuntimeException
* @return string Last line of response string
*/
protected function _expect($code, $timeout = null)
{
// @codingStandardsIgnoreEnd
$this->response = [];
$errMsg = '';
if (! is_array($code)) {
$code = [$code];
}
do {
$this->response[] = $result = $this->_receive($timeout);
list($cmd, $more, $msg) = preg_split('/([\s-]+)/', $result, 2, PREG_SPLIT_DELIM_CAPTURE);
if ($errMsg !== '') {
$errMsg .= ' ' . $msg;
} elseif ($cmd === null || ! in_array($cmd, $code)) {
$errMsg = $msg;
}
// The '-' message prefix indicates an information string instead of a response string.
} while (strpos($more, '-') === 0);
if ($errMsg !== '') {
throw new Exception\RuntimeException($errMsg);
}
return $msg;
}
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Protocol\Exception;
use Laminas\Mail\Exception\ExceptionInterface as MailException;
interface ExceptionInterface extends MailException
{
}

View File

@@ -0,0 +1,18 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Protocol\Exception;
use Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,18 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Protocol\Exception;
use Laminas\Mail\Exception;
/**
* Exception for Laminas\Mail component.
*/
class RuntimeException extends Exception\RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,824 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Protocol;
class Imap
{
use ProtocolTrait;
/**
* Default timeout in seconds for initiating session
*/
const TIMEOUT_CONNECTION = 30;
/**
* @var null|resource
*/
protected $socket;
/**
* counter for request tag
* @var int
*/
protected $tagCount = 0;
/**
* Public constructor
*
* @param string $host hostname or IP address of IMAP server, if given connect() is called
* @param int|null $port port of IMAP server, null for default (143 or 993 for ssl)
* @param string|bool $ssl use ssl? 'SSL', 'TLS' or false
* @param bool $novalidatecert set to true to skip SSL certificate validation
* @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface
*/
public function __construct($host = '', $port = null, $ssl = false, $novalidatecert = false)
{
$this->setNoValidateCert($novalidatecert);
if ($host) {
$this->connect($host, $port, $ssl);
}
}
/**
* Public destructor
*/
public function __destruct()
{
$this->logout();
}
/**
* Open connection to IMAP server
*
* @param string $host hostname or IP address of IMAP server
* @param int|null $port of IMAP server, default is 143 (993 for ssl)
* @param string|bool $ssl use 'SSL', 'TLS' or false
* @throws Exception\RuntimeException
* @return void
*/
public function connect($host, $port = null, $ssl = false)
{
$transport = 'tcp';
$isTls = false;
if ($ssl) {
$ssl = strtolower($ssl);
}
switch ($ssl) {
case 'ssl':
$transport = 'ssl';
if (! $port) {
$port = 993;
}
break;
case 'tls':
$isTls = true;
// break intentionally omitted
default:
if (! $port) {
$port = 143;
}
}
$this->socket = $this->setupSocket($transport, $host, $port, self::TIMEOUT_CONNECTION);
if (! $this->assumedNextLine('* OK')) {
throw new Exception\RuntimeException('host doesn\'t allow connection');
}
if ($isTls) {
$result = $this->requestAndResponse('STARTTLS');
$result = $result && stream_socket_enable_crypto($this->socket, true, $this->getCryptoMethod());
if (! $result) {
throw new Exception\RuntimeException('cannot enable TLS');
}
}
}
/**
* get the next line from socket with error checking, but nothing else
*
* @throws Exception\RuntimeException
* @return string next line
*/
protected function nextLine()
{
$line = fgets($this->socket);
if ($line === false) {
throw new Exception\RuntimeException('cannot read - connection closed?');
}
return $line;
}
/**
* get next line and assume it starts with $start. some requests give a simple
* feedback so we can quickly check if we can go on.
*
* @param string $start the first bytes we assume to be in the next line
* @return bool line starts with $start
*/
protected function assumedNextLine($start)
{
$line = $this->nextLine();
return strpos($line, $start) === 0;
}
/**
* get next line and split the tag. that's the normal case for a response line
*
* @param string $tag tag of line is returned by reference
* @return string next line
*/
protected function nextTaggedLine(&$tag)
{
$line = $this->nextLine();
// separate tag from line
list($tag, $line) = explode(' ', $line, 2);
return $line;
}
/**
* split a given line in tokens. a token is literal of any form or a list
*
* @param string $line line to decode
* @return array tokens, literals are returned as string, lists as array
*/
protected function decodeLine($line)
{
$tokens = [];
$stack = [];
/*
We start to decode the response here. The understood tokens are:
literal
"literal" or also "lit\\er\"al"
{bytes}<NL>literal
(literals*)
All tokens are returned in an array. Literals in braces (the last understood
token in the list) are returned as an array of tokens. I.e. the following response:
"foo" baz {3}<NL>bar ("f\\\"oo" bar)
would be returned as:
array('foo', 'baz', 'bar', array('f\\\"oo', 'bar'));
// TODO: add handling of '[' and ']' to parser for easier handling of response text
*/
// replace any trailing <NL> including spaces with a single space
$line = rtrim($line) . ' ';
while (($pos = strpos($line, ' ')) !== false) {
$token = substr($line, 0, $pos);
if (! strlen($token)) {
continue;
}
while ($token[0] == '(') {
array_push($stack, $tokens);
$tokens = [];
$token = substr($token, 1);
}
if ($token[0] == '"') {
if (preg_match('%^\(*"((.|\\\\|\\")*?)" *%', $line, $matches)) {
$tokens[] = $matches[1];
$line = substr($line, strlen($matches[0]));
continue;
}
}
if ($token[0] == '{') {
$endPos = strpos($token, '}');
$chars = substr($token, 1, $endPos - 1);
if (is_numeric($chars)) {
$token = '';
while (strlen($token) < $chars) {
$token .= $this->nextLine();
}
$line = '';
if (strlen($token) > $chars) {
$line = substr($token, $chars);
$token = substr($token, 0, $chars);
} else {
$line .= $this->nextLine();
}
$tokens[] = $token;
$line = trim($line) . ' ';
continue;
}
}
if ($stack && $token[strlen($token) - 1] == ')') {
// closing braces are not separated by spaces, so we need to count them
$braces = strlen($token);
$token = rtrim($token, ')');
// only count braces if more than one
$braces -= strlen($token) + 1;
// only add if token had more than just closing braces
if (rtrim($token) != '') {
$tokens[] = rtrim($token);
}
$token = $tokens;
$tokens = array_pop($stack);
// special handline if more than one closing brace
while ($braces-- > 0) {
$tokens[] = $token;
$token = $tokens;
$tokens = array_pop($stack);
}
}
$tokens[] = $token;
$line = substr($line, $pos + 1);
}
// maybe the server forgot to send some closing braces
while ($stack) {
$child = $tokens;
$tokens = array_pop($stack);
$tokens[] = $child;
}
return $tokens;
}
/**
* read a response "line" (could also be more than one real line if response has {..}<NL>)
* and do a simple decode
*
* @param array|string $tokens decoded tokens are returned by reference, if $dontParse
* is true the unparsed line is returned here
* @param string $wantedTag check for this tag for response code. Default '*' is
* continuation tag.
* @param bool $dontParse if true only the unparsed line is returned $tokens
* @return bool if returned tag matches wanted tag
*/
public function readLine(&$tokens = [], $wantedTag = '*', $dontParse = false)
{
$tag = null; // define $tag variable before first use
$line = $this->nextTaggedLine($tag); // get next tag
if (! $dontParse) {
$tokens = $this->decodeLine($line);
} else {
$tokens = $line;
}
// if tag is wanted tag we might be at the end of a multiline response
return $tag == $wantedTag;
}
/**
* read all lines of response until given tag is found (last line of response)
*
* @param string $tag the tag of your request
* @param bool $dontParse if true every line is returned unparsed instead of
* the decoded tokens
* @return null|bool|array tokens if success, false if error, null if bad request
*/
public function readResponse($tag, $dontParse = false)
{
$lines = [];
$tokens = null; // define $tokens variable before first use
while (! $this->readLine($tokens, $tag, $dontParse)) {
$lines[] = $tokens;
}
if ($dontParse) {
// last to chars are still needed for response code
$tokens = [substr($tokens, 0, 2)];
}
// last line has response code
if ($tokens[0] == 'OK') {
return $lines ? $lines : true;
} elseif ($tokens[0] == 'NO') {
return false;
}
return;
}
/**
* send a request
*
* @param string $command your request command
* @param array $tokens additional parameters to command, use escapeString() to prepare
* @param string $tag provide a tag otherwise an autogenerated is returned
* @throws Exception\RuntimeException
*/
public function sendRequest($command, $tokens = [], &$tag = null)
{
if (! $tag) {
++$this->tagCount;
$tag = 'TAG' . $this->tagCount;
}
$line = $tag . ' ' . $command;
foreach ($tokens as $token) {
if (is_array($token)) {
if (fwrite($this->socket, $line . ' ' . $token[0] . "\r\n") === false) {
throw new Exception\RuntimeException('cannot write - connection closed?');
}
if (! $this->assumedNextLine('+ ')) {
throw new Exception\RuntimeException('cannot send literal string');
}
$line = $token[1];
} else {
$line .= ' ' . $token;
}
}
if (fwrite($this->socket, $line . "\r\n") === false) {
throw new Exception\RuntimeException('cannot write - connection closed?');
}
}
/**
* send a request and get response at once
*
* @param string $command command as in sendRequest()
* @param array $tokens parameters as in sendRequest()
* @param bool $dontParse if true unparsed lines are returned instead of tokens
* @return mixed response as in readResponse()
*/
public function requestAndResponse($command, $tokens = [], $dontParse = false)
{
$tag = null; // define $tag variable before first use
$this->sendRequest($command, $tokens, $tag);
$response = $this->readResponse($tag, $dontParse);
return $response;
}
/**
* escape one or more literals i.e. for sendRequest
*
* @param string|array $string the literal/-s
* @return string|array escape literals, literals with newline ar returned
* as array('{size}', 'string');
*/
public function escapeString($string)
{
if (func_num_args() < 2) {
if (strpos($string, "\n") !== false) {
return ['{' . strlen($string) . '}', $string];
} else {
return '"' . str_replace(['\\', '"'], ['\\\\', '\\"'], $string) . '"';
}
}
$result = [];
foreach (func_get_args() as $string) {
$result[] = $this->escapeString($string);
}
return $result;
}
/**
* escape a list with literals or lists
*
* @param array $list list with literals or lists as PHP array
* @return string escaped list for imap
*/
public function escapeList($list)
{
$result = [];
foreach ($list as $v) {
if (! is_array($v)) {
$result[] = $v;
continue;
}
$result[] = $this->escapeList($v);
}
return '(' . implode(' ', $result) . ')';
}
/**
* Login to IMAP server.
*
* @param string $user username
* @param string $password password
* @return bool success
*/
public function login($user, $password)
{
return $this->requestAndResponse('LOGIN', $this->escapeString($user, $password), true);
}
/**
* logout of imap server
*
* @return bool success
*/
public function logout()
{
$result = false;
if ($this->socket) {
try {
$result = $this->requestAndResponse('LOGOUT', [], true);
} catch (Exception\ExceptionInterface $e) {
// ignoring exception
}
fclose($this->socket);
$this->socket = null;
}
return $result;
}
/**
* Get capabilities from IMAP server
*
* @return array list of capabilities
* @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface
*/
public function capability()
{
$response = $this->requestAndResponse('CAPABILITY');
if (! $response) {
return [];
}
$capabilities = [];
foreach ($response as $line) {
$capabilities = array_merge($capabilities, $line);
}
return $capabilities;
}
/**
* Examine and select have the same response. The common code for both
* is in this method
*
* @param string $command can be 'EXAMINE' or 'SELECT' and this is used as command
* @param string $box which folder to change to or examine
* @return bool|array false if error, array with returned information
* otherwise (flags, exists, recent, uidvalidity)
* @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface
*/
public function examineOrSelect($command = 'EXAMINE', $box = 'INBOX')
{
$tag = null; // define $tag variable before first use
$this->sendRequest($command, [$this->escapeString($box)], $tag);
$result = [];
$tokens = null; // define $tokens variable before first use
while (! $this->readLine($tokens, $tag)) {
if ($tokens[0] == 'FLAGS') {
array_shift($tokens);
$result['flags'] = $tokens;
continue;
}
switch ($tokens[1]) {
case 'EXISTS':
case 'RECENT':
$result[strtolower($tokens[1])] = $tokens[0];
break;
case '[UIDVALIDITY':
$result['uidvalidity'] = (int) $tokens[2];
break;
default:
// ignore
}
}
if ($tokens[0] != 'OK') {
return false;
}
return $result;
}
/**
* change folder
*
* @param string $box change to this folder
* @return bool|array see examineOrselect()
* @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface
*/
public function select($box = 'INBOX')
{
return $this->examineOrSelect('SELECT', $box);
}
/**
* examine folder
*
* @param string $box examine this folder
* @return bool|array see examineOrselect()
* @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface
*/
public function examine($box = 'INBOX')
{
return $this->examineOrSelect('EXAMINE', $box);
}
/**
* fetch one or more items of one or more messages
*
* @param string|array $items items to fetch from message(s) as string (if only one item)
* or array of strings
* @param int|array $from message for items or start message if $to !== null
* @param int|null $to if null only one message ($from) is fetched, else it's the
* last message, INF means last message available
* @param bool $uid set to true if passing a unique id
* @throws Exception\RuntimeException
* @return string|array if only one item of one message is fetched it's returned as string
* if items of one message are fetched it's returned as (name => value)
* if one items of messages are fetched it's returned as (msgno => value)
* if items of messages are fetched it's returned as (msgno => (name => value))
*/
public function fetch($items, $from, $to = null, $uid = false)
{
if (is_array($from)) {
$set = implode(',', $from);
} elseif ($to === null) {
$set = (int) $from;
} elseif ($to === INF) {
$set = (int) $from . ':*';
} else {
$set = (int) $from . ':' . (int) $to;
}
$items = (array) $items;
$itemList = $this->escapeList($items);
$tag = null; // define $tag variable before first use
$this->sendRequest(($uid ? 'UID ' : '') . 'FETCH', [$set, $itemList], $tag);
$result = [];
$tokens = null; // define $tokens variable before first use
while (! $this->readLine($tokens, $tag)) {
// ignore other responses
if ($tokens[1] != 'FETCH') {
continue;
}
// find array key of UID value; try the last elements, or search for it
if ($uid) {
$count = count($tokens[2]);
if ($tokens[2][$count - 2] == 'UID') {
$uidKey = $count - 1;
} else {
$uidKey = array_search('UID', $tokens[2]) + 1;
}
}
// ignore other messages
if ($to === null && ! is_array($from) && ($uid ? $tokens[2][$uidKey] != $from : $tokens[0] != $from)) {
continue;
}
// if we only want one item we return that one directly
if (count($items) == 1) {
if ($tokens[2][0] == $items[0]) {
$data = $tokens[2][1];
} elseif ($uid && $tokens[2][2] == $items[0]) {
$data = $tokens[2][3];
} else {
// maybe the server send an other field we didn't wanted
$count = count($tokens[2]);
// we start with 2, because 0 was already checked
for ($i = 2; $i < $count; $i += 2) {
if ($tokens[2][$i] != $items[0]) {
continue;
}
$data = $tokens[2][$i + 1];
break;
}
}
} else {
$data = [];
while (key($tokens[2]) !== null) {
$data[current($tokens[2])] = next($tokens[2]);
next($tokens[2]);
}
}
// if we want only one message we can ignore everything else and just return
if ($to === null && ! is_array($from) && ($uid ? $tokens[2][$uidKey] == $from : $tokens[0] == $from)) {
// we still need to read all lines
while (! $this->readLine($tokens, $tag)) {
}
return $data;
}
$result[$tokens[0]] = $data;
}
if ($to === null && ! is_array($from)) {
throw new Exception\RuntimeException('the single id was not found in response');
}
return $result;
}
/**
* get mailbox list
*
* this method can't be named after the IMAP command 'LIST', as list is a reserved keyword
*
* @param string $reference mailbox reference for list
* @param string $mailbox mailbox name match with wildcards
* @return array mailboxes that matched $mailbox as array(globalName => array('delim' => .., 'flags' => ..))
* @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface
*/
public function listMailbox($reference = '', $mailbox = '*')
{
$result = [];
$list = $this->requestAndResponse('LIST', $this->escapeString($reference, $mailbox));
if (! $list || $list === true) {
return $result;
}
foreach ($list as $item) {
if (count($item) != 4 || $item[0] != 'LIST') {
continue;
}
$result[$item[3]] = ['delim' => $item[2], 'flags' => $item[1]];
}
return $result;
}
/**
* set flags
*
* @param array $flags flags to set, add or remove - see $mode
* @param int $from message for items or start message if $to !== null
* @param int|null $to if null only one message ($from) is fetched, else it's the
* last message, INF means last message available
* @param string|null $mode '+' to add flags, '-' to remove flags, everything else sets the flags as given
* @param bool $silent if false the return values are the new flags for the wanted messages
* @return bool|array new flags if $silent is false, else true or false depending on success
* @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface
*/
public function store(array $flags, $from, $to = null, $mode = null, $silent = true)
{
$item = 'FLAGS';
if ($mode == '+' || $mode == '-') {
$item = $mode . $item;
}
if ($silent) {
$item .= '.SILENT';
}
$flags = $this->escapeList($flags);
$set = (int) $from;
if ($to !== null) {
$set .= ':' . ($to == INF ? '*' : (int) $to);
}
$result = $this->requestAndResponse('STORE', [$set, $item, $flags], $silent);
if ($silent) {
return (bool) $result;
}
$tokens = $result;
$result = [];
foreach ($tokens as $token) {
if ($token[1] != 'FETCH' || $token[2][0] != 'FLAGS') {
continue;
}
$result[$token[0]] = $token[2][1];
}
return $result;
}
/**
* append a new message to given folder
*
* @param string $folder name of target folder
* @param string $message full message content
* @param array $flags flags for new message
* @param string $date date for new message
* @return bool success
* @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface
*/
public function append($folder, $message, $flags = null, $date = null)
{
$tokens = [];
$tokens[] = $this->escapeString($folder);
if ($flags !== null) {
$tokens[] = $this->escapeList($flags);
}
if ($date !== null) {
$tokens[] = $this->escapeString($date);
}
$tokens[] = $this->escapeString($message);
return $this->requestAndResponse('APPEND', $tokens, true);
}
/**
* copy message set from current folder to other folder
*
* @param string $folder destination folder
* @param $from
* @param int|null $to if null only one message ($from) is fetched, else it's the
* last message, INF means last message available
* @return bool success
*/
public function copy($folder, $from, $to = null)
{
$set = (int) $from;
if ($to !== null) {
$set .= ':' . ($to == INF ? '*' : (int) $to);
}
return $this->requestAndResponse('COPY', [$set, $this->escapeString($folder)], true);
}
/**
* create a new folder (and parent folders if needed)
*
* @param string $folder folder name
* @return bool success
*/
public function create($folder)
{
return $this->requestAndResponse('CREATE', [$this->escapeString($folder)], true);
}
/**
* rename an existing folder
*
* @param string $old old name
* @param string $new new name
* @return bool success
*/
public function rename($old, $new)
{
return $this->requestAndResponse('RENAME', $this->escapeString($old, $new), true);
}
/**
* remove a folder
*
* @param string $folder folder name
* @return bool success
*/
public function delete($folder)
{
return $this->requestAndResponse('DELETE', [$this->escapeString($folder)], true);
}
/**
* subscribe to a folder
*
* @param string $folder folder name
* @return bool success
*/
public function subscribe($folder)
{
return $this->requestAndResponse('SUBSCRIBE', [$this->escapeString($folder)], true);
}
/**
* permanently remove messages
*
* @return bool success
*/
public function expunge()
{
// TODO: parse response?
return $this->requestAndResponse('EXPUNGE');
}
/**
* send noop
*
* @return bool success
*/
public function noop()
{
// TODO: parse response
return $this->requestAndResponse('NOOP');
}
/**
* do a search request
*
* This method is currently marked as internal as the API might change and is not
* safe if you don't take precautions.
*
* @param array $params
* @return array message ids
*/
public function search(array $params)
{
$response = $this->requestAndResponse('SEARCH', $params);
if (! $response) {
return $response;
}
foreach ($response as $ids) {
if ($ids[0] == 'SEARCH') {
array_shift($ids);
return $ids;
}
}
return [];
}
}

View File

@@ -0,0 +1,401 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Protocol;
use Laminas\Stdlib\ErrorHandler;
class Pop3
{
use ProtocolTrait;
/**
* Default timeout in seconds for initiating session
*/
const TIMEOUT_CONNECTION = 30;
/**
* saves if server supports top
* @var null|bool
*/
public $hasTop = null;
/**
* @var null|resource
*/
protected $socket;
/**
* greeting timestamp for apop
* @var null|string
*/
protected $timestamp;
/**
* Public constructor
*
* @param string $host hostname or IP address of POP3 server, if given connect() is called
* @param int|null $port port of POP3 server, null for default (110 or 995 for ssl)
* @param bool|string $ssl use ssl? 'SSL', 'TLS' or false
* @param bool $novalidatecert set to true to skip SSL certificate validation
*/
public function __construct($host = '', $port = null, $ssl = false, $novalidatecert = false)
{
$this->setNoValidateCert($novalidatecert);
if ($host) {
$this->connect($host, $port, $ssl);
}
}
/**
* Public destructor
*/
public function __destruct()
{
$this->logout();
}
/**
* Open connection to POP3 server
*
* @param string $host hostname or IP address of POP3 server
* @param int|null $port of POP3 server, default is 110 (995 for ssl)
* @param string|bool $ssl use 'SSL', 'TLS' or false
* @throws Exception\RuntimeException
* @return string welcome message
*/
public function connect($host, $port = null, $ssl = false)
{
$transport = 'tcp';
$isTls = false;
if ($ssl) {
$ssl = strtolower($ssl);
}
switch ($ssl) {
case 'ssl':
$transport = 'ssl';
if (! $port) {
$port = 995;
}
break;
case 'tls':
$isTls = true;
// break intentionally omitted
default:
if (! $port) {
$port = 110;
}
}
$this->socket = $this->setupSocket($transport, $host, $port, self::TIMEOUT_CONNECTION);
$welcome = $this->readResponse();
strtok($welcome, '<');
$this->timestamp = strtok('>');
if (! strpos($this->timestamp, '@')) {
$this->timestamp = null;
} else {
$this->timestamp = '<' . $this->timestamp . '>';
}
if ($isTls) {
$this->request('STLS');
$result = stream_socket_enable_crypto($this->socket, true, $this->getCryptoMethod());
if (! $result) {
throw new Exception\RuntimeException('cannot enable TLS');
}
}
return $welcome;
}
/**
* Send a request
*
* @param string $request your request without newline
* @throws Exception\RuntimeException
*/
public function sendRequest($request)
{
ErrorHandler::start();
$result = fputs($this->socket, $request . "\r\n");
$error = ErrorHandler::stop();
if (! $result) {
throw new Exception\RuntimeException('send failed - connection closed?', 0, $error);
}
}
/**
* read a response
*
* @param bool $multiline response has multiple lines and should be read until "<nl>.<nl>"
* @throws Exception\RuntimeException
* @return string response
*/
public function readResponse($multiline = false)
{
ErrorHandler::start();
$result = fgets($this->socket);
$error = ErrorHandler::stop();
if (! is_string($result)) {
throw new Exception\RuntimeException('read failed - connection closed?', 0, $error);
}
$result = trim($result);
if (strpos($result, ' ')) {
list($status, $message) = explode(' ', $result, 2);
} else {
$status = $result;
$message = '';
}
if ($status != '+OK') {
throw new Exception\RuntimeException('last request failed');
}
if ($multiline) {
$message = '';
$line = fgets($this->socket);
while ($line && rtrim($line, "\r\n") != '.') {
if ($line[0] == '.') {
$line = substr($line, 1);
}
$message .= $line;
$line = fgets($this->socket);
};
}
return $message;
}
/**
* Send request and get response
*
* @see sendRequest()
* @see readResponse()
* @param string $request request
* @param bool $multiline multiline response?
* @return string result from readResponse()
*/
public function request($request, $multiline = false)
{
$this->sendRequest($request);
return $this->readResponse($multiline);
}
/**
* End communication with POP3 server (also closes socket)
*/
public function logout()
{
if ($this->socket) {
try {
$this->request('QUIT');
} catch (Exception\ExceptionInterface $e) {
// ignore error - we're closing the socket anyway
}
fclose($this->socket);
$this->socket = null;
}
}
/**
* Get capabilities from POP3 server
*
* @return array list of capabilities
*/
public function capa()
{
$result = $this->request('CAPA', true);
return explode("\n", $result);
}
/**
* Login to POP3 server. Can use APOP
*
* @param string $user username
* @param string $password password
* @param bool $tryApop should APOP be tried?
*/
public function login($user, $password, $tryApop = true)
{
if ($tryApop && $this->timestamp) {
try {
$this->request("APOP $user " . md5($this->timestamp . $password));
return;
} catch (Exception\ExceptionInterface $e) {
// ignore
}
}
$this->request("USER $user");
$this->request("PASS $password");
}
/**
* Make STAT call for message count and size sum
*
* @param int $messages out parameter with count of messages
* @param int $octets out parameter with size in octets of messages
*/
public function status(&$messages, &$octets)
{
$messages = 0;
$octets = 0;
$result = $this->request('STAT');
list($messages, $octets) = explode(' ', $result);
}
/**
* Make LIST call for size of message(s)
*
* @param int|null $msgno number of message, null for all
* @return int|array size of given message or list with array(num => size)
*/
public function getList($msgno = null)
{
if ($msgno !== null) {
$result = $this->request("LIST $msgno");
list(, $result) = explode(' ', $result);
return (int) $result;
}
$result = $this->request('LIST', true);
$messages = [];
$line = strtok($result, "\n");
while ($line) {
list($no, $size) = explode(' ', trim($line));
$messages[(int) $no] = (int) $size;
$line = strtok("\n");
}
return $messages;
}
/**
* Make UIDL call for getting a uniqueid
*
* @param int|null $msgno number of message, null for all
* @return string|array uniqueid of message or list with array(num => uniqueid)
*/
public function uniqueid($msgno = null)
{
if ($msgno !== null) {
$result = $this->request("UIDL $msgno");
list(, $result) = explode(' ', $result);
return $result;
}
$result = $this->request('UIDL', true);
$result = explode("\n", $result);
$messages = [];
foreach ($result as $line) {
if (! $line) {
continue;
}
list($no, $id) = explode(' ', trim($line), 2);
$messages[(int) $no] = $id;
}
return $messages;
}
/**
* Make TOP call for getting headers and maybe some body lines
* This method also sets hasTop - before it it's not known if top is supported
*
* The fallback makes normal RETR call, which retrieves the whole message. Additional
* lines are not removed.
*
* @param int $msgno number of message
* @param int $lines number of wanted body lines (empty line is inserted after header lines)
* @param bool $fallback fallback with full retrieve if top is not supported
* @throws Exception\RuntimeException
* @throws Exception\ExceptionInterface
* @return string message headers with wanted body lines
*/
public function top($msgno, $lines = 0, $fallback = false)
{
if ($this->hasTop === false) {
if ($fallback) {
return $this->retrieve($msgno);
} else {
throw new Exception\RuntimeException('top not supported and no fallback wanted');
}
}
$this->hasTop = true;
$lines = (! $lines || $lines < 1) ? 0 : (int) $lines;
try {
$result = $this->request("TOP $msgno $lines", true);
} catch (Exception\ExceptionInterface $e) {
$this->hasTop = false;
if ($fallback) {
$result = $this->retrieve($msgno);
} else {
throw $e;
}
}
return $result;
}
/**
* Make a RETR call for retrieving a full message with headers and body
*
* @param int $msgno message number
* @return string message
*/
public function retrieve($msgno)
{
$result = $this->request("RETR $msgno", true);
return $result;
}
/**
* Make a NOOP call, maybe needed for keeping the server happy
*/
public function noop()
{
$this->request('NOOP');
}
/**
* Make a DELE count to remove a message
*
* @param $msgno
*/
public function delete($msgno)
{
$this->request("DELE $msgno");
}
/**
* Make RSET call, which rollbacks delete requests
*/
public function undelete()
{
$this->request('RSET');
}
}

View File

@@ -0,0 +1,119 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Protocol;
use Laminas\Stdlib\ErrorHandler;
/**
* https://bugs.php.net/bug.php?id=69195
*/
trait ProtocolTrait
{
/**
* If set to true, do not validate the SSL certificate
* @var null|bool
*/
protected $novalidatecert;
public function getCryptoMethod(): int
{
// Allow the best TLS version(s) we can
$cryptoMethod = STREAM_CRYPTO_METHOD_TLS_CLIENT;
// PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT
// so add them back in manually if we can
if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
$cryptoMethod |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
$cryptoMethod |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
}
return $cryptoMethod;
}
/**
* Do not validate SSL certificate
*
* @todo Update to return self when minimum supported PHP version is 7.4+
* @param bool $novalidatecert Set to true to disable certificate validation
* @return $this
*/
public function setNoValidateCert(bool $novalidatecert)
{
$this->novalidatecert = $novalidatecert;
return $this;
}
/**
* Should we validate SSL certificate?
*
* @return bool
*/
public function validateCert(): bool
{
return ! $this->novalidatecert;
}
/**
* Prepare socket options
*
* @return array
*/
private function prepareSocketOptions(): array
{
return $this->novalidatecert
? [
'ssl' => [
'verify_peer_name' => false,
'verify_peer' => false,
]
]
: [];
}
/**
* Setup connection socket
*
* @param string $host hostname or IP address of IMAP server
* @param int|null $port of IMAP server, default is 143 (993 for ssl)
* @param int $timeout timeout in seconds for initiating session
* @return resource The socket created.
* @throws Exception\RuntimeException If unable to connect to host.
*/
protected function setupSocket(
string $transport,
string $host,
?int $port,
int $timeout
) {
ErrorHandler::start();
$socket = stream_socket_client(
sprintf('%s://%s:%d', $transport, $host, $port),
$errno,
$errstr,
$timeout,
STREAM_CLIENT_CONNECT,
stream_context_create($this->prepareSocketOptions())
);
$error = ErrorHandler::stop();
if (! $socket) {
throw new Exception\RuntimeException(sprintf(
'cannot connect to host%s',
$error ? sprintf('; error = %s (errno = %d )', $error->getMessage(), $error->getCode()) : ''
), 0, $error);
}
if (false === stream_set_timeout($socket, $timeout)) {
throw new Exception\RuntimeException('Could not set stream timeout');
}
return $socket;
}
}

View File

@@ -0,0 +1,460 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Protocol;
/**
* SMTP implementation of Laminas\Mail\Protocol\AbstractProtocol
*
* Minimum implementation according to RFC2821: EHLO, MAIL FROM, RCPT TO, DATA,
* RSET, NOOP, QUIT
*/
class Smtp extends AbstractProtocol
{
use ProtocolTrait;
/**
* The transport method for the socket
*
* @var string
*/
protected $transport = 'tcp';
/**
* Indicates that a session is requested to be secure
*
* @var string
*/
protected $secure;
/**
* Indicates an smtp session has been started by the HELO command
*
* @var bool
*/
protected $sess = false;
/**
* Indicates an smtp AUTH has been issued and authenticated
*
* @var bool
*/
protected $auth = false;
/**
* Indicates a MAIL command has been issued
*
* @var bool
*/
protected $mail = false;
/**
* Indicates one or more RCTP commands have been issued
*
* @var bool
*/
protected $rcpt = false;
/**
* Indicates that DATA has been issued and sent
*
* @var bool
*/
protected $data = null;
/**
* Whether or not send QUIT command
*
* @var bool
*/
protected $useCompleteQuit = true;
/**
* Constructor.
*
* The first argument may be an array of all options. If so, it must include
* the 'host' and 'port' keys in order to ensure that all required values
* are present.
*
* @param string|array $host
* @param null|int $port
* @param null|array $config
* @throws Exception\InvalidArgumentException
*/
public function __construct($host = '127.0.0.1', $port = null, array $config = null)
{
// Did we receive a configuration array?
if (is_array($host)) {
// Merge config array with principal array, if provided
if (is_array($config)) {
$config = array_replace_recursive($host, $config);
} else {
$config = $host;
}
// Look for a host key; if none found, use default value
if (isset($config['host'])) {
$host = $config['host'];
} else {
$host = '127.0.0.1';
}
// Look for a port key; if none found, use default value
if (isset($config['port'])) {
$port = $config['port'];
} else {
$port = null;
}
}
// If we don't have a config array, initialize it
if (null === $config) {
$config = [];
}
if (isset($config['ssl'])) {
switch (strtolower($config['ssl'])) {
case 'tls':
$this->secure = 'tls';
break;
case 'ssl':
$this->transport = 'ssl';
$this->secure = 'ssl';
if ($port === null) {
$port = 465;
}
break;
case '':
// fall-through
case 'none':
break;
default:
throw new Exception\InvalidArgumentException($config['ssl'] . ' is unsupported SSL type');
}
}
if (array_key_exists('use_complete_quit', $config)) {
$this->setUseCompleteQuit($config['use_complete_quit']);
}
// If no port has been specified then check the master PHP ini file. Defaults to 25 if the ini setting is null.
if ($port === null) {
if (($port = ini_get('smtp_port')) == '') {
$port = 25;
}
}
if (array_key_exists('novalidatecert', $config)) {
$this->setNoValidateCert($config['novalidatecert']);
}
parent::__construct($host, $port);
}
/**
* Set whether or not send QUIT command
*
* @param bool $useCompleteQuit use complete quit
* @return bool
*/
public function setUseCompleteQuit($useCompleteQuit)
{
return $this->useCompleteQuit = (bool) $useCompleteQuit;
}
/**
* Whether or not send QUIT command
*
* @return bool
*/
public function useCompleteQuit()
{
return $this->useCompleteQuit;
}
/**
* Connect to the server with the parameters given in the constructor.
*
* @return bool
*/
public function connect()
{
$this->socket = $this->setupSocket(
$this->transport,
$this->host,
$this->port,
self::TIMEOUT_CONNECTION
);
return true;
}
/**
* Initiate HELO/EHLO sequence and set flag to indicate valid smtp session
*
* @param string $host The client hostname or IP address (default: 127.0.0.1)
* @throws Exception\RuntimeException
*/
public function helo($host = '127.0.0.1')
{
// Respect RFC 2821 and disallow HELO attempts if session is already initiated.
if ($this->sess === true) {
throw new Exception\RuntimeException('Cannot issue HELO to existing session');
}
// Validate client hostname
if (! $this->validHost->isValid($host)) {
throw new Exception\RuntimeException(implode(', ', $this->validHost->getMessages()));
}
// Initiate helo sequence
$this->_expect(220, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
$this->ehlo($host);
// If a TLS session is required, commence negotiation
if ($this->secure == 'tls') {
$this->_send('STARTTLS');
$this->_expect(220, 180);
if (! stream_socket_enable_crypto($this->socket, true, $this->getCryptoMethod())) {
throw new Exception\RuntimeException('Unable to connect via TLS');
}
$this->ehlo($host);
}
$this->startSession();
$this->auth();
}
/**
* Returns the perceived session status
*
* @return bool
*/
public function hasSession()
{
return $this->sess;
}
/**
* Send EHLO or HELO depending on capabilities of smtp host
*
* @param string $host The client hostname or IP address (default: 127.0.0.1)
* @throws \Exception|Exception\ExceptionInterface
*/
protected function ehlo($host)
{
// Support for older, less-compliant remote servers. Tries multiple attempts of EHLO or HELO.
try {
$this->_send('EHLO ' . $host);
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
} catch (Exception\ExceptionInterface $e) {
$this->_send('HELO ' . $host);
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
}
}
/**
* Issues MAIL command
*
* @param string $from Sender mailbox
* @throws Exception\RuntimeException
*/
public function mail($from)
{
if ($this->sess !== true) {
throw new Exception\RuntimeException('A valid session has not been started');
}
$this->_send('MAIL FROM:<' . $from . '>');
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
// Set mail to true, clear recipients and any existing data flags as per 4.1.1.2 of RFC 2821
$this->mail = true;
$this->rcpt = false;
$this->data = false;
}
/**
* Issues RCPT command
*
* @param string $to Receiver(s) mailbox
* @throws Exception\RuntimeException
*/
public function rcpt($to)
{
if ($this->mail !== true) {
throw new Exception\RuntimeException('No sender reverse path has been supplied');
}
// Set rcpt to true, as per 4.1.1.3 of RFC 2821
$this->_send('RCPT TO:<' . $to . '>');
$this->_expect([250, 251], 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
$this->rcpt = true;
}
/**
* Issues DATA command
*
* @param string $data
* @throws Exception\RuntimeException
*/
public function data($data)
{
// Ensure recipients have been set
if ($this->rcpt !== true) { // Per RFC 2821 3.3 (page 18)
throw new Exception\RuntimeException('No recipient forward path has been supplied');
}
$this->_send('DATA');
$this->_expect(354, 120); // Timeout set for 2 minutes as per RFC 2821 4.5.3.2
if (($fp = fopen("php://temp", "r+")) === false) {
throw new Exception\RuntimeException('cannot fopen');
}
if (fwrite($fp, $data) === false) {
throw new Exception\RuntimeException('cannot fwrite');
}
unset($data);
rewind($fp);
// max line length is 998 char + \r\n = 1000
while (($line = stream_get_line($fp, 1000, "\n")) !== false) {
$line = rtrim($line, "\r");
if (isset($line[0]) && $line[0] === '.') {
// Escape lines prefixed with a '.'
$line = '.' . $line;
}
$this->_send($line);
}
fclose($fp);
$this->_send('.');
$this->_expect(250, 600); // Timeout set for 10 minutes as per RFC 2821 4.5.3.2
$this->data = true;
}
/**
* Issues the RSET command end validates answer
*
* Can be used to restore a clean smtp communication state when a
* transaction has been cancelled or commencing a new transaction.
*/
public function rset()
{
$this->_send('RSET');
// MS ESMTP doesn't follow RFC, see https://zendframework.com/issues/browse/ZF-1377
$this->_expect([250, 220]);
$this->mail = false;
$this->rcpt = false;
$this->data = false;
}
/**
* Issues the NOOP command end validates answer
*
* Not used by Laminas\Mail, could be used to keep a connection alive or check if it is still open.
*
*/
public function noop()
{
$this->_send('NOOP');
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
}
/**
* Issues the VRFY command end validates answer
*
* Not used by Laminas\Mail.
*
* @param string $user User Name or eMail to verify
*/
public function vrfy($user)
{
$this->_send('VRFY ' . $user);
$this->_expect([250, 251, 252], 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
}
/**
* Issues the QUIT command and clears the current session
*
*/
public function quit()
{
if ($this->sess) {
$this->auth = false;
if ($this->useCompleteQuit()) {
$this->_send('QUIT');
$this->_expect(221, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
}
$this->stopSession();
}
}
/**
* Default authentication method
*
* This default method is implemented by AUTH adapters to properly authenticate to a remote host.
*
* @throws Exception\RuntimeException
*/
public function auth()
{
if ($this->auth === true) {
throw new Exception\RuntimeException('Already authenticated for this session');
}
}
/**
* Closes connection
*
*/
public function disconnect()
{
$this->_disconnect();
}
// @codingStandardsIgnoreStart
/**
* Disconnect from remote host and free resource
*/
protected function _disconnect()
{
// @codingStandardsIgnoreEnd
// Make sure the session gets closed
$this->quit();
parent::_disconnect();
}
/**
* Start mail session
*
*/
protected function startSession()
{
$this->sess = true;
}
/**
* Stop mail session
*
*/
protected function stopSession()
{
$this->sess = false;
}
}

View File

@@ -0,0 +1,138 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Protocol\Smtp\Auth;
use Laminas\Crypt\Hmac;
use Laminas\Mail\Protocol\Smtp;
/**
* Performs CRAM-MD5 authentication
*/
class Crammd5 extends Smtp
{
/**
* @var string
*/
protected $username;
/**
* @var string
*/
protected $password;
/**
* Constructor.
*
* All parameters may be passed as an array to the first argument of the
* constructor. If so,
*
* @param string|array $host (Default: 127.0.0.1)
* @param null|int $port (Default: null)
* @param null|array $config Auth-specific parameters
*/
public function __construct($host = '127.0.0.1', $port = null, $config = null)
{
// Did we receive a configuration array?
$origConfig = $config;
if (is_array($host)) {
// Merge config array with principal array, if provided
if (is_array($config)) {
$config = array_replace_recursive($host, $config);
} else {
$config = $host;
}
}
if (is_array($config)) {
if (isset($config['username'])) {
$this->setUsername($config['username']);
}
if (isset($config['password'])) {
$this->setPassword($config['password']);
}
}
// Call parent with original arguments
parent::__construct($host, $port, $origConfig);
}
/**
* Performs CRAM-MD5 authentication with supplied credentials
*/
public function auth()
{
// Ensure AUTH has not already been initiated.
parent::auth();
$this->_send('AUTH CRAM-MD5');
$challenge = $this->_expect(334);
$challenge = base64_decode($challenge);
$digest = $this->hmacMd5($this->getPassword(), $challenge);
$this->_send(base64_encode($this->getUsername() . ' ' . $digest));
$this->_expect(235);
$this->auth = true;
}
/**
* Set value for username
*
* @param string $username
* @return Crammd5
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* @return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Set value for password
*
* @param string $password
* @return Crammd5
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* @return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Prepare CRAM-MD5 response to server's ticket
*
* @param string $key Challenge key (usually password)
* @param string $data Challenge data
* @param int $block Length of blocks (deprecated; unused)
* @return string
*/
protected function hmacMd5($key, $data, $block = 64)
{
return Hmac::compute($key, 'md5', $data);
}
}

View File

@@ -0,0 +1,126 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Protocol\Smtp\Auth;
use Laminas\Mail\Protocol\Smtp;
/**
* Performs LOGIN authentication
*/
class Login extends Smtp
{
/**
* LOGIN username
*
* @var string
*/
protected $username;
/**
* LOGIN password
*
* @var string
*/
protected $password;
/**
* Constructor.
*
* @param string $host (Default: 127.0.0.1)
* @param int $port (Default: null)
* @param array $config Auth-specific parameters
*/
public function __construct($host = '127.0.0.1', $port = null, $config = null)
{
// Did we receive a configuration array?
$origConfig = $config;
if (is_array($host)) {
// Merge config array with principal array, if provided
if (is_array($config)) {
$config = array_replace_recursive($host, $config);
} else {
$config = $host;
}
}
if (is_array($config)) {
if (isset($config['username'])) {
$this->setUsername($config['username']);
}
if (isset($config['password'])) {
$this->setPassword($config['password']);
}
}
// Call parent with original arguments
parent::__construct($host, $port, $origConfig);
}
/**
* Perform LOGIN authentication with supplied credentials
*
*/
public function auth()
{
// Ensure AUTH has not already been initiated.
parent::auth();
$this->_send('AUTH LOGIN');
$this->_expect(334);
$this->_send(base64_encode($this->getUsername()));
$this->_expect(334);
$this->_send(base64_encode($this->getPassword()));
$this->_expect(235);
$this->auth = true;
}
/**
* Set value for username
*
* @param string $username
* @return Login
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* @return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Set value for password
*
* @param string $password
* @return Login
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* @return string
*/
public function getPassword()
{
return $this->password;
}
}

View File

@@ -0,0 +1,124 @@
<?php
/**
* @see https://github.com/laminas/laminas-mail for the canonical source repository
* @copyright https://github.com/laminas/laminas-mail/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-mail/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\Mail\Protocol\Smtp\Auth;
use Laminas\Mail\Protocol\Smtp;
/**
* Performs PLAIN authentication
*/
class Plain extends Smtp
{
/**
* PLAIN username
*
* @var string
*/
protected $username;
/**
* PLAIN password
*
* @var string
*/
protected $password;
/**
* Constructor.
*
* @param string $host (Default: 127.0.0.1)
* @param int $port (Default: null)
* @param array $config Auth-specific parameters
*/
public function __construct($host = '127.0.0.1', $port = null, $config = null)
{
// Did we receive a configuration array?
$origConfig = $config;
if (is_array($host)) {
// Merge config array with principal array, if provided
if (is_array($config)) {
$config = array_replace_recursive($host, $config);
} else {
$config = $host;
}
}
if (is_array($config)) {
if (isset($config['username'])) {
$this->setUsername($config['username']);
}
if (isset($config['password'])) {
$this->setPassword($config['password']);
}
}
// Call parent with original arguments
parent::__construct($host, $port, $origConfig);
}
/**
* Perform PLAIN authentication with supplied credentials
*
*/
public function auth()
{
// Ensure AUTH has not already been initiated.
parent::auth();
$this->_send('AUTH PLAIN');
$this->_expect(334);
$this->_send(base64_encode("\0" . $this->getUsername() . "\0" . $this->getPassword()));
$this->_expect(235);
$this->auth = true;
}
/**
* Set value for username
*
* @param string $username
* @return Plain
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* @return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Set value for password
*
* @param string $password
* @return Plain
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* @return string
*/
public function getPassword()
{
return $this->password;
}
}

Some files were not shown because too many files have changed in this diff Show More